From f14e3775657768f930668c4404cc1496dca9b90c Mon Sep 17 00:00:00 2001 From: thesai <1021828630@qq.com> Date: Sun, 29 Sep 2024 09:31:21 +0800 Subject: [PATCH] =?UTF-8?q?[=E6=96=B0=E5=A2=9E]=E4=BB=A5=E7=BB=88=E7=AB=AF?= =?UTF-8?q?=E5=8F=8D=E5=90=91=E4=BF=A1=E5=8F=B7=E6=9C=BA=E5=91=BD=E5=90=8D?= =?UTF-8?q?=E7=9A=84=E4=BF=A1=E5=8F=B7=E6=9C=BA=E5=90=8C=E6=A0=B7=E4=B9=9F?= =?UTF-8?q?=E7=94=A8=E6=AD=A4=E4=BF=A1=E5=8F=B7=E6=9C=BA=E4=BD=9C=E4=B8=BA?= =?UTF-8?q?=E5=8A=9E=E7=90=86=E8=BF=9B=E8=B7=AF=E7=9A=84=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DraftMapCiDataGeneratorImpl.java | 4330 +++++++++-------- .../rtss/vo/map/MapCiGenerateConfig.java | 203 +- 2 files changed, 2344 insertions(+), 2189 deletions(-) diff --git a/src/main/java/club/joylink/rtss/services/draftData/DraftMapCiDataGeneratorImpl.java b/src/main/java/club/joylink/rtss/services/draftData/DraftMapCiDataGeneratorImpl.java index 5e6fdb6a6..a0dfbd5cd 100644 --- a/src/main/java/club/joylink/rtss/services/draftData/DraftMapCiDataGeneratorImpl.java +++ b/src/main/java/club/joylink/rtss/services/draftData/DraftMapCiDataGeneratorImpl.java @@ -5,7 +5,22 @@ import club.joylink.rtss.simulation.cbtc.build.SimulationBuilder; import club.joylink.rtss.simulation.cbtc.constant.SignalAspect; import club.joylink.rtss.simulation.cbtc.constant.SignalModel; import club.joylink.rtss.simulation.cbtc.data.CalculateService; -import club.joylink.rtss.simulation.cbtc.data.map.*; +import club.joylink.rtss.simulation.cbtc.data.map.AutoSignal; +import club.joylink.rtss.simulation.cbtc.data.map.Cycle; +import club.joylink.rtss.simulation.cbtc.data.map.DestinationCodeDefinition; +import club.joylink.rtss.simulation.cbtc.data.map.ESP; +import club.joylink.rtss.simulation.cbtc.data.map.MapElement; +import club.joylink.rtss.simulation.cbtc.data.map.PSD; +import club.joylink.rtss.simulation.cbtc.data.map.Route; +import club.joylink.rtss.simulation.cbtc.data.map.RouteFls; +import club.joylink.rtss.simulation.cbtc.data.map.RouteOverlap; +import club.joylink.rtss.simulation.cbtc.data.map.Section; +import club.joylink.rtss.simulation.cbtc.data.map.SectionPath; +import club.joylink.rtss.simulation.cbtc.data.map.Signal; +import club.joylink.rtss.simulation.cbtc.data.map.Stand; +import club.joylink.rtss.simulation.cbtc.data.map.Station; +import club.joylink.rtss.simulation.cbtc.data.map.Switch; +import club.joylink.rtss.simulation.cbtc.data.map.SwitchElement; import club.joylink.rtss.simulation.cbtc.data.support.RoutePath; import club.joylink.rtss.simulation.cbtc.exception.SimulationException; import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType; @@ -14,7 +29,28 @@ import club.joylink.rtss.vo.map.CiGenerateResultVO; import club.joylink.rtss.vo.map.MapCiGenerateConfig; import club.joylink.rtss.vo.map.MapRoutingSectionNewVO; import club.joylink.rtss.vo.map.MapVO; -import club.joylink.rtss.vo.map.logic.*; +import club.joylink.rtss.vo.map.logic.MapAutoReentryVO; +import club.joylink.rtss.vo.map.logic.MapAutoSignalNewVO; +import club.joylink.rtss.vo.map.logic.MapDestinationCodeDefinitionVO; +import club.joylink.rtss.vo.map.logic.MapOverlapVO; +import club.joylink.rtss.vo.map.logic.MapRouteFlankProtectionNewVO; +import club.joylink.rtss.vo.map.logic.MapRouteNewVO; +import club.joylink.rtss.vo.map.logic.MapRoutingDataVO; +import club.joylink.rtss.vo.map.logic.MapSignalApproachSectionVO; +import club.joylink.rtss.vo.map.logic.MapStationRunLevelVO; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Stack; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import java.util.stream.Collectors; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -23,2217 +59,2331 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; -import java.util.stream.Collectors; - @Slf4j @Service public class DraftMapCiDataGeneratorImpl implements DraftMapCiDataGenerator { - @Autowired - private DraftMapService draftMapService; + @Autowired + private DraftMapService draftMapService; - @Autowired - private DraftMapRouteService draftMapRouteService; + @Autowired + private DraftMapRouteService draftMapRouteService; - @Autowired - private RoutingGenerator routingGenerator; + @Autowired + private RoutingGenerator routingGenerator; - @Transactional - @Override - public CiGenerateResultVO generate(Long mapId) { - // 先校验地图基础数据 - MapVO mapVO = this.draftMapService.getDraftMapData(mapId); - SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildBasicMapData(mapVO); - BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), - String.format("地图基础数据有错误: %s", JsonUtils.writeValueAsString(buildResult.getErrMsgList()))); - MapCiGenerateConfig generateConfig = mapVO.getGraphDataNew().getGenerateConfig(); - Map deviceMap = buildResult.getDeviceMap(); - // 联锁关系数据生成 - CiGenerateResult result = this.generate(mapId, deviceMap, generateConfig); - if (!CollectionUtils.isEmpty(result.getErrMsgList())) { - for (String errMsg : result.getErrMsgList()) { - log.warn(String.format("联锁数据生成警告信息:[%s]", errMsg)); - } - } - // 转换数据 - // 信号机接近区段 - List approachSectionVOList = new ArrayList<>(); - for (Signal signal : result.getApproachList()) { - approachSectionVOList.add(MapSignalApproachSectionVO.fromBO(signal)); - } - // 进路 - List routeVOList = new ArrayList<>(); - for (Route route : result.getRouteList()) { - routeVOList.add(MapRouteNewVO.fromBO(route)); - } - // 延续保护 - List overlapVOList = new ArrayList<>(); - for (RouteOverlap routeOverlap : result.getOverlapList()) { - overlapVOList.add(MapOverlapVO.fromBO(routeOverlap)); - } - // 侧防 - List flsVOList = new ArrayList<>(); - for (RouteFls routeFls : result.getFlsList()) { - flsVOList.add(MapRouteFlankProtectionNewVO.fromBO(routeFls)); - } - // 自动进路 - List autoSignalNewVOList = new ArrayList<>(); - for (AutoSignal autoSignal : result.getAutoSignalList()) { - autoSignalNewVOList.add(MapAutoSignalNewVO.fromBO(autoSignal)); - } - // 自动折返 - List autoReentryVOList = new ArrayList<>(); - for (Cycle cycle : result.getCycleList()) { - autoReentryVOList.add(MapAutoReentryVO.fromBO(cycle)); - } - // 目的地码 - List destinationCodeDefinitionVOList = result.getDestinationCodeDefinitionList().stream() - .map(MapDestinationCodeDefinitionVO::fromBO).collect(Collectors.toList()); + @Transactional + @Override + public CiGenerateResultVO generate(Long mapId) { + // 先校验地图基础数据 + MapVO mapVO = this.draftMapService.getDraftMapData(mapId); + SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildBasicMapData( + mapVO); + BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), + String.format("地图基础数据有错误: %s", + JsonUtils.writeValueAsString(buildResult.getErrMsgList()))); + MapCiGenerateConfig generateConfig = mapVO.getGraphDataNew().getGenerateConfig(); + Map deviceMap = buildResult.getDeviceMap(); + // 联锁关系数据生成 + CiGenerateResult result = this.generate(mapId, deviceMap, generateConfig); + if (!CollectionUtils.isEmpty(result.getErrMsgList())) { + for (String errMsg : result.getErrMsgList()) { + log.warn(String.format("联锁数据生成警告信息:[%s]", errMsg)); + } + } + // 转换数据 + // 信号机接近区段 + List approachSectionVOList = new ArrayList<>(); + for (Signal signal : result.getApproachList()) { + approachSectionVOList.add(MapSignalApproachSectionVO.fromBO(signal)); + } + // 进路 + List routeVOList = new ArrayList<>(); + for (Route route : result.getRouteList()) { + routeVOList.add(MapRouteNewVO.fromBO(route)); + } + // 延续保护 + List overlapVOList = new ArrayList<>(); + for (RouteOverlap routeOverlap : result.getOverlapList()) { + overlapVOList.add(MapOverlapVO.fromBO(routeOverlap)); + } + // 侧防 + List flsVOList = new ArrayList<>(); + for (RouteFls routeFls : result.getFlsList()) { + flsVOList.add(MapRouteFlankProtectionNewVO.fromBO(routeFls)); + } + // 自动进路 + List autoSignalNewVOList = new ArrayList<>(); + for (AutoSignal autoSignal : result.getAutoSignalList()) { + autoSignalNewVOList.add(MapAutoSignalNewVO.fromBO(autoSignal)); + } + // 自动折返 + List autoReentryVOList = new ArrayList<>(); + for (Cycle cycle : result.getCycleList()) { + autoReentryVOList.add(MapAutoReentryVO.fromBO(cycle)); + } + // 目的地码 + List destinationCodeDefinitionVOList = result.getDestinationCodeDefinitionList() + .stream() + .map(MapDestinationCodeDefinitionVO::fromBO).collect(Collectors.toList()); - // 删除旧联锁数据,保存新联锁数据 - this.draftMapService.cleanAndSaveCiData(mapId, approachSectionVOList, - routeVOList, overlapVOList, flsVOList, autoSignalNewVOList, - autoReentryVOList, destinationCodeDefinitionVOList, result.getRoutingList()); + // 删除旧联锁数据,保存新联锁数据 + this.draftMapService.cleanAndSaveCiData(mapId, approachSectionVOList, + routeVOList, overlapVOList, flsVOList, autoSignalNewVOList, + autoReentryVOList, destinationCodeDefinitionVOList, result.getRoutingList()); - return result.convert2VO(); + return result.convert2VO(); + } + + @Transactional + @Override + public int generateDepot(Long mapId, String stationCode) { + // 先校验地图基础数据 + MapVO mapVO = this.draftMapService.getDraftMapData(mapId); + SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildBasicMapData( + mapVO); + BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), + String.format("地图基础数据有错误: %s", + JsonUtils.writeValueAsString(buildResult.getErrMsgList()))); + MapCiGenerateConfig generateConfig = mapVO.getGraphDataNew().getGenerateConfig(); + Map deviceMap = buildResult.getDeviceMap(); + // 处理旧数据 + List routeList = this.draftMapRouteService.queryAllRoutes(mapId); + List deletingList = new ArrayList<>(); + Integer routeCodeIndex = routeList.stream().peek(mapRouteNewVO -> { + if (mapRouteNewVO.getStationCode().equals(stationCode)) { + deletingList.add(mapRouteNewVO.getId()); + } + }).map(MapRouteNewVO::getCode) + .map(c -> Integer.parseInt(c.substring(CodeGenerator.Prefix_Route.length()))) + .max(Integer::compareTo).orElse(0); + // 联锁关系数据生成 + List errorList = new ArrayList<>(); + List generatedRouteList = new ArrayList<>(); + CodeGenerator routeCodeGenerator = CodeGenerator.getRouteCodeGenerator(routeCodeIndex); + // 获取所有信号机 + List signalList = deviceMap.values().stream() + .filter(mapElement -> mapElement.getDeviceType().equals(MapElement.DeviceType.SIGNAL)) + .map(mapElement -> ((Signal) mapElement)) + .filter(signal -> signal.getInterlockStation().getCode().equals(stationCode)) + .collect(Collectors.toList()); + log.info(String.format("共有信号机[%s]个", signalList.size())); + signalList.sort((signal1, signal2) -> { + String s1 = signal1.getShowName(); + String s2 = signal2.getShowName(); + return s1.length() != s2.length() ? s1.length() - s2.length() : s1.compareTo(s2); + }); + for (Signal signal : signalList) { + // 列车兼调车信号机、调车信号机 + if (signal.getType().equals(Signal.SignalType.SHUNTING2)) { + signal.setType(Signal.SignalType.SHUNTING); + generatedRouteList.addAll( + this.generateRouteDepot(signal, routeCodeGenerator, generateConfig, errorList)); + signal.setType(Signal.SignalType.SHUNTING2); + generatedRouteList.addAll( + this.generateRouteDepot(signal, routeCodeGenerator, generateConfig, errorList)); + } else if (signal.getType().equals(Signal.SignalType.SHUNTING)) { + generatedRouteList.addAll( + this.generateRouteDepot(signal, routeCodeGenerator, generateConfig, errorList)); + } else if (signal.getType().equals(Signal.SignalType.INBOUND)) { + generatedRouteList.addAll( + this.generateRouteDepot(signal, routeCodeGenerator, generateConfig, errorList)); + } + } + log.info(String.format("生成一般进路[%s]条", generatedRouteList.size())); + // 进路敌对关系构建 + this.buildRouteConflict(generatedRouteList); + + if (!CollectionUtils.isEmpty(errorList)) { + for (String errMsg : errorList) { + log.warn(String.format("联锁数据生成警告信息:[%s]", errMsg)); + } + } + // 删除旧数据,保存新数据 + this.draftMapRouteService.deleteRoutes(deletingList); + this.draftMapRouteService.createRoutes(mapId, generatedRouteList.stream() + .map(MapRouteNewVO::fromBO).collect(Collectors.toList())); + return generatedRouteList.size(); + } + + /** + * 唯一编码生成器 + */ + public static class CodeGenerator { + + public static final String Prefix_Route = "Route"; + public static final String Prefix_Overlap = "Overlap"; + public static final String Prefix_Fls = "Fls"; + public static final String Prefix_Routing = "Routing"; + public static final String Prefix_AutoSignal = "AutoSignal"; + public static final String Prefix_Cycle = "Cycle"; + public static final String Prefix_Overrun = "Overrun"; + + private AtomicInteger sn; + private String prefix; + + private CodeGenerator(String prefix, int initVal) { + this.prefix = prefix; + this.sn = new AtomicInteger(initVal); } - @Transactional - @Override - public int generateDepot(Long mapId, String stationCode) { - // 先校验地图基础数据 - MapVO mapVO = this.draftMapService.getDraftMapData(mapId); - SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildBasicMapData(mapVO); - BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), - String.format("地图基础数据有错误: %s", JsonUtils.writeValueAsString(buildResult.getErrMsgList()))); - MapCiGenerateConfig generateConfig = mapVO.getGraphDataNew().getGenerateConfig(); - Map deviceMap = buildResult.getDeviceMap(); - // 处理旧数据 - List routeList = this.draftMapRouteService.queryAllRoutes(mapId); - List deletingList = new ArrayList<>(); - Integer routeCodeIndex = routeList.stream().peek(mapRouteNewVO -> { - if (mapRouteNewVO.getStationCode().equals(stationCode)) { - deletingList.add(mapRouteNewVO.getId()); - } - }).map(MapRouteNewVO::getCode) - .map(c -> Integer.parseInt(c.substring(CodeGenerator.Prefix_Route.length()))) - .max(Integer::compareTo).orElse(0); - // 联锁关系数据生成 - List errorList = new ArrayList<>(); - List generatedRouteList = new ArrayList<>(); - CodeGenerator routeCodeGenerator = CodeGenerator.getRouteCodeGenerator(routeCodeIndex); - // 获取所有信号机 - List signalList = deviceMap.values().stream() - .filter(mapElement -> mapElement.getDeviceType().equals(MapElement.DeviceType.SIGNAL)) - .map(mapElement -> ((Signal) mapElement)) - .filter(signal -> signal.getInterlockStation().getCode().equals(stationCode)) - .collect(Collectors.toList()); - log.info(String.format("共有信号机[%s]个", signalList.size())); - signalList.sort((signal1, signal2) -> { - String s1 = signal1.getShowName(); - String s2 = signal2.getShowName(); - return s1.length() != s2.length() ? s1.length() - s2.length() : s1.compareTo(s2); - }); - for (Signal signal : signalList) { - // 列车兼调车信号机、调车信号机 - if (signal.getType().equals(Signal.SignalType.SHUNTING2)) { - signal.setType(Signal.SignalType.SHUNTING); - generatedRouteList.addAll(this.generateRouteDepot(signal, routeCodeGenerator, generateConfig, errorList)); - signal.setType(Signal.SignalType.SHUNTING2); - generatedRouteList.addAll(this.generateRouteDepot(signal, routeCodeGenerator, generateConfig, errorList)); - } else if (signal.getType().equals(Signal.SignalType.SHUNTING)) { - generatedRouteList.addAll(this.generateRouteDepot(signal, routeCodeGenerator, generateConfig, errorList)); - } else if (signal.getType().equals(Signal.SignalType.INBOUND)) { - generatedRouteList.addAll(this.generateRouteDepot(signal, routeCodeGenerator, generateConfig, errorList)); - } - } - log.info(String.format("生成一般进路[%s]条", generatedRouteList.size())); - // 进路敌对关系构建 - this.buildRouteConflict(generatedRouteList); - - if (!CollectionUtils.isEmpty(errorList)) { - for (String errMsg : errorList) { - log.warn(String.format("联锁数据生成警告信息:[%s]", errMsg)); - } - } - // 删除旧数据,保存新数据 - this.draftMapRouteService.deleteRoutes(deletingList); - this.draftMapRouteService.createRoutes(mapId, generatedRouteList.stream() - .map(MapRouteNewVO::fromBO).collect(Collectors.toList())); - return generatedRouteList.size(); + public static CodeGenerator getRouteCodeGenerator(int initVal) { + return new CodeGenerator(Prefix_Route, initVal); } - /** - * 唯一编码生成器 - */ - public static class CodeGenerator { - public static final String Prefix_Route = "Route"; - public static final String Prefix_Overlap = "Overlap"; - public static final String Prefix_Fls = "Fls"; - public static final String Prefix_Routing = "Routing"; - public static final String Prefix_AutoSignal = "AutoSignal"; - public static final String Prefix_Cycle = "Cycle"; - public static final String Prefix_Overrun = "Overrun"; - - private AtomicInteger sn; - private String prefix; - - private CodeGenerator(String prefix, int initVal) { - this.prefix = prefix; - this.sn = new AtomicInteger(initVal); - } - - public static CodeGenerator getRouteCodeGenerator(int initVal) { - return new CodeGenerator(Prefix_Route, initVal); - } - - public static CodeGenerator getOverlapCodeGenerator(int initVal) { - return new CodeGenerator(Prefix_Overlap, initVal); - } - - public static CodeGenerator getFlsCodeGenerator(int initVal) { - return new CodeGenerator(Prefix_Fls, initVal); - } - - public static CodeGenerator getRoutingCodeGenerator(int initVal) { - return new CodeGenerator(Prefix_Routing, initVal); - } - - public static CodeGenerator getAutoSignalCodeGenerator(int initVal) { - return new CodeGenerator(Prefix_AutoSignal, initVal); - } - - public static CodeGenerator getCycleCodeGenerator(int initVal) { - return new CodeGenerator(Prefix_Cycle, initVal); - } - - public static CodeGenerator getOverrunCodeGenerator(int initVal) { - return new CodeGenerator(Prefix_Overrun, initVal); - } - - public String next() { - return this.prefix + this.sn.incrementAndGet(); - } + public static CodeGenerator getOverlapCodeGenerator(int initVal) { + return new CodeGenerator(Prefix_Overlap, initVal); } - @Getter - private class CiGenerateResult { - private List errMsgList; + public static CodeGenerator getFlsCodeGenerator(int initVal) { + return new CodeGenerator(Prefix_Fls, initVal); + } - private List approachList; - private List autoSignalList; - private List routeList; - private List overlapList; - private List flsList; - private List cycleList; - private List destinationCodeDefinitionList; + public static CodeGenerator getRoutingCodeGenerator(int initVal) { + return new CodeGenerator(Prefix_Routing, initVal); + } - List routingList; + public static CodeGenerator getAutoSignalCodeGenerator(int initVal) { + return new CodeGenerator(Prefix_AutoSignal, initVal); + } - public CiGenerateResult(List errMsgList, List approachList, List autoSignalList, List routeList, - List overlapList, List flsList, List generateCycleList, List routingList, - List destinationCodeDefinitionList) { - this.errMsgList = errMsgList; - this.approachList = approachList; - this.autoSignalList = autoSignalList; - this.routeList = routeList; - this.overlapList = overlapList; - this.flsList = flsList; - this.cycleList = generateCycleList; - this.destinationCodeDefinitionList = destinationCodeDefinitionList; - this.routingList = routingList; - log.info(String.format("生成信号机接近区段数据[%s]条", approachList.size())); - log.info(String.format("生成进路数据总计[%s]条", routeList.size())); - log.info(String.format("生成延续保护数据[%s]条", overlapList.size())); - log.info(String.format("生成侧防数据[%s]条", flsList.size())); - log.info(String.format("生成自动信号数据[%s]条", autoSignalList.size())); - log.info(String.format("生成自动折返数据[%s]条", generateCycleList.size())); - log.info(String.format("生成交路数据[%s]条", routingList.size())); - } + public static CodeGenerator getCycleCodeGenerator(int initVal) { + return new CodeGenerator(Prefix_Cycle, initVal); + } - public CiGenerateResultVO convert2VO() { - CiGenerateResultVO resultVO = new CiGenerateResultVO(); - resultVO.setRouteCount(this.routeList.size()); - resultVO.setOverlapCount(this.overlapList.size()); - resultVO.setCycleCount(this.cycleList.size()); - resultVO.setAutoSignalCount(this.autoSignalList.size()); - resultVO.setRoutingCount(this.routingList.size()); + public static CodeGenerator getOverrunCodeGenerator(int initVal) { + return new CodeGenerator(Prefix_Overrun, initVal); + } + + public String next() { + return this.prefix + this.sn.incrementAndGet(); + } + } + + @Getter + private class CiGenerateResult { + + private List errMsgList; + + private List approachList; + private List autoSignalList; + private List routeList; + private List overlapList; + private List flsList; + private List cycleList; + private List destinationCodeDefinitionList; + + List routingList; + + public CiGenerateResult(List errMsgList, List approachList, + List autoSignalList, List routeList, + List overlapList, List flsList, List generateCycleList, + List routingList, + List destinationCodeDefinitionList) { + this.errMsgList = errMsgList; + this.approachList = approachList; + this.autoSignalList = autoSignalList; + this.routeList = routeList; + this.overlapList = overlapList; + this.flsList = flsList; + this.cycleList = generateCycleList; + this.destinationCodeDefinitionList = destinationCodeDefinitionList; + this.routingList = routingList; + log.info(String.format("生成信号机接近区段数据[%s]条", approachList.size())); + log.info(String.format("生成进路数据总计[%s]条", routeList.size())); + log.info(String.format("生成延续保护数据[%s]条", overlapList.size())); + log.info(String.format("生成侧防数据[%s]条", flsList.size())); + log.info(String.format("生成自动信号数据[%s]条", autoSignalList.size())); + log.info(String.format("生成自动折返数据[%s]条", generateCycleList.size())); + log.info(String.format("生成交路数据[%s]条", routingList.size())); + } + + public CiGenerateResultVO convert2VO() { + CiGenerateResultVO resultVO = new CiGenerateResultVO(); + resultVO.setRouteCount(this.routeList.size()); + resultVO.setOverlapCount(this.overlapList.size()); + resultVO.setCycleCount(this.cycleList.size()); + resultVO.setAutoSignalCount(this.autoSignalList.size()); + resultVO.setRoutingCount(this.routingList.size()); // resultVO.setStationRunlevelCount(this.stationRunLevelList.size()); // resultVO.setStationParkTimeCount(this.parkTimeList.size()); - resultVO.setDestinationCodeDefinitionCount(this.destinationCodeDefinitionList.size()); - return resultVO; - } + resultVO.setDestinationCodeDefinitionCount(this.destinationCodeDefinitionList.size()); + return resultVO; } + } - private CiGenerateResult generate(Long mapId, Map deviceMap, MapCiGenerateConfig config) { - List errorList = new ArrayList<>(); - List autoSignalList = new ArrayList<>(); - List generatedRouteList = new ArrayList<>(); - CodeGenerator autoSignalGenerator = CodeGenerator.getAutoSignalCodeGenerator(0); - CodeGenerator routeCodeGenerator = CodeGenerator.getRouteCodeGenerator(0); - CodeGenerator overlapCodeGenerator = CodeGenerator.getOverlapCodeGenerator(0); - CodeGenerator cycleCodeGenerator = CodeGenerator.getCycleCodeGenerator(0); - // 获取所有信号机 - List signalList = deviceMap.values().stream() - .filter(mapElement -> mapElement.getDeviceType().equals(MapElement.DeviceType.SIGNAL)) - .map(mapElement -> ((Signal) mapElement)) - .filter(signal -> !signal.getInterlockStation().isDepot()) - .collect(Collectors.toList()); - // 获取所有道岔 - List switchList = deviceMap.values().stream() - .filter(mapElement -> mapElement.getDeviceType().equals(MapElement.DeviceType.SWITCH)) - .map(mapElement -> ((Switch) mapElement)) - .collect(Collectors.toList()); - // 获取所有区段 - List
sectionList = deviceMap.values().stream() - .filter(mapElement -> MapElement.DeviceType.SECTION.equals(mapElement.getDeviceType())) - .map(mapElement -> (Section) mapElement) - .collect(Collectors.toList()); - // 所有车站 - List stationList = deviceMap.values().stream() - .filter(mapElement -> MapElement.DeviceType.STATION.equals(mapElement.getDeviceType())) - .map(mapElement -> (Station) mapElement) - .sorted(Comparator.comparingInt(Station::getSn)) - .collect(Collectors.toList()); + private CiGenerateResult generate(Long mapId, Map deviceMap, + MapCiGenerateConfig config) { + List errorList = new ArrayList<>(); + List autoSignalList = new ArrayList<>(); + List generatedRouteList = new ArrayList<>(); + CodeGenerator autoSignalGenerator = CodeGenerator.getAutoSignalCodeGenerator(0); + CodeGenerator routeCodeGenerator = CodeGenerator.getRouteCodeGenerator(0); + CodeGenerator overlapCodeGenerator = CodeGenerator.getOverlapCodeGenerator(0); + CodeGenerator cycleCodeGenerator = CodeGenerator.getCycleCodeGenerator(0); + // 获取所有信号机 + List signalList = deviceMap.values().stream() + .filter(mapElement -> mapElement.getDeviceType().equals(MapElement.DeviceType.SIGNAL)) + .map(mapElement -> ((Signal) mapElement)) + .filter(signal -> !signal.getInterlockStation().isDepot()) + .collect(Collectors.toList()); + // 获取所有道岔 + List switchList = deviceMap.values().stream() + .filter(mapElement -> mapElement.getDeviceType().equals(MapElement.DeviceType.SWITCH)) + .map(mapElement -> ((Switch) mapElement)) + .collect(Collectors.toList()); + // 获取所有区段 + List
sectionList = deviceMap.values().stream() + .filter(mapElement -> MapElement.DeviceType.SECTION.equals(mapElement.getDeviceType())) + .map(mapElement -> (Section) mapElement) + .collect(Collectors.toList()); + // 所有车站 + List stationList = deviceMap.values().stream() + .filter(mapElement -> MapElement.DeviceType.STATION.equals(mapElement.getDeviceType())) + .map(mapElement -> (Station) mapElement) + .sorted(Comparator.comparingInt(Station::getSn)) + .collect(Collectors.toList()); - Map> overlapMap = new HashMap<>(); - List approachList = new ArrayList<>(); - log.info(String.format("共有信号机[%s]个", signalList.size())); - for (Signal signal : signalList) { - if (signal.isBlockingSignal() || signal.isTransmissionSignal()) { - // 阻挡信号机永远红灯,不生成联锁 - // 传输信号机不需要生成联锁 - continue; - } - // 信号机接近区段构建 - this.generateApproachSection(signal, config); - approachList.add(signal); - if (signal.isPassingSignal() && !config.isRailway()) { - // 通过信号机,生成自动信号 - AutoSignal autoSignal = this.generateAutoSignal(signal, autoSignalGenerator, errorList); - if (Objects.nonNull(autoSignal)) { - autoSignalList.add(autoSignal); - } - } else if (signal.isProtectionSignal()) { - // 防护信号机,生成进路 - if (config.isLikeHa1()) { - generatedRouteList.addAll(this.generateRouteLikeHa1(signal, routeCodeGenerator, overlapMap, - overlapCodeGenerator, config, errorList)); - } else { - generatedRouteList.addAll(this.generateRoute(signal, - routeCodeGenerator, overlapMap, overlapCodeGenerator, config, errorList)); - } - } + Map> overlapMap = new HashMap<>(); + List approachList = new ArrayList<>(); + log.info(String.format("共有信号机[%s]个", signalList.size())); + for (Signal signal : signalList) { + if (signal.isBlockingSignal() || signal.isTransmissionSignal()) { + // 阻挡信号机永远红灯,不生成联锁 + // 传输信号机不需要生成联锁 + continue; + } + // 信号机接近区段构建 + this.generateApproachSection(signal, config); + approachList.add(signal); + if (signal.isPassingSignal() && !config.isRailway()) { + // 通过信号机,生成自动信号 + AutoSignal autoSignal = this.generateAutoSignal(signal, autoSignalGenerator, errorList); + if (Objects.nonNull(autoSignal)) { + autoSignalList.add(autoSignal); } - log.info(String.format("生成一般进路[%s]条", generatedRouteList.size())); + } else if (signal.isProtectionSignal()) { + // 防护信号机,生成进路 if (config.isLikeHa1()) { - log.info(String.format("ATP进路[%s]条。地面信号[%s]条。引导信号[%s]条", - generatedRouteList.stream().filter(route -> route.isAtp()).count(), - generatedRouteList.stream().filter(route -> route.isGround()).count(), - generatedRouteList.stream().filter(route -> route.isGuide()).count())); - } - // 生成侧防,构建进路侧防关系 - List flsList = new ArrayList<>(); - if (config.isGenerateFls()) { - Map flsMap = this.generateFls(switchList); - flsList = new ArrayList<>(flsMap.values()); - for (Route route : generatedRouteList) { - // 进路道岔侧防 - List routeFlsList = new ArrayList<>(); - if (route.getSwitchList() != null) { - for (SwitchElement switchElement : route.getSwitchList()) { - String name = RouteFls.buildName(switchElement); - RouteFls routeFls = flsMap.get(name); - if (routeFls != null) { - routeFlsList.add(routeFls); - } - } - route.setFlsList(routeFlsList); - } - // 进路延续保护道岔侧防 - RouteOverlap overlap = route.getOverlap(); - if (overlap != null) { - List pathList = overlap.getPathList(); - for (SectionPath sectionPath : pathList) { - List overlapFlsList = new ArrayList<>(); - List overlapSwitchList = sectionPath.getSwitchList(); - if (overlapSwitchList != null) { - for (SwitchElement switchElement : overlapSwitchList) { - RouteFls routeFls = flsMap.get(RouteFls.buildName(switchElement)); - if (routeFls != null) { - overlapFlsList.add(routeFls); - } - } - } - sectionPath.setFlsList(overlapFlsList); - } - } - } - } - // 根据配置生成折返进路 - if (config.isGenerateTbRoute()) { - List tbRouteList = this.generateTurnBackRoute(generatedRouteList, routeCodeGenerator, config); - generatedRouteList.addAll(tbRouteList); - } - // 清除不需要的基本进路 - this.deleteBaseRoute(signalList, generatedRouteList); - // 进路敌对关系构建 - this.buildRouteConflict(generatedRouteList); - // 自动信号敌对进路条件构建 - this.buildAutoSignalRouteConflict(autoSignalList, generatedRouteList); - - // 根据配置生成自动折返 - List generateCycleList = new ArrayList<>(); - if (config.isGenerateCycle()) { - List tbSignalList = signalList.stream() - .filter(signal -> !signal.isVirtual() && signal.isTurnBack()) - .collect(Collectors.toList()); - generateCycleList = this.generateCycle(tbSignalList, - generatedRouteList, cycleCodeGenerator, config, errorList); - } - - List generatedOverlapList = new ArrayList<>(); - for (List overlapList : overlapMap.values()) { - generatedOverlapList.addAll(overlapList); - } - - // 处理进路、自动信号存入对应信号机 - Map> signalRoutesMap = this.buildSignalRouteMap(generatedRouteList); - signalRoutesMap.forEach((code, routeList) -> { - ((Signal) deviceMap.get(code)).setRouteList(routeList); - }); - for (AutoSignal autoSignal : autoSignalList) { - autoSignal.getSignal().setAutoSignal(autoSignal); - } - - // 生成交路数据 - List generateRoutingList = this.routingGenerator.generateAllRouting(deviceMap, errorList); - - //目的地码生成 - List destinationCodeDefinitionList - = generateDestinationCodeDefinition(config, sectionList, stationList); - - return new CiGenerateResult(errorList, approachList, - autoSignalList, generatedRouteList, generatedOverlapList, flsList, - generateCycleList, generateRoutingList, destinationCodeDefinitionList); - } - - private List generateDestinationCodeDefinition(MapCiGenerateConfig config, List
sectionList, List stationList) { - List destinationCodeDefinitionList = new ArrayList<>(); - if (config.isGenerateDestination()) { - String code = null; - DestinationCodeDefinition.Type type = null; - String description = null; - Section startSection = null; - Section section = null; - Boolean right = null; - List
necessarySections = null; - Station leftStation = null; - Boolean leftFrontTurnBack = null; - Station rightStation = null; - Boolean rightFrontTurnBack = null; - List routes = null; - - int codeNum = 1; - for (int i = 0; i < stationList.size(); i++) { - leftStation = stationList.get(i); - if (CollectionUtils.isEmpty(leftStation.getTurnBackList())) //没有折返轨的略过 - continue; - if (i == stationList.size() - 1) - break; - - List
leftTbSections = queryAfterTurnBackList(leftStation, false); - leftTbSections.addAll(queryFrontTurnBackList(stationList, leftStation, false)); - for (Section startTbSection : leftTbSections) { - for (int j = stationList.size() - 1; j >= 0; j--) { - rightStation = stationList.get(j); - if (leftStation.equals(rightStation)) { - break; - } - List
rightTbSections = queryAfterTurnBackList(rightStation, true); - rightTbSections.addAll(queryFrontTurnBackList(stationList, rightStation, true)); - for (Section endTbSection : rightTbSections) { - code = String.format("%03d", codeNum++); - type = DestinationCodeDefinition.Type.NORMAL_OPERATION; - description = String.format("%s-%s", leftStation.getName(), rightStation.getName()); - necessarySections = List.of(startTbSection, endTbSection); - leftFrontTurnBack = startTbSection.isNormalStandTrack(); - rightFrontTurnBack = endTbSection.isNormalStandTrack(); - destinationCodeDefinitionList.add( - new DestinationCodeDefinition(code, type, description, null, null, right, necessarySections, - leftStation, leftFrontTurnBack, rightStation, rightFrontTurnBack, null, null, null) - ); - } - } - } - } + generatedRouteList.addAll( + this.generateRouteLikeHa1(signal, routeCodeGenerator, overlapMap, + overlapCodeGenerator, config, errorList)); } else { - if (!CollectionUtils.isEmpty(sectionList)) { - for (Section section : sectionList) { - String destinationCode = section.getDestinationCode(); - if (!StringUtils.hasText(destinationCode)) { - continue; - } - destinationCodeDefinitionList.add(new DestinationCodeDefinition(destinationCode, DestinationCodeDefinition.Type.OTHER, section)); + generatedRouteList.addAll(this.generateRoute(signal, + routeCodeGenerator, overlapMap, overlapCodeGenerator, config, errorList)); + } + } + } + log.info(String.format("生成一般进路[%s]条", generatedRouteList.size())); + if (config.isLikeHa1()) { + log.info(String.format("ATP进路[%s]条。地面信号[%s]条。引导信号[%s]条", + generatedRouteList.stream().filter(route -> route.isAtp()).count(), + generatedRouteList.stream().filter(route -> route.isGround()).count(), + generatedRouteList.stream().filter(route -> route.isGuide()).count())); + } + // 生成侧防,构建进路侧防关系 + List flsList = new ArrayList<>(); + if (config.isGenerateFls()) { + Map flsMap = this.generateFls(switchList); + flsList = new ArrayList<>(flsMap.values()); + for (Route route : generatedRouteList) { + // 进路道岔侧防 + List routeFlsList = new ArrayList<>(); + if (route.getSwitchList() != null) { + for (SwitchElement switchElement : route.getSwitchList()) { + String name = RouteFls.buildName(switchElement); + RouteFls routeFls = flsMap.get(name); + if (routeFls != null) { + routeFlsList.add(routeFls); + } + } + route.setFlsList(routeFlsList); + } + // 进路延续保护道岔侧防 + RouteOverlap overlap = route.getOverlap(); + if (overlap != null) { + List pathList = overlap.getPathList(); + for (SectionPath sectionPath : pathList) { + List overlapFlsList = new ArrayList<>(); + List overlapSwitchList = sectionPath.getSwitchList(); + if (overlapSwitchList != null) { + for (SwitchElement switchElement : overlapSwitchList) { + RouteFls routeFls = flsMap.get(RouteFls.buildName(switchElement)); + if (routeFls != null) { + overlapFlsList.add(routeFls); } + } } + sectionPath.setFlsList(overlapFlsList); + } } - return destinationCodeDefinitionList; + } + } + // 根据配置生成折返进路 + if (config.isGenerateTbRoute()) { + List tbRouteList = this.generateTurnBackRoute(generatedRouteList, routeCodeGenerator, + config); + generatedRouteList.addAll(tbRouteList); + } + // 清除不需要的基本进路 + this.deleteBaseRoute(signalList, generatedRouteList); + // 进路敌对关系构建 + this.buildRouteConflict(generatedRouteList); + // 自动信号敌对进路条件构建 + this.buildAutoSignalRouteConflict(autoSignalList, generatedRouteList); + + // 根据配置生成自动折返 + List generateCycleList = new ArrayList<>(); + if (config.isGenerateCycle()) { + List tbSignalList = signalList.stream() + .filter(signal -> !signal.isVirtual() && signal.isTurnBack()) + .collect(Collectors.toList()); + generateCycleList = this.generateCycle(tbSignalList, + generatedRouteList, cycleCodeGenerator, config, errorList); } - /** - * 筛选站后折返轨(优先右行站台折返) - * - * @param stations 所有车站 - * @param right 是否是右端车站 - */ - private List
queryFrontTurnBackList(List stations, Station station, boolean right) { - List
turnBackList = station.getTurnBackList(); - if (CollectionUtils.isEmpty(turnBackList) || CollectionUtils.isEmpty(station.getAllNormalStands())) { - return new ArrayList<>(); - } - int sn; - if (right) { - sn = station.getSn() - 1; - } else { - sn = station.getSn() + 1; - } - Station adjacentStation = stations.stream().filter(sta -> sta.getSn() == sn).findAny().get(); - if (CollectionUtils.isEmpty(adjacentStation.getAllNormalStands())) { - return new ArrayList<>(); - } - Section leftStandTrack = station.getNormalStand(false).get(0).getSection(); - Section rightStandTrack = station.getNormalStand(true).get(0).getSection(); - Section adjacentLeftStandTrack = adjacentStation.getNormalStand(false).get(0).getSection(); - Section adjacentRightStandTrack = adjacentStation.getNormalStand(true).get(0).getSection(); - List
tbSections = new ArrayList<>(); - if (right) { - if (rightStandTrack.isTurnBackTrack() - && !CollectionUtils.isEmpty(CalculateService.queryRoutePathsOnDirection(rightStandTrack, adjacentLeftStandTrack, false, 10))) { - tbSections.add(rightStandTrack); - } - if (leftStandTrack.isTurnBackTrack() - && !CollectionUtils.isEmpty(CalculateService.queryRoutePathsOnDirection(adjacentRightStandTrack, leftStandTrack, true, 10))) { - tbSections.add(leftStandTrack); - } - } else { - if (rightStandTrack.isTurnBackTrack() - && !CollectionUtils.isEmpty(CalculateService.queryRoutePathsOnDirection(adjacentLeftStandTrack, rightStandTrack, false, 10))) { - tbSections.add(rightStandTrack); - } - if (leftStandTrack.isTurnBackTrack() - && !CollectionUtils.isEmpty(CalculateService.queryRoutePathsOnDirection(leftStandTrack, adjacentRightStandTrack, true, 10))) { - tbSections.add(leftStandTrack); - } - } - return tbSections; + List generatedOverlapList = new ArrayList<>(); + for (List overlapList : overlapMap.values()) { + generatedOverlapList.addAll(overlapList); } - /** - * 筛选站前折返轨 - * - * @param right 是否是右端车站 - */ - private List
queryAfterTurnBackList(Station station, boolean right) { - List
turnBackList = station.getTurnBackList(); - if (CollectionUtils.isEmpty(turnBackList)) { - return new ArrayList<>(); - } - Section standTrack = station.getNormalStand(right).get(0).getSection(); - return turnBackList.stream().filter(section -> !section.isNormalStandTrack()) - .filter(section -> !CollectionUtils.isEmpty(CalculateService.queryRoutePathsOnDirection(standTrack, section, right, 10))) - .collect(Collectors.toList()); + // 处理进路、自动信号存入对应信号机 + Map> signalRoutesMap = this.buildSignalRouteMap(generatedRouteList); + signalRoutesMap.forEach((code, routeList) -> { + ((Signal) deviceMap.get(code)).setRouteList(routeList); + }); + for (AutoSignal autoSignal : autoSignalList) { + autoSignal.getSignal().setAutoSignal(autoSignal); } - private Collection generateRouteLikeHa1(Signal signal, CodeGenerator routeCodeGenerator, - Map> overlapMap, - CodeGenerator overlapCodeGenerator, - MapCiGenerateConfig config, List errorList) { - // 生成ATP信号 - List routeList = new ArrayList<>(); - List atpRouteList = this.generateRoute(signal, routeCodeGenerator, overlapMap, overlapCodeGenerator, config, errorList); - if (!CollectionUtils.isEmpty(atpRouteList)) { - for (Route route : atpRouteList) { - route.setAtp(true); - if ((signal.isRight() && signal.getSection().isRightLine()) - || (!signal.isRight() && signal.getSection().isLeftLine())) { - route.setArs(true); - } - routeList.add(route); + // 生成交路数据 + List generateRoutingList = this.routingGenerator.generateAllRouting(deviceMap, + errorList); + + //目的地码生成 + List destinationCodeDefinitionList + = generateDestinationCodeDefinition(config, sectionList, stationList); + + return new CiGenerateResult(errorList, approachList, + autoSignalList, generatedRouteList, generatedOverlapList, flsList, + generateCycleList, generateRoutingList, destinationCodeDefinitionList); + } + + private List generateDestinationCodeDefinition( + MapCiGenerateConfig config, List
sectionList, List stationList) { + List destinationCodeDefinitionList = new ArrayList<>(); + if (config.isGenerateDestination()) { + String code = null; + DestinationCodeDefinition.Type type = null; + String description = null; + Section startSection = null; + Section section = null; + Boolean right = null; + List
necessarySections = null; + Station leftStation = null; + Boolean leftFrontTurnBack = null; + Station rightStation = null; + Boolean rightFrontTurnBack = null; + List routes = null; + + int codeNum = 1; + for (int i = 0; i < stationList.size(); i++) { + leftStation = stationList.get(i); + if (CollectionUtils.isEmpty(leftStation.getTurnBackList())) //没有折返轨的略过 + { + continue; + } + if (i == stationList.size() - 1) { + break; + } + + List
leftTbSections = queryAfterTurnBackList(leftStation, false); + leftTbSections.addAll(queryFrontTurnBackList(stationList, leftStation, false)); + for (Section startTbSection : leftTbSections) { + for (int j = stationList.size() - 1; j >= 0; j--) { + rightStation = stationList.get(j); + if (leftStation.equals(rightStation)) { + break; } - } - // 生成地面信号 - List groundRouteList = this.generateGroundRoute(signal, routeCodeGenerator, overlapMap, overlapCodeGenerator, config, errorList); - if (!CollectionUtils.isEmpty(groundRouteList)) { - for (Route ground : groundRouteList) { - ground.setGround(true); - ground.setArs(false); - routeList.add(ground); + List
rightTbSections = queryAfterTurnBackList(rightStation, true); + rightTbSections.addAll(queryFrontTurnBackList(stationList, rightStation, true)); + for (Section endTbSection : rightTbSections) { + code = String.format("%03d", codeNum++); + type = DestinationCodeDefinition.Type.NORMAL_OPERATION; + description = String.format("%s-%s", leftStation.getName(), rightStation.getName()); + necessarySections = List.of(startTbSection, endTbSection); + leftFrontTurnBack = startTbSection.isNormalStandTrack(); + rightFrontTurnBack = endTbSection.isNormalStandTrack(); + destinationCodeDefinitionList.add( + new DestinationCodeDefinition(code, type, description, null, null, right, + necessarySections, + leftStation, leftFrontTurnBack, rightStation, rightFrontTurnBack, null, null, + null) + ); } + } } - // 生成引导信号 - if (!CollectionUtils.isEmpty(groundRouteList)) { - for (Route route : groundRouteList) { - Route guide = this.buildGuideRouteFromGroundRoute(route, routeCodeGenerator, config.isRouteInterlockDoNotIncludeStandHoldTrain()); - routeList.add(guide); - } - } - return routeList; - } - - private Route buildGuideRouteFromGroundRoute(Route route, CodeGenerator routeCodeGenerator, boolean noStandHold) { - Route clone = new Route(routeCodeGenerator.next(), route.getName()); - clone.setArs(false); - clone.setGuide(true); - clone.setInterlockStation(route.getInterlockStation()); - clone.setStart(route.getStart()); - clone.setDestination(route.getDestination()); - clone.setAspect(route.getAspect()); - clone.setSectionList(route.getSectionList()); - clone.setSwitchList(route.getSwitchList()); - clone.setPsdList(route.getPsdList()); - clone.setEspList(route.getEspList()); - if (!noStandHold) { - clone.setStandHoldList(route.getStandHoldList()); - } - clone.setDestinationButtonSignal(route.getDestinationButtonSignal()); - return clone; - } - - private List generateGroundRoute(Signal signal, CodeGenerator routeCodeGenerator, - Map> overlapMap, - CodeGenerator overlapCodeGenerator, - MapCiGenerateConfig config, List errorList) { - if (signal.isVirtual()) { // 如果是虚拟信号机,返回 - return new ArrayList<>(); - } - boolean right = signal.isRight(); - Section startSection = signal.getSection().getSectionOf(right); - List routePathList = new ArrayList<>(); - getRoutePathOf(signal, startSection, true, - new SectionPath(right), routePathList, config, errorList); - List routeList = this.buildRouteFromPath(signal, routeCodeGenerator, routePathList, overlapMap, - overlapCodeGenerator, config, errorList); - return routeList; - } - - /** - * 生成进路 - * - * @param start 始端信号机 - * @param routeCodeGenerator 进路code生成器 - * @param overlapMap 已经构建的延续保护数据map(key-信号机code,val-延续保护路径) - * @param overlapCodeGenerator 延续保护code生成器 - * @param config 生成配置 - * @param errorList 生成错误信息 - */ - private List generateRoute(Signal start, CodeGenerator routeCodeGenerator, - Map> overlapMap, - CodeGenerator overlapCodeGenerator, - MapCiGenerateConfig config, List errorList) { - boolean right = start.isRight(); - Section startSection = start.getSection().getSectionOf(right); - List routePathList = new ArrayList<>(); - getRoutePathOf(start, startSection, false, - new SectionPath(right), routePathList, config, errorList); - List routeList = buildRouteFromPath(start, routeCodeGenerator, routePathList, - overlapMap, overlapCodeGenerator, config, errorList); - return routeList; - } - - private List buildRouteFromPath(Signal start, CodeGenerator routeCodeGenerator, List routePathList, - Map> overlapMap, - CodeGenerator overlapCodeGenerator, - MapCiGenerateConfig config, List errorList) { - boolean right = start.isRight(); - List routeList = new ArrayList<>(); - if (!CollectionUtils.isEmpty(routePathList)) { - for (SectionPath sectionPath : routePathList) { - Section lastSection = sectionPath.getLastSection(); - //最后一个区段是轨道尽头,则认为是单列车进路 - boolean singleTrain = lastSection.getNextSection(sectionPath.isRight()) == null; - Signal end = lastSection.getSignalOf(right); - List overlapList = overlapMap.get(end.getCode()); - // 根据配置是否有延续保护,生成 - if (!end.isNoOverlap()) { - // 查询延续保护是否已经生成,若未生成,则生成 - if (Objects.isNull(overlapList)) { - overlapList = new ArrayList<>(); - overlapMap.put(end.getCode(), overlapList); - overlapList.addAll(this.generateOverlap(end, overlapCodeGenerator, config, errorList)); - } - } - // 根据配置取进路终端信号机名称 - String endName = end.getName(); - Signal clickEnd = null; - Signal oeSignal = null; // 进路终端信号机反向信号机 - if (config.isRouteNameUseEndOppositeSignalName()) { - oeSignal = this.queryRouteEndOppositeSignal(end); - if (Objects.nonNull(oeSignal)) { - endName = oeSignal.getName(); - if (config.isRouteButton()) { - clickEnd = oeSignal; - } - } - } - if (config.isRouteButton() && config.isGetNearlySignal()) { - // 进路按钮取最近的信号机 - clickEnd = this.queryNearlySignalOf(start, sectionPath); - } - // 构建进路 - if (config.isRouteApartByOverlap() && !CollectionUtils.isEmpty(overlapList)) { - int index = 1; - for (RouteOverlap routeOverlap : overlapList) { - String code = routeCodeGenerator.next(); - String name = String.format("%s-%s_%s", start.getName(), endName, index); - Route route = this.buildRoute(code, name, start, end, clickEnd, sectionPath, routeOverlap, - config.isRouteSignalAlwaysGreen(), config.isRouteInterlockDoNotIncludeStandHoldTrain(), singleTrain); - routeList.add(route); - ++index; - } - } else if (config.isOverlapSettingByTrigger()) { // 触发建立,进路不绑定延续保护 - String code = routeCodeGenerator.next(); - String name = String.format("%s-%s", start.getName(), endName); - Route route = this.buildRoute(code, name, start, end, clickEnd, sectionPath, null, - config.isRouteSignalAlwaysGreen(), config.isRouteInterlockDoNotIncludeStandHoldTrain(), singleTrain); - routeList.add(route); - } else { - String code = routeCodeGenerator.next(); - String name = String.format("%s-%s", start.getName(), endName); - RouteOverlap overlap = null; - if (!CollectionUtils.isEmpty(overlapList)) { - overlap = overlapList.get(0); - } - Route route = this.buildRoute(code, name, start, end, clickEnd, sectionPath, overlap, - config.isRouteSignalAlwaysGreen(), config.isRouteInterlockDoNotIncludeStandHoldTrain(), singleTrain); - routeList.add(route); - } - } - } else { - errorList.add(String.format("以[%s(%s)]为始端信号的进路未搜索到", start.getName(), start.getCode())); - } - return routeList; - } - - private List generateRouteDepot(Signal start, CodeGenerator routeCodeGenerator, - MapCiGenerateConfig config, List errorList) { - boolean right = start.isRight(); - Section startSection = start.getSection().getSectionOf(right); - List routePathList = new ArrayList<>(); - getRoutePathOfDepot(start, startSection, new SectionPath(right), routePathList, config, errorList); - return buildRouteFromPathDepot(start, routeCodeGenerator, routePathList, config, errorList); - } - - private List buildRouteFromPathDepot(Signal startSignal, CodeGenerator routeCodeGenerator, List routePathList, - MapCiGenerateConfig config, List errorList) { - boolean right = startSignal.isRight(); - List routeList = new ArrayList<>(); - if (!CollectionUtils.isEmpty(routePathList)) { - for (SectionPath sectionPath : routePathList) { - Section lastSection = sectionPath.getLastSection(); - Signal.SignalType startSignalType = startSignal.getType(); - // 终端信号机 - Signal endSignal = lastSection.getSignalOf(right); - Signal.SignalType endSignalType = Objects.nonNull(endSignal) ? endSignal.getType() : null; - // 反向信号机 - Signal endOpSignal = lastSection.getSignalOf(!right); - Signal.SignalType endOpSignalType = Objects.nonNull(endOpSignal) ? endOpSignal.getType() : null; - Section nextSection = lastSection.getSectionOf(right); - // 下个区段反向信号机 - Signal nextOpSignal = Objects.nonNull(nextSection) ? nextSection.getSignalOf(!right) : null; - Signal clickEnd; - - SignalAspect signalAspect; - if ((Signal.SignalType.SHUNTING2.equals(endSignalType) && Signal.SignalType.SHUNTING2.equals(startSignalType)) - || (Signal.SignalType.SHUNTING2.equals(endSignalType) && Signal.SignalType.INBOUND.equals(startSignalType)) - || (Signal.SignalType.OUTBOUND.equals(endSignalType) && Signal.SignalType.SHUNTING2.equals(startSignalType))) { - // 列车进路 - signalAspect = SignalAspect.Y; - if (Objects.nonNull(endOpSignal) && (Signal.SignalType.SHUNTING2.equals(endOpSignalType) - || Signal.SignalType.OUTBOUND.equals(endOpSignalType))) { - clickEnd = endOpSignal; - } else { - clickEnd = endSignal; - } - } else { - // 调车进路 - signalAspect = SignalAspect.W; - if (Objects.nonNull(endOpSignal) && sectionPath.getSectionList().size() > 1) { - // 使用反向信号机,过滤 列车兼调车信号机 -> 尽头,列车兼调车信号机 -> 出段信号机 - clickEnd = endOpSignal; - } else if (Objects.nonNull(nextOpSignal)) { - // 下个区段反向信号机存在,则使用 - clickEnd = nextOpSignal; - } else { - // 其余设置为终端信号机,可能为null - clickEnd = endSignal; - } - } - - String endName = Objects.nonNull(endSignal) ? endSignal.getShowName() : lastSection.getName(); - // 构建进路 - String code = routeCodeGenerator.next(); - String name = String.format("%s-%s", startSignal.getShowName(), endName); - Route route = this.buildRouteDepot(code, name, startSignal, endSignal, clickEnd, sectionPath, signalAspect); - routeList.add(route); - } - } else { - errorList.add(String.format("以[%s(%s)]为始端信号(%s)的进路未搜索到", startSignal.getShowName(), - startSignal.getCode(), startSignal.getType())); - } - return routeList; - } - - /** - * 查询距给给定信号机最近的信号机 - * - * @param signal - * @param sectionPath - * @return - */ - private Signal queryNearlySignalOf(Signal signal, SectionPath sectionPath) { - boolean right = signal.isRight(); - List
sectionList = sectionPath.getSectionList(); - Signal nearly = null; + } + } else { + if (!CollectionUtils.isEmpty(sectionList)) { for (Section section : sectionList) { - Signal ods = section.getSignalOf(!right);// 与给定信号机反向信号机 - Signal sds = section.getSignalOf(right);// 与给定信号机同向信号机 - if (Objects.nonNull(ods)) { - nearly = ods; - break; - } else if (Objects.nonNull(sds)) { - nearly = sds; - break; - } + String destinationCode = section.getDestinationCode(); + if (!StringUtils.hasText(destinationCode)) { + continue; + } + destinationCodeDefinitionList.add( + new DestinationCodeDefinition(destinationCode, DestinationCodeDefinition.Type.OTHER, + section)); } - if (Objects.isNull(nearly)) { - log.warn(String.format("信号机[%s(%s)]最近的信号机未找到", - signal.getName(), signal.getCode())); - } - return nearly; + } } + return destinationCodeDefinitionList; + } - /** - * 根据信号机配置,删除不需要的基本进路 - * - * @param signalList - * @param generatedRouteList - */ - private void deleteBaseRoute(List signalList, List generatedRouteList) { - Map signalMap = signalList.stream().collect(Collectors.toMap(Signal::getCode, Function.identity())); - List removeList = new ArrayList<>(); - for (Route route : generatedRouteList) { - if (route.isTurnBack()) { // 折返进路不处理 - continue; - } - Signal signal = signalMap.get(route.getStart().getCode()); - List ignoreEndCodeList = signal.getIgnoreRouteEnd(); - if (!CollectionUtils.isEmpty(ignoreEndCodeList)) { - if (ignoreEndCodeList.contains(route.getDestination().getCode())) { - removeList.add(route); - continue; - } - } - if (signal.isNoRoute()) { - removeList.add(route); - } - } - generatedRouteList.removeAll(removeList); + /** + * 筛选站后折返轨(优先右行站台折返) + * + * @param stations 所有车站 + * @param right 是否是右端车站 + */ + private List
queryFrontTurnBackList(List stations, Station station, + boolean right) { + List
turnBackList = station.getTurnBackList(); + if (CollectionUtils.isEmpty(turnBackList) || CollectionUtils.isEmpty( + station.getAllNormalStands())) { + return new ArrayList<>(); } - - private Map generateFls(List switchList) { - CodeGenerator fpCodeGenerator = CodeGenerator.getFlsCodeGenerator(0); // 侧防 - Map map = new HashMap<>(); - for (Switch aSwitch : switchList) { - RouteFls npFls = this.buildNpFls(aSwitch, fpCodeGenerator); - if (Objects.nonNull(npFls)) { - map.put(npFls.getName(), npFls); - } - RouteFls rpFls = this.buildRpFls(aSwitch, fpCodeGenerator); - if (Objects.nonNull(rpFls)) { - map.put(rpFls.getName(), rpFls); - } - } - return map; + int sn; + if (right) { + sn = station.getSn() - 1; + } else { + sn = station.getSn() + 1; } + Station adjacentStation = stations.stream().filter(sta -> sta.getSn() == sn).findAny().get(); + if (CollectionUtils.isEmpty(adjacentStation.getAllNormalStands())) { + return new ArrayList<>(); + } + Section leftStandTrack = station.getNormalStand(false).get(0).getSection(); + Section rightStandTrack = station.getNormalStand(true).get(0).getSection(); + Section adjacentLeftStandTrack = adjacentStation.getNormalStand(false).get(0).getSection(); + Section adjacentRightStandTrack = adjacentStation.getNormalStand(true).get(0).getSection(); + List
tbSections = new ArrayList<>(); + if (right) { + if (rightStandTrack.isTurnBackTrack() + && !CollectionUtils.isEmpty( + CalculateService.queryRoutePathsOnDirection(rightStandTrack, adjacentLeftStandTrack, + false, 10))) { + tbSections.add(rightStandTrack); + } + if (leftStandTrack.isTurnBackTrack() + && !CollectionUtils.isEmpty( + CalculateService.queryRoutePathsOnDirection(adjacentRightStandTrack, leftStandTrack, true, + 10))) { + tbSections.add(leftStandTrack); + } + } else { + if (rightStandTrack.isTurnBackTrack() + && !CollectionUtils.isEmpty( + CalculateService.queryRoutePathsOnDirection(adjacentLeftStandTrack, rightStandTrack, + false, 10))) { + tbSections.add(rightStandTrack); + } + if (leftStandTrack.isTurnBackTrack() + && !CollectionUtils.isEmpty( + CalculateService.queryRoutePathsOnDirection(leftStandTrack, adjacentRightStandTrack, true, + 10))) { + tbSections.add(leftStandTrack); + } + } + return tbSections; + } - /** - * 构建道岔定位侧防 - * - * @param aSwitch - * @param fpCodeGenerator - * @return - */ - private RouteFls buildNpFls(Switch aSwitch, CodeGenerator fpCodeGenerator) { - RouteFls fls = new RouteFls(fpCodeGenerator.next(), new SwitchElement(aSwitch, true)); - // 暂时只生成一级侧防 - Switch linkedSwitch = aSwitch.queryLinkedSwitch(); - if (Objects.nonNull(linkedSwitch)) { - // 联动道岔存在,联动道岔定位即为一级侧防 - RouteFls.FlsElement flsElement = new RouteFls.FlsElement(new SwitchElement(linkedSwitch, true)); - fls.addLevel1(flsElement); + /** + * 筛选站前折返轨 + * + * @param right 是否是右端车站 + */ + private List
queryAfterTurnBackList(Station station, boolean right) { + List
turnBackList = station.getTurnBackList(); + if (CollectionUtils.isEmpty(turnBackList)) { + return new ArrayList<>(); + } + Section standTrack = station.getNormalStand(right).get(0).getSection(); + return turnBackList.stream().filter(section -> !section.isNormalStandTrack()) + .filter(section -> !CollectionUtils.isEmpty( + CalculateService.queryRoutePathsOnDirection(standTrack, section, right, 10))) + .collect(Collectors.toList()); + } + + private Collection generateRouteLikeHa1(Signal signal, + CodeGenerator routeCodeGenerator, + Map> overlapMap, + CodeGenerator overlapCodeGenerator, + MapCiGenerateConfig config, List errorList) { + // 生成ATP信号 + List routeList = new ArrayList<>(); + List atpRouteList = this.generateRoute(signal, routeCodeGenerator, overlapMap, + overlapCodeGenerator, config, errorList); + if (!CollectionUtils.isEmpty(atpRouteList)) { + for (Route route : atpRouteList) { + route.setAtp(true); + if ((signal.isRight() && signal.getSection().isRightLine()) + || (!signal.isRight() && signal.getSection().isLeftLine())) { + route.setArs(true); + } + routeList.add(route); + } + } + // 生成地面信号 + List groundRouteList = this.generateGroundRoute(signal, routeCodeGenerator, overlapMap, + overlapCodeGenerator, config, errorList); + if (!CollectionUtils.isEmpty(groundRouteList)) { + for (Route ground : groundRouteList) { + ground.setGround(true); + ground.setArs(false); + routeList.add(ground); + } + } + // 生成引导信号 + if (!CollectionUtils.isEmpty(groundRouteList)) { + for (Route route : groundRouteList) { + Route guide = this.buildGuideRouteFromGroundRoute(route, routeCodeGenerator, + config.isRouteInterlockDoNotIncludeStandHoldTrain()); + routeList.add(guide); + } + } + return routeList; + } + + private Route buildGuideRouteFromGroundRoute(Route route, CodeGenerator routeCodeGenerator, + boolean noStandHold) { + Route clone = new Route(routeCodeGenerator.next(), route.getName()); + clone.setArs(false); + clone.setGuide(true); + clone.setInterlockStation(route.getInterlockStation()); + clone.setStart(route.getStart()); + clone.setDestination(route.getDestination()); + clone.setAspect(route.getAspect()); + clone.setSectionList(route.getSectionList()); + clone.setSwitchList(route.getSwitchList()); + clone.setPsdList(route.getPsdList()); + clone.setEspList(route.getEspList()); + if (!noStandHold) { + clone.setStandHoldList(route.getStandHoldList()); + } + clone.setDestinationButtonSignal(route.getDestinationButtonSignal()); + return clone; + } + + private List generateGroundRoute(Signal signal, CodeGenerator routeCodeGenerator, + Map> overlapMap, + CodeGenerator overlapCodeGenerator, + MapCiGenerateConfig config, List errorList) { + if (signal.isVirtual()) { // 如果是虚拟信号机,返回 + return new ArrayList<>(); + } + boolean right = signal.isRight(); + Section startSection = signal.getSection().getSectionOf(right); + List routePathList = new ArrayList<>(); + getRoutePathOf(signal, startSection, true, + new SectionPath(right), routePathList, config, errorList); + List routeList = this.buildRouteFromPath(signal, routeCodeGenerator, routePathList, + overlapMap, + overlapCodeGenerator, config, errorList); + return routeList; + } + + /** + * 生成进路 + * + * @param start 始端信号机 + * @param routeCodeGenerator 进路code生成器 + * @param overlapMap 已经构建的延续保护数据map(key-信号机code,val-延续保护路径) + * @param overlapCodeGenerator 延续保护code生成器 + * @param config 生成配置 + * @param errorList 生成错误信息 + */ + private List generateRoute(Signal start, CodeGenerator routeCodeGenerator, + Map> overlapMap, + CodeGenerator overlapCodeGenerator, + MapCiGenerateConfig config, List errorList) { + boolean right = start.isRight(); + Section startSection = start.getSection().getSectionOf(right); + List routePathList = new ArrayList<>(); + getRoutePathOf(start, startSection, false, + new SectionPath(right), routePathList, config, errorList); + List routeList = buildRouteFromPath(start, routeCodeGenerator, routePathList, + overlapMap, overlapCodeGenerator, config, errorList); + return routeList; + } + + private List buildRouteFromPath(Signal start, CodeGenerator routeCodeGenerator, + List routePathList, + Map> overlapMap, + CodeGenerator overlapCodeGenerator, + MapCiGenerateConfig config, List errorList) { + boolean right = start.isRight(); + List routeList = new ArrayList<>(); + if (!CollectionUtils.isEmpty(routePathList)) { + for (SectionPath sectionPath : routePathList) { + Section lastSection = sectionPath.getLastSection(); + //最后一个区段是轨道尽头,则认为是单列车进路 + boolean singleTrain = lastSection.getNextSection(sectionPath.isRight()) == null; + Signal end = lastSection.getSignalOf(right); + List overlapList = overlapMap.get(end.getCode()); + // 根据配置是否有延续保护,生成 + if (!end.isNoOverlap()) { + // 查询延续保护是否已经生成,若未生成,则生成 + if (Objects.isNull(overlapList)) { + overlapList = new ArrayList<>(); + overlapMap.put(end.getCode(), overlapList); + overlapList.addAll(this.generateOverlap(end, overlapCodeGenerator, config, errorList)); + } + } + // 根据配置取进路终端信号机名称 + String endName = end.getName(); + Signal clickEnd = null; + Signal oeSignal = null; // 进路终端信号机反向信号机 + if (config.isRouteNameUseEndOppositeSignalName()) { + oeSignal = this.queryRouteEndOppositeSignal(end); + if (Objects.nonNull(oeSignal)) { + endName = oeSignal.getName(); + if (config.isRouteButton()) { + clickEnd = oeSignal; + } + } + } + if (config.isRouteButton() && config.isGetNearlySignal()) { + // 进路按钮取最近的信号机 + clickEnd = this.queryNearlySignalOf(start, sectionPath); + } + // 构建进路 + if (config.isRouteApartByOverlap() && !CollectionUtils.isEmpty(overlapList)) { + int index = 1; + for (RouteOverlap routeOverlap : overlapList) { + String code = routeCodeGenerator.next(); + String name = String.format("%s-%s_%s", start.getName(), endName, index); + Route route = this.buildRoute(code, name, start, end, clickEnd, sectionPath, + routeOverlap, + config.isRouteSignalAlwaysGreen(), + config.isRouteInterlockDoNotIncludeStandHoldTrain(), singleTrain); + routeList.add(route); + ++index; + } + } else if (config.isOverlapSettingByTrigger()) { // 触发建立,进路不绑定延续保护 + String code = routeCodeGenerator.next(); + String name = String.format("%s-%s", start.getName(), endName); + Route route = this.buildRoute(code, name, start, end, clickEnd, sectionPath, null, + config.isRouteSignalAlwaysGreen(), + config.isRouteInterlockDoNotIncludeStandHoldTrain(), singleTrain); + routeList.add(route); } else { - // 无联动道岔,则从道岔C区段向外查询,第一个反向信号机和经过的路径道岔位置构成一级侧防 - Section c = aSwitch.getC(); - if (c.getLeftSection() == null && c.getRightSection() == null) { - // 尽头区段,不需构成侧防 - return null; - } - BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(c.getLeftSection() != null && c.getRightSection() != null, - String.format("道岔区段[%s]关联区段关系异常,只能最多一边关联,实际两边都关联了区段", c.debugStr())); - boolean right = true; - Section startSection = c.getRightSection(); - if (c.getLeftSection() != null) { // 左向区段存在,方向向左 - right = false; - startSection = c.getLeftSection(); - } - Stack
sectionStack = new Stack<>(); - Section pre = null; - sectionStack.push(startSection); - int i = 0; - while (!sectionStack.isEmpty() && i < 100) { - ++i; - Section section = sectionStack.pop(); - Signal oppositeSignal = section.getSignalOf(!right); - if (Objects.nonNull(oppositeSignal)) { // 找到反向信号机 - Section firstSection = oppositeSignal.getSection().getSectionOf(oppositeSignal.isRight()); - RouteFls.FlsElement flsElement; - Switch relSwitch = firstSection.getRelSwitch(); - if (firstSection.isSwitchTrack() && !Objects.equals(aSwitch, relSwitch)) { - boolean normal = true; - if (pre != null && - ((relSwitch.isC(pre) && relSwitch.isA(firstSection)) || - relSwitch.isC(firstSection) && relSwitch.isA(pre))) { - normal = false; - } - flsElement = new RouteFls.FlsElement(oppositeSignal, new SwitchElement(relSwitch, normal)); - } else { - flsElement = new RouteFls.FlsElement(oppositeSignal); - } - fls.addLevel1(flsElement); - pre = null; - } else { // 未找到,取下一区段,入栈 - Section next = section.getSectionOf(right); - if (next != null) { - if (next.isSwitchTrack() && next.getRelSwitch().isC(next)) { - // C区段,一级侧防为此道岔定位 - RouteFls.FlsElement flsElement = new RouteFls.FlsElement(new SwitchElement(next.getRelSwitch(), true)); - fls.addLevel1(flsElement); - pre = null; - } else { - sectionStack.push(next); - pre = section; - } - } else { - if (section.isSwitchTrack() && section.getSectionOf(!right) != null) { - // 非尽头道岔区段 - Switch relSwitch = section.getRelSwitch(); - if (relSwitch.isA(section)) { - sectionStack.push(relSwitch.getC()); - sectionStack.push(relSwitch.getB()); - pre = section; - } else { - sectionStack.push(relSwitch.getA()); - pre = section; - } - } - } - } - } + String code = routeCodeGenerator.next(); + String name = String.format("%s-%s", start.getName(), endName); + RouteOverlap overlap = null; + if (!CollectionUtils.isEmpty(overlapList)) { + overlap = overlapList.get(0); + } + Route route = this.buildRoute(code, name, start, end, clickEnd, sectionPath, overlap, + config.isRouteSignalAlwaysGreen(), + config.isRouteInterlockDoNotIncludeStandHoldTrain(), singleTrain); + routeList.add(route); } - if (!fls.hasElement()) { - return null; - } - return fls; + } + } else { + errorList.add( + String.format("以[%s(%s)]为始端信号的进路未搜索到", start.getName(), start.getCode())); } + return routeList; + } - /** - * 构建道岔反位侧防 - * - * @param aSwitch - * @param fpCodeGenerator - * @return - */ - private RouteFls buildRpFls(Switch aSwitch, CodeGenerator fpCodeGenerator) { - RouteFls fls = new RouteFls(fpCodeGenerator.next(), new SwitchElement(aSwitch, false)); - // 暂只生成一级侧防 - Section b = aSwitch.getB(); - if (b.getLeftSection() == null && b.getRightSection() == null) { - // 尽头区段,不需构成侧防 - return null; + private List generateRouteDepot(Signal start, CodeGenerator routeCodeGenerator, + MapCiGenerateConfig config, List errorList) { + boolean right = start.isRight(); + Section startSection = start.getSection().getSectionOf(right); + List routePathList = new ArrayList<>(); + getRoutePathOfDepot(start, startSection, new SectionPath(right), routePathList, config, + errorList); + return buildRouteFromPathDepot(start, routeCodeGenerator, routePathList, config, errorList); + } + + private List buildRouteFromPathDepot(Signal startSignal, CodeGenerator routeCodeGenerator, + List routePathList, + MapCiGenerateConfig config, List errorList) { + boolean right = startSignal.isRight(); + List routeList = new ArrayList<>(); + if (!CollectionUtils.isEmpty(routePathList)) { + for (SectionPath sectionPath : routePathList) { + Section lastSection = sectionPath.getLastSection(); + Signal.SignalType startSignalType = startSignal.getType(); + // 终端信号机 + Signal endSignal = lastSection.getSignalOf(right); + Signal.SignalType endSignalType = Objects.nonNull(endSignal) ? endSignal.getType() : null; + // 反向信号机 + Signal endOpSignal = lastSection.getSignalOf(!right); + Signal.SignalType endOpSignalType = + Objects.nonNull(endOpSignal) ? endOpSignal.getType() : null; + Section nextSection = lastSection.getSectionOf(right); + // 下个区段反向信号机 + Signal nextOpSignal = Objects.nonNull(nextSection) ? nextSection.getSignalOf(!right) : null; + Signal clickEnd; + + SignalAspect signalAspect; + if ((Signal.SignalType.SHUNTING2.equals(endSignalType) + && Signal.SignalType.SHUNTING2.equals(startSignalType)) + || (Signal.SignalType.SHUNTING2.equals(endSignalType) + && Signal.SignalType.INBOUND.equals(startSignalType)) + || (Signal.SignalType.OUTBOUND.equals(endSignalType) + && Signal.SignalType.SHUNTING2.equals(startSignalType))) { + // 列车进路 + signalAspect = SignalAspect.Y; + if (Objects.nonNull(endOpSignal) && (Signal.SignalType.SHUNTING2.equals(endOpSignalType) + || Signal.SignalType.OUTBOUND.equals(endOpSignalType))) { + clickEnd = endOpSignal; + } else { + clickEnd = endSignal; + } + } else { + // 调车进路 + signalAspect = SignalAspect.W; + if (Objects.nonNull(endOpSignal) && sectionPath.getSectionList().size() > 1) { + // 使用反向信号机,过滤 列车兼调车信号机 -> 尽头,列车兼调车信号机 -> 出段信号机 + clickEnd = endOpSignal; + } else if (Objects.nonNull(nextOpSignal)) { + // 下个区段反向信号机存在,则使用 + clickEnd = nextOpSignal; + } else { + // 其余设置为终端信号机,可能为null + clickEnd = endSignal; + } } - BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(b.getLeftSection() != null && b.getRightSection() != null, - String.format("道岔区段[%s]关联区段关系异常,只能最多一边关联,实际两边都关联了区段", b.debugStr())); - boolean right = true; - Section startSection = b.getRightSection(); - if (b.getLeftSection() != null) { // 左向区段存在,方向向左 - right = false; - startSection = b.getLeftSection(); - } - Stack
sectionStack = new Stack<>(); - sectionStack.push(startSection); - int i = 0; - while (!sectionStack.isEmpty() && i < 100) { - ++i; - Section section = sectionStack.pop(); - Signal oppositeSignal = section.getSignalOf(!right); - if (Objects.nonNull(oppositeSignal)) { // 找到反向信号机 - Section firstSection = oppositeSignal.getSection().getSectionOf(oppositeSignal.isRight()); - RouteFls.FlsElement flsElement; - Switch relSwitch = firstSection.getRelSwitch(); - if (firstSection.isSwitchTrack() && - !Objects.equals(aSwitch, relSwitch) && - !Objects.equals(aSwitch.queryAxleRelatedOtherSwitch(), relSwitch)) { - Switch remoteSwitch = relSwitch.queryAxleRelatedOtherSwitch(); - if (Objects.nonNull(remoteSwitch)) { - flsElement = new RouteFls.FlsElement(oppositeSignal, new SwitchElement(remoteSwitch, true)); - } else { - flsElement = new RouteFls.FlsElement(oppositeSignal, new SwitchElement(relSwitch, true)); - } - } else { - flsElement = new RouteFls.FlsElement(oppositeSignal); - } - fls.addLevel1(flsElement); - } else { // 未找到,取下一区段,入栈 - Section next = section.getSectionOf(right); - if (next != null) { - if (next.isSwitchTrack() && next.getRelSwitch().isC(next)) { - // C区段,一级侧防为此道岔定位 - RouteFls.FlsElement flsElement = new RouteFls.FlsElement(new SwitchElement(next.getRelSwitch(), true)); - fls.addLevel1(flsElement); - } else { - sectionStack.push(next); - } - } else { - if (section.isSwitchTrack() && section.getSectionOf(!right) != null) { - // 非尽头道岔区段 - Switch relSwitch = section.getRelSwitch(); - if (relSwitch.isA(section)) { - sectionStack.push(relSwitch.getC()); - sectionStack.push(relSwitch.getB()); - } else { - sectionStack.push(relSwitch.getA()); - } - } - } - } - } - if (!fls.hasElement()) { - return null; - } - return fls; + + String endName = + Objects.nonNull(endSignal) ? endSignal.getShowName() : lastSection.getName(); + // 构建进路 + String code = routeCodeGenerator.next(); + String name = String.format("%s-%s", startSignal.getShowName(), endName); + Route route = this.buildRouteDepot(code, name, startSignal, endSignal, clickEnd, + sectionPath, signalAspect); + routeList.add(route); + } + } else { + errorList.add( + String.format("以[%s(%s)]为始端信号(%s)的进路未搜索到", startSignal.getShowName(), + startSignal.getCode(), startSignal.getType())); } + return routeList; + } - private void generateRunLevel(Map deviceMap, List errorList, - List generatedRoutingList, - List generatedStationRunLevelList) { - List stationList = deviceMap.values().stream() - .filter(mapElement -> mapElement.getDeviceType().equals(MapElement.DeviceType.STATION)) - .map(mapElement -> ((Station) mapElement)) - .sorted(Comparator.comparing(Station::getSn)) - .collect(Collectors.toList()); - for (MapRoutingDataVO routing : generatedRoutingList) { - Section routingStartSection = (Section) deviceMap.get(routing.getStartSectionCode()); - Section routingEndSection = (Section) deviceMap.get(routing.getEndSectionCode()); - Boolean right = routing.getRight(); - List sectionCodeList = routing.getParkSectionCodeList(); - for (int i = 0; i < sectionCodeList.size() - 1; i++) { - Section startSection = (Section) deviceMap.get(sectionCodeList.get(i).getSectionCode()); - Section endSection = (Section) deviceMap.get(sectionCodeList.get(i + 1).getSectionCode()); - //已创建 - boolean exist = false; - for (MapStationRunLevelVO vo : generatedStationRunLevelList) { - if (vo.isSameOf(startSection.getCode(), endSection.getCode())) { - exist = true; - break; - } - } - if (exist) { - continue; - } - int min = Math.min(startSection.getStation().getSn(), endSection.getStation().getSn()); - int max = Math.max(startSection.getStation().getSn(), endSection.getStation().getSn()); - int di = Math.abs(max - min); - if (di > 1) { // 间隔大于1,判断中间车站是否停车场/非正常车站 - for (Station station : stationList) { - if (station.getSn() > min && station.getSn() < max) { - BusinessExceptionAssertEnum.CI_GENERATE_ERROR - .assertTrue(station.isDepot() || station.isNoDepotAndNoNormalStand(), - String.format("交路[%s]下的站间运行等级[%s]数据间隔车站大于1且间隔中的车站[%s]是正常可停靠车站", - String.format("%s(%s)->%s(%s)", - routingStartSection.getStation().getName(), routingStartSection.getName(), - routingEndSection.getStation().getName(), routingEndSection.getName()), - String.format("%s(%s(%s))->%s(%s(%s))", - startSection.getStation().getName(), startSection.getName(), startSection.getCode(), - endSection.getStation().getName(), endSection.getName(), endSection.getCode()), - station.getName())); - } - } - } - // 创建 - MapStationRunLevelVO runLevelVO = new MapStationRunLevelVO(); - runLevelVO.setStartSectionCode(startSection.getCode()); - runLevelVO.setStartStationCode(startSection.getStation().getCode()); - runLevelVO.setEndSectionCode(endSection.getCode()); - runLevelVO.setEndStationCode(endSection.getStation().getCode()); - runLevelVO.setRight(right); - List routePaths = CalculateService.queryRoutePathsOnDirection(startSection, endSection, right, 10); - if (CollectionUtils.isEmpty(routePaths)) { - // 未找到,反方向再找 - routePaths = CalculateService.queryRoutePathsOnDirection(startSection, endSection, !right, 10); - if (!CollectionUtils.isEmpty(routePaths)) { - log.info(String.format("站间运行等级[%s]与交路[%s]方向相反,实际为[%s]", - String.format("%s(%s(%s))->%s(%s(%s))", - startSection.getStation().getName(), startSection.getName(), startSection.getCode(), - endSection.getStation().getName(), endSection.getName(), endSection.getCode()), - String.format("%s(%s)->%s(%s)", - routingStartSection.getStation().getName(), routingStartSection.getName(), - routingEndSection.getStation().getName(), routingEndSection.getName()), - !right ? "右向" : "左向")); - runLevelVO.setRight(!right); - } - } - if (CollectionUtils.isEmpty(routePaths)) { - log.warn(String.format("站间运行等级数据生成失败:没有找到[%s(%s) ——> %s(%s)]对应方向[%s]的站间", - startSection.getStation().getName(), startSection.getName(), endSection.getStation().getName(), endSection.getName(), right ? "右向" : "左向")); + /** + * 查询距给给定信号机最近的信号机 + * + * @param signal + * @param sectionPath + * @return + */ + private Signal queryNearlySignalOf(Signal signal, SectionPath sectionPath) { + boolean right = signal.isRight(); + List
sectionList = sectionPath.getSectionList(); + Signal nearly = null; + for (Section section : sectionList) { + Signal ods = section.getSignalOf(!right);// 与给定信号机反向信号机 + Signal sds = section.getSignalOf(right);// 与给定信号机同向信号机 + if (Objects.nonNull(ods)) { + nearly = ods; + break; + } else if (Objects.nonNull(sds)) { + nearly = sds; + break; + } + } + if (Objects.isNull(nearly)) { + log.warn(String.format("信号机[%s(%s)]最近的信号机未找到", + signal.getName(), signal.getCode())); + } + return nearly; + } + + /** + * 根据信号机配置,删除不需要的基本进路 + * + * @param signalList + * @param generatedRouteList + */ + private void deleteBaseRoute(List signalList, List generatedRouteList) { + Map signalMap = signalList.stream() + .collect(Collectors.toMap(Signal::getCode, Function.identity())); + List removeList = new ArrayList<>(); + for (Route route : generatedRouteList) { + if (route.isTurnBack()) { // 折返进路不处理 + continue; + } + Signal signal = signalMap.get(route.getStart().getCode()); + List ignoreEndCodeList = signal.getIgnoreRouteEnd(); + if (!CollectionUtils.isEmpty(ignoreEndCodeList)) { + if (ignoreEndCodeList.contains(route.getDestination().getCode())) { + removeList.add(route); + continue; + } + } + if (signal.isNoRoute()) { + removeList.add(route); + } + } + generatedRouteList.removeAll(removeList); + } + + private Map generateFls(List switchList) { + CodeGenerator fpCodeGenerator = CodeGenerator.getFlsCodeGenerator(0); // 侧防 + Map map = new HashMap<>(); + for (Switch aSwitch : switchList) { + RouteFls npFls = this.buildNpFls(aSwitch, fpCodeGenerator); + if (Objects.nonNull(npFls)) { + map.put(npFls.getName(), npFls); + } + RouteFls rpFls = this.buildRpFls(aSwitch, fpCodeGenerator); + if (Objects.nonNull(rpFls)) { + map.put(rpFls.getName(), rpFls); + } + } + return map; + } + + /** + * 构建道岔定位侧防 + * + * @param aSwitch + * @param fpCodeGenerator + * @return + */ + private RouteFls buildNpFls(Switch aSwitch, CodeGenerator fpCodeGenerator) { + RouteFls fls = new RouteFls(fpCodeGenerator.next(), new SwitchElement(aSwitch, true)); + // 暂时只生成一级侧防 + Switch linkedSwitch = aSwitch.queryLinkedSwitch(); + if (Objects.nonNull(linkedSwitch)) { + // 联动道岔存在,联动道岔定位即为一级侧防 + RouteFls.FlsElement flsElement = new RouteFls.FlsElement( + new SwitchElement(linkedSwitch, true)); + fls.addLevel1(flsElement); + } else { + // 无联动道岔,则从道岔C区段向外查询,第一个反向信号机和经过的路径道岔位置构成一级侧防 + Section c = aSwitch.getC(); + if (c.getLeftSection() == null && c.getRightSection() == null) { + // 尽头区段,不需构成侧防 + return null; + } + BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue( + c.getLeftSection() != null && c.getRightSection() != null, + String.format("道岔区段[%s]关联区段关系异常,只能最多一边关联,实际两边都关联了区段", + c.debugStr())); + boolean right = true; + Section startSection = c.getRightSection(); + if (c.getLeftSection() != null) { // 左向区段存在,方向向左 + right = false; + startSection = c.getLeftSection(); + } + Stack
sectionStack = new Stack<>(); + Section pre = null; + sectionStack.push(startSection); + int i = 0; + while (!sectionStack.isEmpty() && i < 100) { + ++i; + Section section = sectionStack.pop(); + Signal oppositeSignal = section.getSignalOf(!right); + if (Objects.nonNull(oppositeSignal)) { // 找到反向信号机 + Section firstSection = oppositeSignal.getSection().getSectionOf(oppositeSignal.isRight()); + RouteFls.FlsElement flsElement; + Switch relSwitch = firstSection.getRelSwitch(); + if (firstSection.isSwitchTrack() && !Objects.equals(aSwitch, relSwitch)) { + boolean normal = true; + if (pre != null && + ((relSwitch.isC(pre) && relSwitch.isA(firstSection)) || + relSwitch.isC(firstSection) && relSwitch.isA(pre))) { + normal = false; + } + flsElement = new RouteFls.FlsElement(oppositeSignal, + new SwitchElement(relSwitch, normal)); + } else { + flsElement = new RouteFls.FlsElement(oppositeSignal); + } + fls.addLevel1(flsElement); + pre = null; + } else { // 未找到,取下一区段,入栈 + Section next = section.getSectionOf(right); + if (next != null) { + if (next.isSwitchTrack() && next.getRelSwitch().isC(next)) { + // C区段,一级侧防为此道岔定位 + RouteFls.FlsElement flsElement = new RouteFls.FlsElement( + new SwitchElement(next.getRelSwitch(), true)); + fls.addLevel1(flsElement); + pre = null; + } else { + sectionStack.push(next); + pre = section; + } + } else { + if (section.isSwitchTrack() && section.getSectionOf(!right) != null) { + // 非尽头道岔区段 + Switch relSwitch = section.getRelSwitch(); + if (relSwitch.isA(section)) { + sectionStack.push(relSwitch.getC()); + sectionStack.push(relSwitch.getB()); + pre = section; + } else { + sectionStack.push(relSwitch.getA()); + pre = section; + } + } + } + } + } + } + if (!fls.hasElement()) { + return null; + } + return fls; + } + + /** + * 构建道岔反位侧防 + * + * @param aSwitch + * @param fpCodeGenerator + * @return + */ + private RouteFls buildRpFls(Switch aSwitch, CodeGenerator fpCodeGenerator) { + RouteFls fls = new RouteFls(fpCodeGenerator.next(), new SwitchElement(aSwitch, false)); + // 暂只生成一级侧防 + Section b = aSwitch.getB(); + if (b.getLeftSection() == null && b.getRightSection() == null) { + // 尽头区段,不需构成侧防 + return null; + } + BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue( + b.getLeftSection() != null && b.getRightSection() != null, + String.format("道岔区段[%s]关联区段关系异常,只能最多一边关联,实际两边都关联了区段", + b.debugStr())); + boolean right = true; + Section startSection = b.getRightSection(); + if (b.getLeftSection() != null) { // 左向区段存在,方向向左 + right = false; + startSection = b.getLeftSection(); + } + Stack
sectionStack = new Stack<>(); + sectionStack.push(startSection); + int i = 0; + while (!sectionStack.isEmpty() && i < 100) { + ++i; + Section section = sectionStack.pop(); + Signal oppositeSignal = section.getSignalOf(!right); + if (Objects.nonNull(oppositeSignal)) { // 找到反向信号机 + Section firstSection = oppositeSignal.getSection().getSectionOf(oppositeSignal.isRight()); + RouteFls.FlsElement flsElement; + Switch relSwitch = firstSection.getRelSwitch(); + if (firstSection.isSwitchTrack() && + !Objects.equals(aSwitch, relSwitch) && + !Objects.equals(aSwitch.queryAxleRelatedOtherSwitch(), relSwitch)) { + Switch remoteSwitch = relSwitch.queryAxleRelatedOtherSwitch(); + if (Objects.nonNull(remoteSwitch)) { + flsElement = new RouteFls.FlsElement(oppositeSignal, + new SwitchElement(remoteSwitch, true)); + } else { + flsElement = new RouteFls.FlsElement(oppositeSignal, + new SwitchElement(relSwitch, true)); + } + } else { + flsElement = new RouteFls.FlsElement(oppositeSignal); + } + fls.addLevel1(flsElement); + } else { // 未找到,取下一区段,入栈 + Section next = section.getSectionOf(right); + if (next != null) { + if (next.isSwitchTrack() && next.getRelSwitch().isC(next)) { + // C区段,一级侧防为此道岔定位 + RouteFls.FlsElement flsElement = new RouteFls.FlsElement( + new SwitchElement(next.getRelSwitch(), true)); + fls.addLevel1(flsElement); + } else { + sectionStack.push(next); + } + } else { + if (section.isSwitchTrack() && section.getSectionOf(!right) != null) { + // 非尽头道岔区段 + Switch relSwitch = section.getRelSwitch(); + if (relSwitch.isA(section)) { + sectionStack.push(relSwitch.getC()); + sectionStack.push(relSwitch.getB()); + } else { + sectionStack.push(relSwitch.getA()); + } + } + } + } + } + if (!fls.hasElement()) { + return null; + } + return fls; + } + + private void generateRunLevel(Map deviceMap, List errorList, + List generatedRoutingList, + List generatedStationRunLevelList) { + List stationList = deviceMap.values().stream() + .filter(mapElement -> mapElement.getDeviceType().equals(MapElement.DeviceType.STATION)) + .map(mapElement -> ((Station) mapElement)) + .sorted(Comparator.comparing(Station::getSn)) + .collect(Collectors.toList()); + for (MapRoutingDataVO routing : generatedRoutingList) { + Section routingStartSection = (Section) deviceMap.get(routing.getStartSectionCode()); + Section routingEndSection = (Section) deviceMap.get(routing.getEndSectionCode()); + Boolean right = routing.getRight(); + List sectionCodeList = routing.getParkSectionCodeList(); + for (int i = 0; i < sectionCodeList.size() - 1; i++) { + Section startSection = (Section) deviceMap.get(sectionCodeList.get(i).getSectionCode()); + Section endSection = (Section) deviceMap.get(sectionCodeList.get(i + 1).getSectionCode()); + //已创建 + boolean exist = false; + for (MapStationRunLevelVO vo : generatedStationRunLevelList) { + if (vo.isSameOf(startSection.getCode(), endSection.getCode())) { + exist = true; + break; + } + } + if (exist) { + continue; + } + int min = Math.min(startSection.getStation().getSn(), endSection.getStation().getSn()); + int max = Math.max(startSection.getStation().getSn(), endSection.getStation().getSn()); + int di = Math.abs(max - min); + if (di > 1) { // 间隔大于1,判断中间车站是否停车场/非正常车站 + for (Station station : stationList) { + if (station.getSn() > min && station.getSn() < max) { + BusinessExceptionAssertEnum.CI_GENERATE_ERROR + .assertTrue(station.isDepot() || station.isNoDepotAndNoNormalStand(), + String.format( + "交路[%s]下的站间运行等级[%s]数据间隔车站大于1且间隔中的车站[%s]是正常可停靠车站", + String.format("%s(%s)->%s(%s)", + routingStartSection.getStation().getName(), + routingStartSection.getName(), + routingEndSection.getStation().getName(), + routingEndSection.getName()), + String.format("%s(%s(%s))->%s(%s(%s))", + startSection.getStation().getName(), startSection.getName(), + startSection.getCode(), + endSection.getStation().getName(), endSection.getName(), + endSection.getCode()), + station.getName())); + } + } + } + // 创建 + MapStationRunLevelVO runLevelVO = new MapStationRunLevelVO(); + runLevelVO.setStartSectionCode(startSection.getCode()); + runLevelVO.setStartStationCode(startSection.getStation().getCode()); + runLevelVO.setEndSectionCode(endSection.getCode()); + runLevelVO.setEndStationCode(endSection.getStation().getCode()); + runLevelVO.setRight(right); + List routePaths = CalculateService.queryRoutePathsOnDirection(startSection, + endSection, right, 10); + if (CollectionUtils.isEmpty(routePaths)) { + // 未找到,反方向再找 + routePaths = CalculateService.queryRoutePathsOnDirection(startSection, endSection, !right, + 10); + if (!CollectionUtils.isEmpty(routePaths)) { + log.info(String.format("站间运行等级[%s]与交路[%s]方向相反,实际为[%s]", + String.format("%s(%s(%s))->%s(%s(%s))", + startSection.getStation().getName(), startSection.getName(), + startSection.getCode(), + endSection.getStation().getName(), endSection.getName(), endSection.getCode()), + String.format("%s(%s)->%s(%s)", + routingStartSection.getStation().getName(), routingStartSection.getName(), + routingEndSection.getStation().getName(), routingEndSection.getName()), + !right ? "右向" : "左向")); + runLevelVO.setRight(!right); + } + } + if (CollectionUtils.isEmpty(routePaths)) { + log.warn(String.format( + "站间运行等级数据生成失败:没有找到[%s(%s) ——> %s(%s)]对应方向[%s]的站间", + startSection.getStation().getName(), startSection.getName(), + endSection.getStation().getName(), endSection.getName(), right ? "右向" : "左向")); // errorList.add(String.format("站间运行等级数据生成失败:没有找到[%s(%s) ——> %s(%s)]对应方向[%s]的站间", // startSection.getStation().getName(), startSection.getName(), endSection.getStation().getName(), endSection.getName(), right ? "右向" : "左向")); - continue; - } - // 找到,计算距离 - float distance = routePaths.get(0).calculateDistance(); - runLevelVO.setDistance(distance); - runLevelVO.generateDefaultRunLevel(); - log.info(String.format("站间运行等级[%s]生成成功", - String.format("%s(%s(%s))->%s(%s(%s))", - startSection.getStation().getName(), startSection.getName(), startSection.getCode(), - endSection.getStation().getName(), endSection.getName(), endSection.getCode()))); - generatedStationRunLevelList.add(runLevelVO); - } + continue; } + // 找到,计算距离 + float distance = routePaths.get(0).calculateDistance(); + runLevelVO.setDistance(distance); + runLevelVO.generateDefaultRunLevel(); + log.info(String.format("站间运行等级[%s]生成成功", + String.format("%s(%s(%s))->%s(%s(%s))", + startSection.getStation().getName(), startSection.getName(), startSection.getCode(), + endSection.getStation().getName(), endSection.getName(), endSection.getCode()))); + generatedStationRunLevelList.add(runLevelVO); + } } + } - private void buildAutoSignalRouteConflict(List autoSignalList, List generatedRouteList) { - if (CollectionUtils.isEmpty(autoSignalList)) { - // 自动信号为空,返回 - return; - } - for (AutoSignal autoSignal : autoSignalList) { - Signal signal = autoSignal.getSignal(); - Section signalSection = signal.getSection(); - for (Route route : generatedRouteList) { - if (Objects.equals(route.getStart().getSection(), signalSection)) { - // 相同区段相反信号 - autoSignal.addConflictRoute(route); - continue; - } - if (!Objects.equals(route.getStart().isRight(), signal.isRight()) && - route.containSameSection(autoSignal.getSectionList())) { - // 信号机反向,包含相同区段 - autoSignal.addConflictRoute(route); - continue; - } - } - } + private void buildAutoSignalRouteConflict(List autoSignalList, + List generatedRouteList) { + if (CollectionUtils.isEmpty(autoSignalList)) { + // 自动信号为空,返回 + return; } - - /** - * 生成自动折返 - * - * @param tbSignalList - * @param generatedRouteList - * @param cycleCodeGenerator - * @param config - * @param errorList - * @return - */ - private List generateCycle(List tbSignalList, - List generatedRouteList, - CodeGenerator cycleCodeGenerator, - MapCiGenerateConfig config, List errorList) { - List cycleList = new ArrayList<>(); - if (CollectionUtils.isEmpty(tbSignalList)) { - errorList.add(String.format("自动折返数据生成失败:没有折返信号")); - return cycleList; + for (AutoSignal autoSignal : autoSignalList) { + Signal signal = autoSignal.getSignal(); + Section signalSection = signal.getSection(); + for (Route route : generatedRouteList) { + if (Objects.equals(route.getStart().getSection(), signalSection)) { + // 相同区段相反信号 + autoSignal.addConflictRoute(route); + continue; } - Map> signalRouteMap = this.buildSignalRouteMap(generatedRouteList); - for (Signal signal : tbSignalList) { - int number = 1; - List list = new ArrayList<>(); - List routeList = signalRouteMap.get(signal.getCode()); - if (CollectionUtils.isEmpty(routeList)) { - errorList.add(String.format("自动折返数据生成失败:没有以折返信号[%s(%s)]为始端的进路", - signal.getName(), signal.getCode())); - continue; - } else { - List tbRouteList = routeList.stream() - .filter(Route::isTurnBack) - .collect(Collectors.toList()); - if (CollectionUtils.isEmpty(tbRouteList)) { - errorList.add(String.format("自动折返数据生成失败:没有以折返信号[%s(%s)]为始端的折返进路", - signal.getName(), signal.getCode())); - continue; - } - for (Route tbRoute : tbRouteList) { - // 查询折返进路终端反向信号机 - Signal oppositeSignal = this.queryRouteEndOppositeSignal(tbRoute.getDestination()); - if (Objects.nonNull(oppositeSignal)) { - // 反向信号存在 - List oppositeRouteList = signalRouteMap.get(oppositeSignal.getCode()); - List basicRouteList = oppositeRouteList.stream() - .filter(route -> !route.isTurnBack()) - .collect(Collectors.toList()); - Route basicRoute = null; - for (Route route : basicRouteList) { - if (tbRoute.containConflictSwitch(route.getSwitchList())) { - basicRoute = route; - break; - } - } - if (Objects.isNull(basicRoute)) { - errorList.add(String.format("自动折返数据生成失败:折返进路[%s(%s)]的反向基本进路不存在", - tbRoute.getName(), tbRoute.getCode())); - continue; - } - // 存在,生成 - String code = cycleCodeGenerator.next(); - String name = String.format("%s-%s-%s", - signal.getName(), - basicRoute.getStart().getName(), - basicRoute.getDestination().getName()); - ++number; - Cycle cycle = new Cycle(code, name); - cycle.setTurnBack(tbRoute); - cycle.setBasic(basicRoute); - cycle.setTurnBackSection(oppositeSignal.getSection()); - cycle.setStation(cycle.getTurnBackSection().getDeviceStation()); - list.add(cycle); - } - } - } - if (list.size() == 2) { - // 生成了2条,判断是否需要生成全自动折返 - if (list.get(0).getTurnBackSection().isFirstTurnBack() || - list.get(1).getTurnBackSection().isFirstTurnBack()) { - // 有设置优先折返,生成全自动折返 - String code = cycleCodeGenerator.next(); - String name = String.format("%s-%s/%s-%s", - signal.getName(), - list.get(0).getBasic().getStart().getName(), - list.get(1).getBasic().getStart().getName(), - list.get(0).getTurnBack().getDestination().getName()); - ++number; - Cycle cycle = new Cycle(code, name); - cycle.setStation(list.get(0).getStation()); - cycle.setTurnBack(list.get(0).getTurnBack()); - cycle.setBasic(list.get(0).getBasic()); - cycle.setTurnBackSection(list.get(0).getTurnBackSection()); - cycle.setTurnBack2(list.get(1).getTurnBack()); - cycle.setBasic2(list.get(1).getBasic()); - cycle.setTurnBackSection2(list.get(1).getTurnBackSection()); - list.add(cycle); - } - } else if (list.size() > 2) { - log.error(String.format("自动折返数据生成异常:折返信号[%s(%s)]生成了[%s]条自动折返", - signal.getName(), signal.getCode(), list.size())); - } - log.debug(String.format("折返信号[%s(%s)]生成自动折返数据[%s]条", - signal.getName(), signal.getCode(), list.size())); - cycleList.addAll(list); + if (!Objects.equals(route.getStart().isRight(), signal.isRight()) && + route.containSameSection(autoSignal.getSectionList())) { + // 信号机反向,包含相同区段 + autoSignal.addConflictRoute(route); + continue; } - return cycleList; + } } + } - private Map> buildSignalRouteMap(List generatedRouteList) { - Map> signalRouteMap = new HashMap<>(); - for (Route route : generatedRouteList) { - List routeList = signalRouteMap.get(route.getStart().getCode()); - if (Objects.isNull(routeList)) { - routeList = new ArrayList<>(); - signalRouteMap.put(route.getStart().getCode(), routeList); - } - routeList.add(route); - } - return signalRouteMap; + /** + * 生成自动折返 + * + * @param tbSignalList + * @param generatedRouteList + * @param cycleCodeGenerator + * @param config + * @param errorList + * @return + */ + private List generateCycle(List tbSignalList, + List generatedRouteList, + CodeGenerator cycleCodeGenerator, + MapCiGenerateConfig config, List errorList) { + List cycleList = new ArrayList<>(); + if (CollectionUtils.isEmpty(tbSignalList)) { + errorList.add(String.format("自动折返数据生成失败:没有折返信号")); + return cycleList; } - - /** - * 生成折返进路 - * - * @param routeList - * @param routeCodeGenerator - * @param config - * @return - */ - private List generateTurnBackRoute(List routeList, - CodeGenerator routeCodeGenerator, - MapCiGenerateConfig config) { - List tbRouteList = new ArrayList<>(); - // 始端信号机的进路map - Map> signalRouteMap = this.buildSignalRouteMap(routeList); - // 遍历进路列表,判断需要生成的折返进路 - for (Route route : routeList) { - // 1,进路的最后区段是折返轨, - // 2,且进路存在道岔, - // 3,且折返轨存在反向信号机的反向进路, - // 4,且此反向进路的第一个道岔和进路的此道岔位置不同, - // 则生成折返进路 - boolean generate = false; - boolean right = route.getStart().isRight(); - Section lastRouteSection = route.getLastRouteSection(); - Signal endOppositeSignal = null; - if (lastRouteSection.isTurnBackTrack() && !CollectionUtils.isEmpty(route.getSwitchList())) { - endOppositeSignal = this.queryRouteEndOppositeSignal(route.getDestination()); - if (Objects.nonNull(endOppositeSignal)) { - List oppositeRouteList = signalRouteMap.get(endOppositeSignal.getCode()); - if (!CollectionUtils.isEmpty(oppositeRouteList)) { - for (Route opposite : oppositeRouteList) { - if (route.containConflictSwitch(opposite.getSwitchList())) { - generate = true; - break; - } - } - } - } - } - if (generate) { - String endName = route.getDestination().getName(); - if (config.isTbRouteNameUseEndOppositeSignalName()) { - endName = endOppositeSignal.getName(); - } - - String name = String.format("%s-%s", route.getStart().getName(), endName); - String code = routeCodeGenerator.next(); - Route tbRoute = new Route(code, name); - // 拷贝进路其他属性 - this.copyToTurnBackRoute(route, tbRoute, config.isRouteInterlockDoNotIncludeStandHoldTrain()); - tbRoute.setTurnBack(true); - // 如果生成进路按钮,折返进路按钮默认为终端信号机 - if (config.isRouteButton()) { - tbRoute.setDestinationButtonSignal(route.getDestination()); - } - tbRouteList.add(tbRoute); - } + Map> signalRouteMap = this.buildSignalRouteMap(generatedRouteList); + for (Signal signal : tbSignalList) { + int number = 1; + List list = new ArrayList<>(); + List routeList = signalRouteMap.get(signal.getCode()); + if (CollectionUtils.isEmpty(routeList)) { + errorList.add(String.format("自动折返数据生成失败:没有以折返信号[%s(%s)]为始端的进路", + signal.getName(), signal.getCode())); + continue; + } else { + List tbRouteList = routeList.stream() + .filter(Route::isTurnBack) + .collect(Collectors.toList()); + if (CollectionUtils.isEmpty(tbRouteList)) { + errorList.add(String.format("自动折返数据生成失败:没有以折返信号[%s(%s)]为始端的折返进路", + signal.getName(), signal.getCode())); + continue; } - log.info(String.format("生成折返进路[%s]条", tbRouteList.size())); - return tbRouteList; - } - - private void copyToTurnBackRoute(Route route, Route tbRoute, boolean noStandHold) { - tbRoute.setInterlockStation(route.getInterlockStation()); - tbRoute.setStart(route.getStart()); - tbRoute.setDestination(route.getDestination()); - tbRoute.setSectionList(route.getSectionList()); - tbRoute.setSwitchList(route.getSwitchList()); - tbRoute.setSetOverlapInCtc(route.isSetOverlapInCtc()); - tbRoute.setOverlap(route.getOverlap()); - tbRoute.setAspect(route.getAspect()); - // 根据信号机和区段是否同向,设置进路联锁自排和是否车队模式 - tbRoute.setFlt(route.isFlt()); - tbRoute.setArs(route.isArs()); - // 根据区段设置进路联锁站台相关元素 - if (!noStandHold) { - tbRoute.setStandHoldList(route.getStandHoldList()); - } - tbRoute.setPsdList(route.getPsdList()); - tbRoute.setEspList(route.getEspList()); - } - - /** - * 查询进路终端信号机的临近反向信号机 - * - * @param end - * @return - */ - private Signal queryRouteEndOppositeSignal(Signal end) { - Section endSection = end.getSection(); - boolean right = end.isRight(); - // 终端同区段的反向信号机 - Signal oeSignal = endSection.getSignalOf(!right); - if (Objects.isNull(oeSignal)) { - // 查询反向区段,如果反向区段是非道岔区段,且反向区段存在反向信号机 - Section frontSection = endSection.getSectionOf(!right); - if (Objects.nonNull(frontSection) && !frontSection.isSwitchTrack()) { - oeSignal = frontSection.getSignalOf(!right); - } - // 查询同向区段,如果同向区段存在反向信号机 - if (Objects.isNull(oeSignal)) { - Section next = endSection.getSectionOf(right); - if (Objects.nonNull(next)) { - oeSignal = next.getSignalOf(!right); - } - } - } - return oeSignal; - } - - /** - * 生成进路的敌对关系 - * - * @param routeList - */ - private void buildRouteConflict(List routeList) { - // 敌对进路:两进路方向相反,且始端信号机在同一区段或有共同区段,但无冲突道岔 - for (int i = 0; i < routeList.size(); i++) { - Route route1 = routeList.get(i); - for (int j = i + 1; j < routeList.size(); j++) { - Route route2 = routeList.get(j); - if (route1.containConflictRoute(route2)) { - continue; - } - boolean conflict = false; - if (!Objects.equals(route1.getStart().isRight(), route2.getStart().isRight())) { - // 方向相反进路 - if (Objects.equals(route1.getStart().getSection(), route2.getStart().getSection())) { - // 同一区段的相反信号机 - conflict = true; - } else { - // 进路包含相同区段或位置不同的道岔 - if (route1.containSameSection(route2.getSectionList()) && - !route1.containConflictSwitch(route2.getSwitchList())) { - conflict = true; - } - } - } - if (conflict) { - route1.addConflictRoute(route2); - route2.addConflictRoute(route1); - } - } - } - } - - /** - * 构造进路对象 - * - * @param code - * @param name - * @param start 始端信号机 - * @param end 终端信号机 - * @param endButton 建立方式为按钮点选方式时,终端按钮信号机 - * @param sectionPath - * @param routeOverlap - * @param alwaysGreen 进路始端信号是否总是开绿灯 - * @param noStandHold - * @param singleTrain - * @return - */ - private Route buildRoute(String code, String name, - Signal start, Signal end, Signal endButton, - SectionPath sectionPath, RouteOverlap routeOverlap, boolean alwaysGreen, boolean noStandHold, boolean singleTrain) { - Route route = new Route(code, name); - route.setInterlockStation(start.getInterlockStation()); - route.setStart(start); - route.setDestination(end); - route.setDestinationButtonSignal(endButton); - route.setSectionList(sectionPath.getSectionList()); - route.setSwitchList(sectionPath.getSwitchList()); - route.setOverlap(routeOverlap); - route.setSingleTrain(singleTrain); - SignalModel signalModel = start.getSignalModel(); - switch (signalModel) { - case RGY:{ - route.setAspect(SignalAspect.G); - if (!alwaysGreen && sectionPath.containRpSwitch()) { - route.setAspect(SignalAspect.Y); - } + for (Route tbRoute : tbRouteList) { + // 查询折返进路终端反向信号机 + Signal oppositeSignal = this.queryRouteEndOppositeSignal(tbRoute.getDestination()); + if (Objects.nonNull(oppositeSignal)) { + // 反向信号存在 + List oppositeRouteList = signalRouteMap.get(oppositeSignal.getCode()); + List basicRouteList = oppositeRouteList.stream() + .filter(route -> !route.isTurnBack()) + .collect(Collectors.toList()); + Route basicRoute = null; + for (Route route : basicRouteList) { + if (tbRoute.containConflictSwitch(route.getSwitchList())) { + basicRoute = route; break; + } } - case BW: - route.setAspect(SignalAspect.W); + if (Objects.isNull(basicRoute)) { + errorList.add( + String.format("自动折返数据生成失败:折返进路[%s(%s)]的反向基本进路不存在", + tbRoute.getName(), tbRoute.getCode())); + continue; + } + // 存在,生成 + String code = cycleCodeGenerator.next(); + String name = String.format("%s-%s-%s", + signal.getName(), + basicRoute.getStart().getName(), + basicRoute.getDestination().getName()); + ++number; + Cycle cycle = new Cycle(code, name); + cycle.setTurnBack(tbRoute); + cycle.setBasic(basicRoute); + cycle.setTurnBackSection(oppositeSignal.getSection()); + cycle.setStation(cycle.getTurnBackSection().getDeviceStation()); + list.add(cycle); + } + } + } + if (list.size() == 2) { + // 生成了2条,判断是否需要生成全自动折返 + if (list.get(0).getTurnBackSection().isFirstTurnBack() || + list.get(1).getTurnBackSection().isFirstTurnBack()) { + // 有设置优先折返,生成全自动折返 + String code = cycleCodeGenerator.next(); + String name = String.format("%s-%s/%s-%s", + signal.getName(), + list.get(0).getBasic().getStart().getName(), + list.get(1).getBasic().getStart().getName(), + list.get(0).getTurnBack().getDestination().getName()); + ++number; + Cycle cycle = new Cycle(code, name); + cycle.setStation(list.get(0).getStation()); + cycle.setTurnBack(list.get(0).getTurnBack()); + cycle.setBasic(list.get(0).getBasic()); + cycle.setTurnBackSection(list.get(0).getTurnBackSection()); + cycle.setTurnBack2(list.get(1).getTurnBack()); + cycle.setBasic2(list.get(1).getBasic()); + cycle.setTurnBackSection2(list.get(1).getTurnBackSection()); + list.add(cycle); + } + } else if (list.size() > 2) { + log.error(String.format("自动折返数据生成异常:折返信号[%s(%s)]生成了[%s]条自动折返", + signal.getName(), signal.getCode(), list.size())); + } + log.debug(String.format("折返信号[%s(%s)]生成自动折返数据[%s]条", + signal.getName(), signal.getCode(), list.size())); + cycleList.addAll(list); + } + return cycleList; + } + + private Map> buildSignalRouteMap(List generatedRouteList) { + Map> signalRouteMap = new HashMap<>(); + for (Route route : generatedRouteList) { + List routeList = signalRouteMap.get(route.getStart().getCode()); + if (Objects.isNull(routeList)) { + routeList = new ArrayList<>(); + signalRouteMap.put(route.getStart().getCode(), routeList); + } + routeList.add(route); + } + return signalRouteMap; + } + + /** + * 生成折返进路 + * + * @param routeList + * @param routeCodeGenerator + * @param config + * @return + */ + private List generateTurnBackRoute(List routeList, + CodeGenerator routeCodeGenerator, + MapCiGenerateConfig config) { + List tbRouteList = new ArrayList<>(); + // 始端信号机的进路map + Map> signalRouteMap = this.buildSignalRouteMap(routeList); + // 遍历进路列表,判断需要生成的折返进路 + for (Route route : routeList) { + // 1,进路的最后区段是折返轨, + // 2,且进路存在道岔, + // 3,且折返轨存在反向信号机的反向进路, + // 4,且此反向进路的第一个道岔和进路的此道岔位置不同, + // 则生成折返进路 + boolean generate = false; + boolean right = route.getStart().isRight(); + Section lastRouteSection = route.getLastRouteSection(); + Signal endOppositeSignal = null; + if (lastRouteSection.isTurnBackTrack() && !CollectionUtils.isEmpty(route.getSwitchList())) { + endOppositeSignal = this.queryRouteEndOppositeSignal(route.getDestination()); + if (Objects.nonNull(endOppositeSignal)) { + List oppositeRouteList = signalRouteMap.get(endOppositeSignal.getCode()); + if (!CollectionUtils.isEmpty(oppositeRouteList)) { + for (Route opposite : oppositeRouteList) { + if (route.containConflictSwitch(opposite.getSwitchList())) { + generate = true; break; - default: - throw BusinessExceptionAssertEnum.DATA_ERROR.exception(String.format("信号机[%s]型号[%s]不正确", - start.debugStr(), start.getSignalModel())); - } - route.setTurnBack(false); - // 根据信号机和区段是否同向,设置进路联锁自排和是否车队模式 - boolean ars = true; // 联锁自排 - boolean flt = false; // 车队 - if (start.isOppositeToSection()) { // 如果是反向进路,没有联锁自排功能 - if (!(start.getSection().isTurnBackTrack() && end.getSection().isNormalStandTrack())) { - // 始端信号机反向,且不是始端为折返轨,终端为正常站台轨 - ars = false; + } } + } } - RouteOverlap overlap = route.getOverlap(); - if (overlap != null && !overlap.isStraight()) { //如果延续保护不是直向,没有联锁自动触发 - ars = false; - } - for (Section section : route.getSectionList()) { - //进路中的区段类型与进路方向相反,说明不是常规运行进路,没有联锁自动触发 - if (section.isLeftLine() && route.isRight() || section.isRightLine() && !route.isRight()) { - ars = false; - break; - } - } - if (start.isSameDirectionToSection() && end.isSameDirectionToSection() && route.isStraight()) { - // 进路始端、终端信号机都是常规运行方向,且进路是直向进路,则为车队进路 - flt = true; + } + if (generate) { + String endName = route.getDestination().getName(); + if (config.isTbRouteNameUseEndOppositeSignalName()) { + endName = endOppositeSignal.getName(); } - route.setArs(ars); - route.setFlt(flt); - // 根据区段设置进路联锁站台相关元素 - List standHoldList = new ArrayList<>(); - List psdList = new ArrayList<>(); - List espList = new ArrayList<>(); - Section section = start.getSection(); - if (section.isNormalStandTrack()) { - // 始端信号机是正常站台出站信号机,构建站台扣车联锁 - standHoldList.addAll(section.getStandList()); - for (Stand stand : section.getStandList()) { - if (Objects.nonNull(stand.getPsd())) { - psdList.add(stand.getPsd()); - } - if (Objects.nonNull(stand.getEsp())) { - espList.add(stand.getEsp()); - } + String name = String.format("%s-%s", route.getStart().getName(), endName); + String code = routeCodeGenerator.next(); + Route tbRoute = new Route(code, name); + // 拷贝进路其他属性 + this.copyToTurnBackRoute(route, tbRoute, + config.isRouteInterlockDoNotIncludeStandHoldTrain()); + tbRoute.setTurnBack(true); + if (config.isTbRouteNameUseEndOppositeSignalName()) { + tbRoute.setDestinationButtonSignal(endOppositeSignal); + } + // 如果生成进路按钮,折返进路按钮默认为终端信号机 + if (config.isRouteButton()) { + tbRoute.setDestinationButtonSignal(route.getDestination()); + } + tbRouteList.add(tbRoute); + } + } + log.info(String.format("生成折返进路[%s]条", tbRouteList.size())); + return tbRouteList; + } + + private void copyToTurnBackRoute(Route route, Route tbRoute, boolean noStandHold) { + tbRoute.setInterlockStation(route.getInterlockStation()); + tbRoute.setStart(route.getStart()); + tbRoute.setDestination(route.getDestination()); + tbRoute.setSectionList(route.getSectionList()); + tbRoute.setSwitchList(route.getSwitchList()); + tbRoute.setSetOverlapInCtc(route.isSetOverlapInCtc()); + tbRoute.setOverlap(route.getOverlap()); + tbRoute.setAspect(route.getAspect()); + // 根据信号机和区段是否同向,设置进路联锁自排和是否车队模式 + tbRoute.setFlt(route.isFlt()); + tbRoute.setArs(route.isArs()); + // 根据区段设置进路联锁站台相关元素 + if (!noStandHold) { + tbRoute.setStandHoldList(route.getStandHoldList()); + } + tbRoute.setPsdList(route.getPsdList()); + tbRoute.setEspList(route.getEspList()); + } + + /** + * 查询进路终端信号机的临近反向信号机 + * + * @param end + * @return + */ + private Signal queryRouteEndOppositeSignal(Signal end) { + Section endSection = end.getSection(); + boolean right = end.isRight(); + // 终端同区段的反向信号机 + Signal oeSignal = endSection.getSignalOf(!right); + if (Objects.isNull(oeSignal)) { + // 查询反向区段,如果反向区段是非道岔区段,且反向区段存在反向信号机 + Section frontSection = endSection.getSectionOf(!right); + if (Objects.nonNull(frontSection) && !frontSection.isSwitchTrack()) { + oeSignal = frontSection.getSignalOf(!right); + } + // 查询同向区段,如果同向区段存在反向信号机 + if (Objects.isNull(oeSignal)) { + Section next = endSection.getSectionOf(right); + if (Objects.nonNull(next)) { + oeSignal = next.getSignalOf(!right); + } + } + } + return oeSignal; + } + + /** + * 生成进路的敌对关系 + * + * @param routeList + */ + private void buildRouteConflict(List routeList) { + // 敌对进路:两进路方向相反,且始端信号机在同一区段或有共同区段,但无冲突道岔 + for (int i = 0; i < routeList.size(); i++) { + Route route1 = routeList.get(i); + for (int j = i + 1; j < routeList.size(); j++) { + Route route2 = routeList.get(j); + if (route1.containConflictRoute(route2)) { + continue; + } + boolean conflict = false; + if (!Objects.equals(route1.getStart().isRight(), route2.getStart().isRight())) { + // 方向相反进路 + if (Objects.equals(route1.getStart().getSection(), route2.getStart().getSection())) { + // 同一区段的相反信号机 + conflict = true; + } else { + // 进路包含相同区段或位置不同的道岔 + if (route1.containSameSection(route2.getSectionList()) && + !route1.containConflictSwitch(route2.getSwitchList())) { + conflict = true; } + } } - List
sectionList = route.getSectionList(); - for (Section track : sectionList) { - if (track.isNormalStandTrack()) { - for (Stand stand : section.getStandList()) { - if (Objects.nonNull(stand.getPsd())) { - psdList.add(stand.getPsd()); - } - if (Objects.nonNull(stand.getEsp())) { - espList.add(stand.getEsp()); - } - } - } + if (conflict) { + route1.addConflictRoute(route2); + route2.addConflictRoute(route1); } - if (!noStandHold) { - route.setStandHoldList(standHoldList); + } + } + } + + /** + * 构造进路对象 + * + * @param code + * @param name + * @param start 始端信号机 + * @param end 终端信号机 + * @param endButton 建立方式为按钮点选方式时,终端按钮信号机 + * @param sectionPath + * @param routeOverlap + * @param alwaysGreen 进路始端信号是否总是开绿灯 + * @param noStandHold + * @param singleTrain + * @return + */ + private Route buildRoute(String code, String name, + Signal start, Signal end, Signal endButton, + SectionPath sectionPath, RouteOverlap routeOverlap, boolean alwaysGreen, boolean noStandHold, + boolean singleTrain) { + Route route = new Route(code, name); + route.setInterlockStation(start.getInterlockStation()); + route.setStart(start); + route.setDestination(end); + route.setDestinationButtonSignal(endButton); + route.setSectionList(sectionPath.getSectionList()); + route.setSwitchList(sectionPath.getSwitchList()); + route.setOverlap(routeOverlap); + route.setSingleTrain(singleTrain); + SignalModel signalModel = start.getSignalModel(); + switch (signalModel) { + case RGY: { + route.setAspect(SignalAspect.G); + if (!alwaysGreen && sectionPath.containRpSwitch()) { + route.setAspect(SignalAspect.Y); } - route.setPsdList(psdList); - route.setEspList(espList); - return route; + break; + } + case BW: + route.setAspect(SignalAspect.W); + break; + default: + throw BusinessExceptionAssertEnum.DATA_ERROR.exception( + String.format("信号机[%s]型号[%s]不正确", + start.debugStr(), start.getSignalModel())); + } + route.setTurnBack(false); + // 根据信号机和区段是否同向,设置进路联锁自排和是否车队模式 + boolean ars = true; // 联锁自排 + boolean flt = false; // 车队 + if (start.isOppositeToSection()) { // 如果是反向进路,没有联锁自排功能 + if (!(start.getSection().isTurnBackTrack() && end.getSection().isNormalStandTrack())) { + // 始端信号机反向,且不是始端为折返轨,终端为正常站台轨 + ars = false; + } + } + RouteOverlap overlap = route.getOverlap(); + if (overlap != null && !overlap.isStraight()) { //如果延续保护不是直向,没有联锁自动触发 + ars = false; + } + for (Section section : route.getSectionList()) { + //进路中的区段类型与进路方向相反,说明不是常规运行进路,没有联锁自动触发 + if (section.isLeftLine() && route.isRight() || section.isRightLine() && !route.isRight()) { + ars = false; + break; + } + } + if (start.isSameDirectionToSection() && end.isSameDirectionToSection() && route.isStraight()) { + // 进路始端、终端信号机都是常规运行方向,且进路是直向进路,则为车队进路 + flt = true; } - /** - * 构建车辆段进路 - */ - private Route buildRouteDepot(String code, String name, Signal start, Signal end, - Signal endButton, SectionPath sectionPath, SignalAspect signalAspect) { - Route route = new Route(code, name); - route.setInterlockStation(start.getInterlockStation()); - route.setStart(start); - route.setDestination(end); - route.setDestinationButtonSignal(endButton); - route.setSectionList(sectionPath.getSectionList()); - route.setSwitchList(sectionPath.getSwitchList()); - route.setAspect(signalAspect); - route.setPsdList(Collections.emptyList()); - route.setEspList(Collections.emptyList()); - return route; + route.setArs(ars); + route.setFlt(flt); + // 根据区段设置进路联锁站台相关元素 + List standHoldList = new ArrayList<>(); + List psdList = new ArrayList<>(); + List espList = new ArrayList<>(); + Section section = start.getSection(); + if (section.isNormalStandTrack()) { + // 始端信号机是正常站台出站信号机,构建站台扣车联锁 + standHoldList.addAll(section.getStandList()); + for (Stand stand : section.getStandList()) { + if (Objects.nonNull(stand.getPsd())) { + psdList.add(stand.getPsd()); + } + if (Objects.nonNull(stand.getEsp())) { + espList.add(stand.getEsp()); + } + } } + List
sectionList = route.getSectionList(); + for (Section track : sectionList) { + if (track.isNormalStandTrack()) { + for (Stand stand : section.getStandList()) { + if (Objects.nonNull(stand.getPsd())) { + psdList.add(stand.getPsd()); + } + if (Objects.nonNull(stand.getEsp())) { + espList.add(stand.getEsp()); + } + } + } + } + if (!noStandHold) { + route.setStandHoldList(standHoldList); + } + route.setPsdList(psdList); + route.setEspList(espList); + return route; + } - /** - * 根据路径创建延续保护 - * - * @param end 延续保护始端信号机 - * @param overlapCodeGenerator code生成器 - * @param config 配置 - * @param errorList - * @return - */ - private List generateOverlap(Signal end, CodeGenerator overlapCodeGenerator, - MapCiGenerateConfig config, List errorList) { - boolean right = end.isRight(); - List overlapPathList = new ArrayList<>(); - Section signalSection = end.getSection(); - getOverlapPathOf(signalSection.getSectionOf(right), right, - new SectionPath(right), overlapPathList, config, errorList); - List overlapList = new ArrayList<>(); - if (!CollectionUtils.isEmpty(overlapPathList)) { - if (config.isOverlapSignalOppositeSwitchNpOnly() && end.isOppositeToSection()) { - // 如果信号机和区段反向,且配置反向信号机延续保护只包含道岔定位情况,删除道岔反位数据 - List removeList = new ArrayList<>(); - for (SectionPath sectionPath : overlapPathList) { - if (sectionPath.containRpSwitch()) { - removeList.add(sectionPath); - } - } - if (!CollectionUtils.isEmpty(removeList)) { - overlapPathList.removeAll(removeList); - } - } - if (config.isRouteApartByOverlap()) { // 一种延续保护一条进路,延续保护分开创建 - // 遍历路径,每个生成一个延续保护 - for (SectionPath sectionPath : overlapPathList) { - String deviceName; - Section lastSection = sectionPath.getLastSection(); - if (lastSection.isSwitchTrack()) { - deviceName = lastSection.getRelSwitch().getName(); - } else { - List
logicList = new ArrayList<>(lastSection.getLogicList()); - if (!CollectionUtils.isEmpty(logicList)) { - // 倒序,取第一个逻辑区段名 - if (right) { - Collections.reverse(logicList); - } - deviceName = lastSection.getName() + logicList.get(0).getName(); - } else { - deviceName = lastSection.getName(); - } - } - RouteOverlap routeOverlap = new RouteOverlap(overlapCodeGenerator.next(), - String.format("O_%s_%s", end.getName(), deviceName)); - routeOverlap.setPathList(Arrays.asList(sectionPath)); - routeOverlap.setSection(signalSection); - routeOverlap.setSignal(end); - routeOverlap.setRight(right); - routeOverlap.setDelayReleaseTime(config.getOverlapReleaseTime()); // 默认延时解锁时间 + /** + * 构建车辆段进路 + */ + private Route buildRouteDepot(String code, String name, Signal start, Signal end, + Signal endButton, SectionPath sectionPath, SignalAspect signalAspect) { + Route route = new Route(code, name); + route.setInterlockStation(start.getInterlockStation()); + route.setStart(start); + route.setDestination(end); + route.setDestinationButtonSignal(endButton); + route.setSectionList(sectionPath.getSectionList()); + route.setSwitchList(sectionPath.getSwitchList()); + route.setAspect(signalAspect); + route.setPsdList(Collections.emptyList()); + route.setEspList(Collections.emptyList()); + return route; + } - if (signalSection.getLen() >= 250) { // 长区段根据长度生成 - if (signalSection.getLen() >= 250 && signalSection.getLen() <= 400) { - if (config.getOverlapReleaseTime() < 40) { - routeOverlap.setDelayReleaseTime(40); - } - } else { - int time = (int) (signalSection.getLen() / 15); - if (config.getOverlapReleaseTime() < time) { - routeOverlap.setDelayReleaseTime(time); - } - } - } - overlapList.add(routeOverlap); - } - // 若存在重名,根据道岔位置修改名称 - Map> overlapMap = new HashMap<>(); - for (RouteOverlap routeOverlap : overlapList) { - List tempList = overlapMap.get(routeOverlap.getName()); - if (Objects.isNull(tempList)) { - tempList = new ArrayList<>(); - overlapMap.put(routeOverlap.getName(), tempList); - } - tempList.add(routeOverlap); - } - overlapMap.forEach((name, list) -> { - if (list.size() == 2) { - for (RouteOverlap routeOverlap : list) { - if (routeOverlap.containRpSwitch()) { - routeOverlap.setName(routeOverlap.getName() + "_2"); - } else { - routeOverlap.setName(routeOverlap.getName() + "_1"); - } - } - } else if (list.size() > 2) { - log.warn(String.format("延续保护名称[%s],同名的延续保护大于2", name)); - } - }); + /** + * 根据路径创建延续保护 + * + * @param end 延续保护始端信号机 + * @param overlapCodeGenerator code生成器 + * @param config 配置 + * @param errorList + * @return + */ + private List generateOverlap(Signal end, CodeGenerator overlapCodeGenerator, + MapCiGenerateConfig config, List errorList) { + boolean right = end.isRight(); + List overlapPathList = new ArrayList<>(); + Section signalSection = end.getSection(); + getOverlapPathOf(signalSection.getSectionOf(right), right, + new SectionPath(right), overlapPathList, config, errorList); + List overlapList = new ArrayList<>(); + if (!CollectionUtils.isEmpty(overlapPathList)) { + if (config.isOverlapSignalOppositeSwitchNpOnly() && end.isOppositeToSection()) { + // 如果信号机和区段反向,且配置反向信号机延续保护只包含道岔定位情况,删除道岔反位数据 + List removeList = new ArrayList<>(); + for (SectionPath sectionPath : overlapPathList) { + if (sectionPath.containRpSwitch()) { + removeList.add(sectionPath); + } + } + if (!CollectionUtils.isEmpty(removeList)) { + overlapPathList.removeAll(removeList); + } + } + if (config.isRouteApartByOverlap()) { // 一种延续保护一条进路,延续保护分开创建 + // 遍历路径,每个生成一个延续保护 + for (SectionPath sectionPath : overlapPathList) { + String deviceName; + Section lastSection = sectionPath.getLastSection(); + if (lastSection.isSwitchTrack()) { + deviceName = lastSection.getRelSwitch().getName(); + } else { + List
logicList = new ArrayList<>(lastSection.getLogicList()); + if (!CollectionUtils.isEmpty(logicList)) { + // 倒序,取第一个逻辑区段名 + if (right) { + Collections.reverse(logicList); + } + deviceName = lastSection.getName() + logicList.get(0).getName(); } else { - RouteOverlap routeOverlap = new RouteOverlap(overlapCodeGenerator.next(), - String.format("O_%s", end.getName())); - routeOverlap.setPathList(overlapPathList); - routeOverlap.setSection(signalSection); - routeOverlap.setDelayReleaseTime(config.getOverlapReleaseTime()); // 默认延时解锁时间 - routeOverlap.setSignal(end); - routeOverlap.setRight(right); - // 是否触发式延续保护 - if (config.isOverlapSettingByTrigger()) { - List triggerPathList = new ArrayList<>(); - Section section = signalSection; - // 反方向找触发区段 - this.getOverlapTriggerPathOf(end, section, !right, new SectionPath(!right), triggerPathList); - routeOverlap.setTriggerPathList(triggerPathList); - } - overlapList.add(routeOverlap); + deviceName = lastSection.getName(); } - } - // 处理延续保护只有区段且区段有逻辑区段的情况(延续保护区段更换为逻辑区段) - for (RouteOverlap overlap : overlapList) { - List pathList = overlap.getPathList(); - for (SectionPath sectionPath : pathList) { - if (CollectionUtils.isEmpty(sectionPath.getSwitchList())) { - // 非道岔延续保护 - List
logicOverlapList = new ArrayList<>(); - List
sectionList = sectionPath.getSectionList(); - Section section = sectionList.get(0); - List
logicList = section.getLogicList(); - if (!CollectionUtils.isEmpty(logicList)) { - Section logic = logicList.get(0); - if (!end.isRight()) { - logic = logicList.get(logicList.size() - 1); - } - logicOverlapList.add(logic); - } - sectionPath.setLogicList(logicOverlapList); - } - } - } - return overlapList; - } + } + RouteOverlap routeOverlap = new RouteOverlap(overlapCodeGenerator.next(), + String.format("O_%s_%s", end.getName(), deviceName)); + routeOverlap.setPathList(Arrays.asList(sectionPath)); + routeOverlap.setSection(signalSection); + routeOverlap.setSignal(end); + routeOverlap.setRight(right); + routeOverlap.setDelayReleaseTime(config.getOverlapReleaseTime()); // 默认延时解锁时间 - private void getOverlapTriggerPathOf(Signal end, Section section, - boolean right, SectionPath tempPath, - List triggerPathList) { - if (Objects.isNull(section)) { // 找到尽头 - return; - } - if (!CollectionUtils.isEmpty(tempPath.getSectionList())) { - Signal sameDirectionSignal = tempPath.getLastSection().getSignalOf(!right); - if (Objects.nonNull(sameDirectionSignal) && !Objects.equals(end, sameDirectionSignal)) { - // 找到,返回 - triggerPathList.add(tempPath); - return; - } - } - tempPath.addSection(section); - if (section.isSwitchTrack()) { // 道岔区段 - Switch relSwitch = section.getRelSwitch(); - if (relSwitch.isA(section)) { - // 路径存在两种情况,道岔定位从A->B和道岔反位从A->C - // 产生分化递归 - SectionPath npPath = tempPath.cloneNew();// 定位路径 - npPath.addSection(relSwitch.getB()); - npPath.addSwitchElement(new SwitchElement(relSwitch, true)); - getOverlapTriggerPathOf(end, relSwitch.getB().getSectionOf(right), right, - npPath, triggerPathList); - SectionPath rpPath = tempPath.cloneNew();// 反位路径 - rpPath.addSection(relSwitch.getC()); - rpPath.addSwitchElement(new SwitchElement(relSwitch, false)); - getOverlapTriggerPathOf(end, relSwitch.getC().getSectionOf(right), right, - rpPath, triggerPathList); - } else if (relSwitch.isB(section)) { - // 只有一条路径,从B->A,道岔定位 - tempPath.addSection(relSwitch.getA()); - tempPath.addSwitchElement(new SwitchElement(relSwitch, true)); - getOverlapTriggerPathOf(end, relSwitch.getA().getSectionOf(right), right, - tempPath, triggerPathList); - } else if (relSwitch.isC(section)) { - // 只有一条路径,从C->A,道岔反位 - tempPath.addSection(relSwitch.getA()); - tempPath.addSwitchElement(new SwitchElement(relSwitch, false)); - getOverlapTriggerPathOf(end, relSwitch.getA().getSectionOf(right), right, - tempPath, triggerPathList); + if (signalSection.getLen() >= 250) { // 长区段根据长度生成 + if (signalSection.getLen() >= 250 && signalSection.getLen() <= 400) { + if (config.getOverlapReleaseTime() < 40) { + routeOverlap.setDelayReleaseTime(40); + } } else { - log.error(String.format("地图基础数据有错误:区段[%s(%s)]关联了道岔[%s(%s)],却不是此道岔的关联区段", - section.getName(), section.getCode(), - relSwitch.getName(), relSwitch.getCode())); - return; + int time = (int) (signalSection.getLen() / 15); + if (config.getOverlapReleaseTime() < time) { + routeOverlap.setDelayReleaseTime(time); + } } - } else { - getOverlapTriggerPathOf(end, section.getSectionOf(right), right, - tempPath, triggerPathList); + } + overlapList.add(routeOverlap); } + // 若存在重名,根据道岔位置修改名称 + Map> overlapMap = new HashMap<>(); + for (RouteOverlap routeOverlap : overlapList) { + List tempList = overlapMap.get(routeOverlap.getName()); + if (Objects.isNull(tempList)) { + tempList = new ArrayList<>(); + overlapMap.put(routeOverlap.getName(), tempList); + } + tempList.add(routeOverlap); + } + overlapMap.forEach((name, list) -> { + if (list.size() == 2) { + for (RouteOverlap routeOverlap : list) { + if (routeOverlap.containRpSwitch()) { + routeOverlap.setName(routeOverlap.getName() + "_2"); + } else { + routeOverlap.setName(routeOverlap.getName() + "_1"); + } + } + } else if (list.size() > 2) { + log.warn(String.format("延续保护名称[%s],同名的延续保护大于2", name)); + } + }); + } else { + RouteOverlap routeOverlap = new RouteOverlap(overlapCodeGenerator.next(), + String.format("O_%s", end.getName())); + routeOverlap.setPathList(overlapPathList); + routeOverlap.setSection(signalSection); + routeOverlap.setDelayReleaseTime(config.getOverlapReleaseTime()); // 默认延时解锁时间 + routeOverlap.setSignal(end); + routeOverlap.setRight(right); + // 是否触发式延续保护 + if (config.isOverlapSettingByTrigger()) { + List triggerPathList = new ArrayList<>(); + Section section = signalSection; + // 反方向找触发区段 + this.getOverlapTriggerPathOf(end, section, !right, new SectionPath(!right), + triggerPathList); + routeOverlap.setTriggerPathList(triggerPathList); + } + overlapList.add(routeOverlap); + } } - - /** - * 获取延续保护路径 - * - * @param section - * @param right 方向 - * @param tempPath 临时路径 - * @param overlapPathList 最终结果列表 - * @param config 生成配置参数 - * @param errorList - */ - private void getOverlapPathOf(Section section, boolean right, - SectionPath tempPath, List overlapPathList, - MapCiGenerateConfig config, List errorList) { - if (!CollectionUtils.isEmpty(tempPath.getSectionList())) { // 已经有路径 - Section lastSection = tempPath.getLastSection(); - if (Objects.isNull(section) || - !section.isSwitchTrack() || - !lastSection.isSwitchTrack()) { - // 且后面的是尽头或路径最后已经是非道岔区段,构建成功,返回 - overlapPathList.add(tempPath); - return; - } else if (tempPath.getTotalLen() > config.getOverlapMinLen()) { - // 延续保护长度已经足够,返回 - overlapPathList.add(tempPath); - return; + // 处理延续保护只有区段且区段有逻辑区段的情况(延续保护区段更换为逻辑区段) + for (RouteOverlap overlap : overlapList) { + List pathList = overlap.getPathList(); + for (SectionPath sectionPath : pathList) { + if (CollectionUtils.isEmpty(sectionPath.getSwitchList())) { + // 非道岔延续保护 + List
logicOverlapList = new ArrayList<>(); + List
sectionList = sectionPath.getSectionList(); + Section section = sectionList.get(0); + List
logicList = section.getLogicList(); + if (!CollectionUtils.isEmpty(logicList)) { + Section logic = logicList.get(0); + if (!end.isRight()) { + logic = logicList.get(logicList.size() - 1); } - } else if (Objects.isNull(section)) { // 如果区段不存在,就没有延续保护区段 - return; - } else if (config.isOverlapOnlySwitch() && !section.isSwitchTrack()) { // 如果只构建道岔延续保护,不是道岔区段,不构建,返回 - return; + logicOverlapList.add(logic); + } + sectionPath.setLogicList(logicOverlapList); } - tempPath.addSection(section); - if (section.isSwitchTrack()) { // 道岔区段 - Switch relSwitch = section.getRelSwitch(); - Switch linkedSwitch = relSwitch.queryLinkedSwitch(); + } + } + return overlapList; + } + + private void getOverlapTriggerPathOf(Signal end, Section section, + boolean right, SectionPath tempPath, + List triggerPathList) { + if (Objects.isNull(section)) { // 找到尽头 + return; + } + if (!CollectionUtils.isEmpty(tempPath.getSectionList())) { + Signal sameDirectionSignal = tempPath.getLastSection().getSignalOf(!right); + if (Objects.nonNull(sameDirectionSignal) && !Objects.equals(end, sameDirectionSignal)) { + // 找到,返回 + triggerPathList.add(tempPath); + return; + } + } + tempPath.addSection(section); + if (section.isSwitchTrack()) { // 道岔区段 + Switch relSwitch = section.getRelSwitch(); + if (relSwitch.isA(section)) { + // 路径存在两种情况,道岔定位从A->B和道岔反位从A->C + // 产生分化递归 + SectionPath npPath = tempPath.cloneNew();// 定位路径 + npPath.addSection(relSwitch.getB()); + npPath.addSwitchElement(new SwitchElement(relSwitch, true)); + getOverlapTriggerPathOf(end, relSwitch.getB().getSectionOf(right), right, + npPath, triggerPathList); + SectionPath rpPath = tempPath.cloneNew();// 反位路径 + rpPath.addSection(relSwitch.getC()); + rpPath.addSwitchElement(new SwitchElement(relSwitch, false)); + getOverlapTriggerPathOf(end, relSwitch.getC().getSectionOf(right), right, + rpPath, triggerPathList); + } else if (relSwitch.isB(section)) { + // 只有一条路径,从B->A,道岔定位 + tempPath.addSection(relSwitch.getA()); + tempPath.addSwitchElement(new SwitchElement(relSwitch, true)); + getOverlapTriggerPathOf(end, relSwitch.getA().getSectionOf(right), right, + tempPath, triggerPathList); + } else if (relSwitch.isC(section)) { + // 只有一条路径,从C->A,道岔反位 + tempPath.addSection(relSwitch.getA()); + tempPath.addSwitchElement(new SwitchElement(relSwitch, false)); + getOverlapTriggerPathOf(end, relSwitch.getA().getSectionOf(right), right, + tempPath, triggerPathList); + } else { + log.error(String.format( + "地图基础数据有错误:区段[%s(%s)]关联了道岔[%s(%s)],却不是此道岔的关联区段", + section.getName(), section.getCode(), + relSwitch.getName(), relSwitch.getCode())); + return; + } + } else { + getOverlapTriggerPathOf(end, section.getSectionOf(right), right, + tempPath, triggerPathList); + } + } + + /** + * 获取延续保护路径 + * + * @param section + * @param right 方向 + * @param tempPath 临时路径 + * @param overlapPathList 最终结果列表 + * @param config 生成配置参数 + * @param errorList + */ + private void getOverlapPathOf(Section section, boolean right, + SectionPath tempPath, List overlapPathList, + MapCiGenerateConfig config, List errorList) { + if (!CollectionUtils.isEmpty(tempPath.getSectionList())) { // 已经有路径 + Section lastSection = tempPath.getLastSection(); + if (Objects.isNull(section) || + !section.isSwitchTrack() || + !lastSection.isSwitchTrack()) { + // 且后面的是尽头或路径最后已经是非道岔区段,构建成功,返回 + overlapPathList.add(tempPath); + return; + } else if (tempPath.getTotalLen() > config.getOverlapMinLen()) { + // 延续保护长度已经足够,返回 + overlapPathList.add(tempPath); + return; + } + } else if (Objects.isNull(section)) { // 如果区段不存在,就没有延续保护区段 + return; + } else if (config.isOverlapOnlySwitch() + && !section.isSwitchTrack()) { // 如果只构建道岔延续保护,不是道岔区段,不构建,返回 + return; + } + tempPath.addSection(section); + if (section.isSwitchTrack()) { // 道岔区段 + Switch relSwitch = section.getRelSwitch(); + Switch linkedSwitch = relSwitch.queryLinkedSwitch(); // if (config.isCoupleSwitch()) { // linkedSwitch = relSwitch.queryLinkedSwitch(); // } - if (relSwitch.isA(section)) { - // 路径存在两种情况,道岔定位从A->B和道岔反位从A->C - // 产生分化递归 - SectionPath npPath = tempPath.cloneNew();// 定位路径 - npPath.addSection(relSwitch.getB()); - npPath.addSwitchElement(new SwitchElement(relSwitch, true)); - if (!config.isGenerateFls() && Objects.nonNull(linkedSwitch)) { - npPath.addSwitchElement(new SwitchElement(linkedSwitch, true)); - } - getOverlapPathOf(relSwitch.getB().getSectionOf(right), right, - npPath, overlapPathList, config, errorList); - if (!config.isOverlapSwitchNpOnly()) { // 如果非只构建道岔定位的延续保护 - SectionPath rpPath = tempPath.cloneNew();// 反位路径 - rpPath.addSection(relSwitch.getC()); - rpPath.addSwitchElement(new SwitchElement(relSwitch, false)); - if (!config.isGenerateFls() && Objects.nonNull(linkedSwitch)) { - // 如果有联动道岔,且配置只构建一个道岔,这里添加上联动道岔 - rpPath.addSwitchElement(new SwitchElement(linkedSwitch, false)); - } + if (relSwitch.isA(section)) { + // 路径存在两种情况,道岔定位从A->B和道岔反位从A->C + // 产生分化递归 + SectionPath npPath = tempPath.cloneNew();// 定位路径 + npPath.addSection(relSwitch.getB()); + npPath.addSwitchElement(new SwitchElement(relSwitch, true)); + if (!config.isGenerateFls() && Objects.nonNull(linkedSwitch)) { + npPath.addSwitchElement(new SwitchElement(linkedSwitch, true)); + } + getOverlapPathOf(relSwitch.getB().getSectionOf(right), right, + npPath, overlapPathList, config, errorList); + if (!config.isOverlapSwitchNpOnly()) { // 如果非只构建道岔定位的延续保护 + SectionPath rpPath = tempPath.cloneNew();// 反位路径 + rpPath.addSection(relSwitch.getC()); + rpPath.addSwitchElement(new SwitchElement(relSwitch, false)); + if (!config.isGenerateFls() && Objects.nonNull(linkedSwitch)) { + // 如果有联动道岔,且配置只构建一个道岔,这里添加上联动道岔 + rpPath.addSwitchElement(new SwitchElement(linkedSwitch, false)); + } // if (config.isCoupleSwitch()) { - // 如果是同一道岔计轴,添加另一道岔定位 - Switch otherSwitch = relSwitch.queryAxleRelatedOtherSwitch(); - if (!config.isGenerateFls() && Objects.nonNull(otherSwitch) && relSwitch.isBConnectTo(otherSwitch)) { - rpPath.addSwitchElement(new SwitchElement(otherSwitch, true)); - } + // 如果是同一道岔计轴,添加另一道岔定位 + Switch otherSwitch = relSwitch.queryAxleRelatedOtherSwitch(); + if (!config.isGenerateFls() && Objects.nonNull(otherSwitch) && relSwitch.isBConnectTo( + otherSwitch)) { + rpPath.addSwitchElement(new SwitchElement(otherSwitch, true)); + } // } - getOverlapPathOf(relSwitch.getC().getSectionOf(right), right, - rpPath, overlapPathList, config, errorList); - } - } else if (relSwitch.isB(section)) { - // 只有一条路径,从B->A,道岔定位 - tempPath.addSection(relSwitch.getA()); - tempPath.addSwitchElement(new SwitchElement(relSwitch, true)); - if (!config.isGenerateFls() && Objects.nonNull(linkedSwitch)) { - tempPath.addSwitchElement(new SwitchElement(linkedSwitch, true)); - } - getOverlapPathOf(relSwitch.getA().getSectionOf(right), right, - tempPath, overlapPathList, config, errorList); - } else if (relSwitch.isC(section)) { - // 只有一条路径,从C->A,道岔反位 - tempPath.addSection(relSwitch.getA()); - tempPath.addSwitchElement(new SwitchElement(relSwitch, false)); + getOverlapPathOf(relSwitch.getC().getSectionOf(right), right, + rpPath, overlapPathList, config, errorList); + } + } else if (relSwitch.isB(section)) { + // 只有一条路径,从B->A,道岔定位 + tempPath.addSection(relSwitch.getA()); + tempPath.addSwitchElement(new SwitchElement(relSwitch, true)); + if (!config.isGenerateFls() && Objects.nonNull(linkedSwitch)) { + tempPath.addSwitchElement(new SwitchElement(linkedSwitch, true)); + } + getOverlapPathOf(relSwitch.getA().getSectionOf(right), right, + tempPath, overlapPathList, config, errorList); + } else if (relSwitch.isC(section)) { + // 只有一条路径,从C->A,道岔反位 + tempPath.addSection(relSwitch.getA()); + tempPath.addSwitchElement(new SwitchElement(relSwitch, false)); // if (config.isCoupleSwitch()) { - // 如果是同一道岔计轴,添加另一道岔定位 - Switch otherSwitch = relSwitch.queryAxleRelatedOtherSwitch(); - if (!config.isGenerateFls() && Objects.nonNull(otherSwitch)) { - tempPath.addSwitchElement(new SwitchElement(otherSwitch, true)); - } + // 如果是同一道岔计轴,添加另一道岔定位 + Switch otherSwitch = relSwitch.queryAxleRelatedOtherSwitch(); + if (!config.isGenerateFls() && Objects.nonNull(otherSwitch)) { + tempPath.addSwitchElement(new SwitchElement(otherSwitch, true)); + } // } - getOverlapPathOf(relSwitch.getA().getSectionOf(right), right, - tempPath, overlapPathList, config, errorList); - } else { - errorList.add(String.format("地图基础数据有错误:区段[%s(%s)]关联了道岔[%s(%s)],却不是此道岔的关联区段", - section.getName(), section.getCode(), - relSwitch.getName(), relSwitch.getCode())); - return; - } - } else { - getOverlapPathOf(section.getSectionOf(right), right, tempPath, overlapPathList, config, errorList); - } + getOverlapPathOf(relSwitch.getA().getSectionOf(right), right, + tempPath, overlapPathList, config, errorList); + } else { + errorList.add(String.format( + "地图基础数据有错误:区段[%s(%s)]关联了道岔[%s(%s)],却不是此道岔的关联区段", + section.getName(), section.getCode(), + relSwitch.getName(), relSwitch.getCode())); + return; + } + } else { + getOverlapPathOf(section.getSectionOf(right), right, tempPath, overlapPathList, config, + errorList); } + } - /** - * 获取可走的进路路径 - * - * @param section 下一个区段 - * @param ground 是否查询地面信号 - * @param tempPath 临时路径 - * @param routePathList 最终结果 - * @param config 生成配置参数 - * @param errorList 错误信息 - */ - private void getRoutePathOf(Signal startSignal, Section section, boolean ground, - SectionPath tempPath, List routePathList, - MapCiGenerateConfig config, List errorList) { - boolean right = startSignal.isRight(); - if (!CollectionUtils.isEmpty(tempPath.getSectionList())) { - // 兼容在道岔区段的信号机 - Signal signal = tempPath.getLastSection().getSignalOf(right); - if (Objects.nonNull(signal)) { // 找到,添加路径,返回 - if (ground) { // 如果是地面信号,需要非虚拟信号机 - if (!signal.isVirtual() && !signal.isPassingSignal()) { - routePathList.add(tempPath); - return; - } - } else { // 不是生成地面信号,只要是进路终端或非通过信号机即可 - if (signal.isRouteEnd() || !signal.isPassingSignal()) { - routePathList.add(tempPath); - return; - } - } - } - } - if (Objects.isNull(section)) { - // 找到尽头也没有构成进路,异常 - log.error(String.format("始端信号机[%s(%s)]:找到尽头也没有构成进路,所寻路径为[%s]", - startSignal.getName(), startSignal.getCode(), - tempPath.getSectionPathString())); - errorList.add(String.format("始端信号机[%s(%s)]:找到尽头也没有构成进路,所寻路径为[%s]", - startSignal.getName(), startSignal.getCode(), - tempPath.getSectionPathString())); + /** + * 获取可走的进路路径 + * + * @param section 下一个区段 + * @param ground 是否查询地面信号 + * @param tempPath 临时路径 + * @param routePathList 最终结果 + * @param config 生成配置参数 + * @param errorList 错误信息 + */ + private void getRoutePathOf(Signal startSignal, Section section, boolean ground, + SectionPath tempPath, List routePathList, + MapCiGenerateConfig config, List errorList) { + boolean right = startSignal.isRight(); + if (!CollectionUtils.isEmpty(tempPath.getSectionList())) { + // 兼容在道岔区段的信号机 + Signal signal = tempPath.getLastSection().getSignalOf(right); + if (Objects.nonNull(signal)) { // 找到,添加路径,返回 + if (ground) { // 如果是地面信号,需要非虚拟信号机 + if (!signal.isVirtual() && !signal.isPassingSignal()) { + routePathList.add(tempPath); return; + } + } else { // 不是生成地面信号,只要是进路终端或非通过信号机即可 + if (signal.isRouteEnd() || !signal.isPassingSignal()) { + routePathList.add(tempPath); + return; + } } - tempPath.addSection(section); - if (section.isSwitchTrack()) { - Switch relSwitch = section.getRelSwitch(); - Switch linkedSwitch = relSwitch.queryLinkedSwitch(); + } + } + if (Objects.isNull(section)) { + // 找到尽头也没有构成进路,异常 + log.error(String.format("始端信号机[%s(%s)]:找到尽头也没有构成进路,所寻路径为[%s]", + startSignal.getName(), startSignal.getCode(), + tempPath.getSectionPathString())); + errorList.add(String.format("始端信号机[%s(%s)]:找到尽头也没有构成进路,所寻路径为[%s]", + startSignal.getName(), startSignal.getCode(), + tempPath.getSectionPathString())); + return; + } + tempPath.addSection(section); + if (section.isSwitchTrack()) { + Switch relSwitch = section.getRelSwitch(); + Switch linkedSwitch = relSwitch.queryLinkedSwitch(); // if (config.isCoupleSwitch()) { // linkedSwitch = relSwitch.queryLinkedSwitch(); // } - if (relSwitch.isA(section)) { - // 路径存在两种情况,道岔定位从A->B和道岔反位从A->C - // 产生分化递归 - SectionPath npPath = tempPath.cloneNew();// 定位路径 - npPath.addSection(relSwitch.getB()); - npPath.addSwitchElement(new SwitchElement(relSwitch, true)); - // 没有侧防,且联动道岔存在 - if (!config.isGenerateFls() && Objects.nonNull(linkedSwitch)) { - npPath.addSwitchElement(new SwitchElement(linkedSwitch, true)); - } - getRoutePathOf(startSignal, relSwitch.getB().getSectionOf(right), ground, npPath, routePathList, config, errorList); - SectionPath rpPath = tempPath.cloneNew();// 反位路径 - rpPath.addSection(relSwitch.getC()); - rpPath.addSwitchElement(new SwitchElement(relSwitch, false)); + if (relSwitch.isA(section)) { + // 路径存在两种情况,道岔定位从A->B和道岔反位从A->C + // 产生分化递归 + SectionPath npPath = tempPath.cloneNew();// 定位路径 + npPath.addSection(relSwitch.getB()); + npPath.addSwitchElement(new SwitchElement(relSwitch, true)); + // 没有侧防,且联动道岔存在 + if (!config.isGenerateFls() && Objects.nonNull(linkedSwitch)) { + npPath.addSwitchElement(new SwitchElement(linkedSwitch, true)); + } + getRoutePathOf(startSignal, relSwitch.getB().getSectionOf(right), ground, npPath, + routePathList, config, errorList); + SectionPath rpPath = tempPath.cloneNew();// 反位路径 + rpPath.addSection(relSwitch.getC()); + rpPath.addSwitchElement(new SwitchElement(relSwitch, false)); // if (Objects.nonNull(linkedSwitch)) { // rpPath.addSwitchElement(new SwitchElement(linkedSwitch, false)); // } - // 如果是同一道岔计轴,添加另一道岔定位 - Switch otherSwitch = relSwitch.queryAxleRelatedOtherSwitch(); - if (!config.isGenerateFls() && Objects.nonNull(otherSwitch) && relSwitch.isBConnectTo(otherSwitch)) { - rpPath.addSwitchElement(new SwitchElement(otherSwitch, true)); - // 另一道岔联动道岔也需要 - Switch otherLinkSwitch = otherSwitch.queryLinkedSwitch(); - if (otherLinkSwitch != null) { - rpPath.addSwitchElement(new SwitchElement(otherLinkSwitch, true)); - } - } - getRoutePathOf(startSignal, relSwitch.getC().getSectionOf(right), ground, rpPath, routePathList, config, errorList); - } else if (relSwitch.isB(section)) { - // 只有一条路径,从B->A,道岔定位 - tempPath.addSection(relSwitch.getA()); - tempPath.addSwitchElement(new SwitchElement(relSwitch, true)); - // 没有侧防,且联动道岔存在 - if (!config.isGenerateFls() && Objects.nonNull(linkedSwitch)) { - tempPath.addSwitchElement(new SwitchElement(linkedSwitch, true)); - } - getRoutePathOf(startSignal, relSwitch.getA().getSectionOf(right), ground, tempPath, routePathList, config, errorList); - } else if (relSwitch.isC(section)) { - // 只有一条路径,从C->A,道岔反位 - tempPath.addSection(relSwitch.getA()); - tempPath.addSwitchElement(new SwitchElement(relSwitch, false)); + // 如果是同一道岔计轴,添加另一道岔定位 + Switch otherSwitch = relSwitch.queryAxleRelatedOtherSwitch(); + if (!config.isGenerateFls() && Objects.nonNull(otherSwitch) && relSwitch.isBConnectTo( + otherSwitch)) { + rpPath.addSwitchElement(new SwitchElement(otherSwitch, true)); + // 另一道岔联动道岔也需要 + Switch otherLinkSwitch = otherSwitch.queryLinkedSwitch(); + if (otherLinkSwitch != null) { + rpPath.addSwitchElement(new SwitchElement(otherLinkSwitch, true)); + } + } + getRoutePathOf(startSignal, relSwitch.getC().getSectionOf(right), ground, rpPath, + routePathList, config, errorList); + } else if (relSwitch.isB(section)) { + // 只有一条路径,从B->A,道岔定位 + tempPath.addSection(relSwitch.getA()); + tempPath.addSwitchElement(new SwitchElement(relSwitch, true)); + // 没有侧防,且联动道岔存在 + if (!config.isGenerateFls() && Objects.nonNull(linkedSwitch)) { + tempPath.addSwitchElement(new SwitchElement(linkedSwitch, true)); + } + getRoutePathOf(startSignal, relSwitch.getA().getSectionOf(right), ground, tempPath, + routePathList, config, errorList); + } else if (relSwitch.isC(section)) { + // 只有一条路径,从C->A,道岔反位 + tempPath.addSection(relSwitch.getA()); + tempPath.addSwitchElement(new SwitchElement(relSwitch, false)); // if (Objects.nonNull(linkedSwitch)) { // tempPath.addSwitchElement(new SwitchElement(linkedSwitch, false)); // } - // 如果是同一道岔计轴,添加另一道岔定位 - Switch otherSwitch = relSwitch.queryAxleRelatedOtherSwitch(); - if (!config.isGenerateFls() && Objects.nonNull(otherSwitch)) { - tempPath.addSwitchElement(new SwitchElement(otherSwitch, true)); - // 另一道岔联动道岔也需要 - Switch otherLinkSwitch = otherSwitch.queryLinkedSwitch(); - if (otherLinkSwitch != null) { - tempPath.addSwitchElement(new SwitchElement(otherLinkSwitch, true)); - } - } - getRoutePathOf(startSignal, relSwitch.getA().getSectionOf(right), ground, tempPath, routePathList, config, errorList); - } else { - errorList.add(String.format("地图基础数据有错误:区段[%s(%s)]关联了道岔[%s(%s)],却不是此道岔的关联区段", - section.getName(), section.getCode(), - relSwitch.getName(), relSwitch.getCode())); - return; - } - } else { - // 非道岔区段 - Section next = section.getSectionOf(right); - getRoutePathOf(startSignal, next, ground, tempPath, routePathList, config, errorList); + // 如果是同一道岔计轴,添加另一道岔定位 + Switch otherSwitch = relSwitch.queryAxleRelatedOtherSwitch(); + if (!config.isGenerateFls() && Objects.nonNull(otherSwitch)) { + tempPath.addSwitchElement(new SwitchElement(otherSwitch, true)); + // 另一道岔联动道岔也需要 + Switch otherLinkSwitch = otherSwitch.queryLinkedSwitch(); + if (otherLinkSwitch != null) { + tempPath.addSwitchElement(new SwitchElement(otherLinkSwitch, true)); + } } + getRoutePathOf(startSignal, relSwitch.getA().getSectionOf(right), ground, tempPath, + routePathList, config, errorList); + } else { + errorList.add(String.format( + "地图基础数据有错误:区段[%s(%s)]关联了道岔[%s(%s)],却不是此道岔的关联区段", + section.getName(), section.getCode(), + relSwitch.getName(), relSwitch.getCode())); + return; + } + } else { + // 非道岔区段 + Section next = section.getSectionOf(right); + getRoutePathOf(startSignal, next, ground, tempPath, routePathList, config, errorList); } + } - private void getRoutePathOfDepot(Signal startSignal, Section section, - SectionPath tempPath, List routePathList, - MapCiGenerateConfig config, List errorList) { - boolean right = startSignal.isRight(); - if (!CollectionUtils.isEmpty(tempPath.getSectionList())) { - Signal signal = tempPath.getLastSection().getSignalOf(right); - if (startSignal.getType().equals(Signal.SignalType.INBOUND) - || startSignal.getType().equals(Signal.SignalType.SHUNTING2)) { - // 进段信号机 -> 列车兼调车信号机, 列车兼调车信号机 -> 列车兼调车信号机, 列车兼调车信号机 -> 出段信号机 - if (Objects.nonNull(signal) && (signal.getType().equals(Signal.SignalType.SHUNTING2) - || signal.getType().equals(Signal.SignalType.OUTBOUND))) { - routePathList.add(tempPath); - return; - } - if (Objects.isNull(section)) { - Signal lastSignal = tempPath.getLastSection().getSignalOf(!right); - if (Objects.nonNull(lastSignal) && lastSignal.getType().equals(Signal.SignalType.SHUNTING2)) { - routePathList.add(tempPath); - } - return; - } - } else { - // 同向类型相同信号机 - if (Objects.nonNull(signal)) { - // 调车信号机 -> 调车信号机/列车兼调车信号机/ 阻挡信号机/出段信号机 - if (Signal.SignalType.SHUNTING.equals(signal.getType()) - || Signal.SignalType.SHUNTING2.equals(signal.getType()) - || Signal.SignalType.BLOCKING.equals(signal.getType()) - || Signal.SignalType.OUTBOUND.equals(signal.getType())) { - routePathList.add(tempPath); - return; - } - } - if (Objects.isNull(section)) { - // 尽头有反向信号机 - if (Objects.nonNull(tempPath.getLastSection().getSignalOf(!right))) { - routePathList.add(tempPath); - } - return; - } - } + private void getRoutePathOfDepot(Signal startSignal, Section section, + SectionPath tempPath, List routePathList, + MapCiGenerateConfig config, List errorList) { + boolean right = startSignal.isRight(); + if (!CollectionUtils.isEmpty(tempPath.getSectionList())) { + Signal signal = tempPath.getLastSection().getSignalOf(right); + if (startSignal.getType().equals(Signal.SignalType.INBOUND) + || startSignal.getType().equals(Signal.SignalType.SHUNTING2)) { + // 进段信号机 -> 列车兼调车信号机, 列车兼调车信号机 -> 列车兼调车信号机, 列车兼调车信号机 -> 出段信号机 + if (Objects.nonNull(signal) && (signal.getType().equals(Signal.SignalType.SHUNTING2) + || signal.getType().equals(Signal.SignalType.OUTBOUND))) { + routePathList.add(tempPath); + return; } - tempPath.addSection(section); - if (section.isSwitchTrack()) { - Switch relSwitch = section.getRelSwitch(); - Switch linkedSwitch = relSwitch.queryLinkedSwitch(); - if (relSwitch.isA(section)) { - // 路径存在两种情况,道岔定位从A->B和道岔反位从A->C - // 产生分化递归 - SectionPath npPath = tempPath.cloneNew();// 定位路径 - npPath.addSection(relSwitch.getB()); - npPath.addSwitchElement(new SwitchElement(relSwitch, true)); - // 联动道岔存在 - if (Objects.nonNull(linkedSwitch)) { - npPath.addSwitchElement(new SwitchElement(linkedSwitch, true)); - } - getRoutePathOfDepot(startSignal, relSwitch.getB().getSectionOf(right), npPath, routePathList, config, errorList); - SectionPath rpPath = tempPath.cloneNew();// 反位路径 - rpPath.addSection(relSwitch.getC()); - rpPath.addSwitchElement(new SwitchElement(relSwitch, false)); - // 如果是同一道岔计轴,添加另一道岔定位 - Switch otherSwitch = relSwitch.queryAxleRelatedOtherSwitch(); - if (Objects.nonNull(otherSwitch) && relSwitch.isBConnectTo(otherSwitch)) { - rpPath.addSwitchElement(new SwitchElement(otherSwitch, true)); - // 另一道岔联动道岔也需要 - Switch otherLinkSwitch = otherSwitch.queryLinkedSwitch(); - if (otherLinkSwitch != null) { - rpPath.addSwitchElement(new SwitchElement(otherLinkSwitch, true)); - } - } - getRoutePathOfDepot(startSignal, relSwitch.getC().getSectionOf(right), rpPath, routePathList, config, errorList); - } else if (relSwitch.isB(section)) { - // 只有一条路径,从B->A,道岔定位 - tempPath.addSection(relSwitch.getA()); - tempPath.addSwitchElement(new SwitchElement(relSwitch, true)); - // 没有侧防,且联动道岔存在 - if (Objects.nonNull(linkedSwitch)) { - tempPath.addSwitchElement(new SwitchElement(linkedSwitch, true)); - } - getRoutePathOfDepot(startSignal, relSwitch.getA().getSectionOf(right), tempPath, routePathList, config, errorList); - } else if (relSwitch.isC(section)) { - // 只有一条路径,从C->A,道岔反位 - tempPath.addSection(relSwitch.getA()); - tempPath.addSwitchElement(new SwitchElement(relSwitch, false)); - // 如果是同一道岔计轴,添加另一道岔定位 - Switch otherSwitch = relSwitch.queryAxleRelatedOtherSwitch(); - if (Objects.nonNull(otherSwitch)) { - tempPath.addSwitchElement(new SwitchElement(otherSwitch, true)); - // 另一道岔联动道岔也需要 - Switch otherLinkSwitch = otherSwitch.queryLinkedSwitch(); - if (otherLinkSwitch != null) { - tempPath.addSwitchElement(new SwitchElement(otherLinkSwitch, true)); - } - } - getRoutePathOfDepot(startSignal, relSwitch.getA().getSectionOf(right), tempPath, routePathList, config, errorList); - } else { - errorList.add(String.format("地图基础数据有错误:区段[%s(%s)]关联了道岔[%s(%s)],却不是此道岔的关联区段", - section.getName(), section.getCode(), - relSwitch.getName(), relSwitch.getCode())); - return; - } - } else { - // 非道岔区段 - Section next = section.getSectionOf(right); - getRoutePathOfDepot(startSignal, next, tempPath, routePathList, config, errorList); + if (Objects.isNull(section)) { + Signal lastSignal = tempPath.getLastSection().getSignalOf(!right); + if (Objects.nonNull(lastSignal) && lastSignal.getType() + .equals(Signal.SignalType.SHUNTING2)) { + routePathList.add(tempPath); + } + return; } - } - - /** - * 生成接近区段 - * - * @param signal - * @param config - */ - private void generateApproachSection(Signal signal, MapCiGenerateConfig config) { - List approachPathList = new ArrayList<>(); - boolean right = !signal.isRight(); // 信号机反方向 - Section section = signal.getSection(); - if (config.isSignalApproachOnlyOne()) { - approachPathList.add(new SectionPath(right, null, Arrays.asList(section), new ArrayList<>())); - } else { - float l = 600; // 接近距离默认600m - getApproachPathOf(section, right, l, new SectionPath(right), config, approachPathList); - } - for (SectionPath sectionPath : approachPathList) { - float len = 0; - List
logicApproachList = new ArrayList<>(); - List
sectionList = sectionPath.getSectionList(); - for (Section phySection : sectionList) { - if (len >= 600) break; - if (phySection.isSwitchTrack()) { - len += phySection.getLen(); - logicApproachList.add(phySection); - continue; - } - List
logicList = phySection.getLogicList(); - if (CollectionUtils.isEmpty(logicList)) { - len += phySection.getLen(); - logicApproachList.add(phySection); - continue; - } - List
sortedList = new ArrayList<>(logicList); - if (signal.isRight()) { - Collections.reverse(sortedList); - } - for (Section logic : sortedList) { - logicApproachList.add(logic); - len += logic.getLen(); - if (len >= 600) break; - } - } - sectionPath.setLogicList(logicApproachList); - } - signal.setApproachPathList(approachPathList); - signal.setRouteReleaseTime(config.getRouteReleaseTime()); - } - - public void getApproachPathOf(Section section, boolean right, Float distance, SectionPath tempPath, MapCiGenerateConfig config, List results) { - if (!CollectionUtils.isEmpty(tempPath.getSectionList())) { - // 已经有区段了 - if (Objects.isNull(section)) { - results.add(tempPath); - return; - } else if (config.isSignalApproachOnlyNpSwitch()) { - if (section.isSwitchTrack() && section.getRelSwitch().isC(section)) { - results.add(tempPath); - return; - } - } - if (config.isSignalApproachNotPassPreSignal() && Objects.nonNull(section.getSignalOf(!right))) { - results.add(tempPath); - return; - } - if (tempPath.getTotalLen() > distance) { - results.add(tempPath); - return; - } - } else if (Objects.isNull(section)) { - // 直接空区段,数据有问题 + } else { + // 同向类型相同信号机 + if (Objects.nonNull(signal)) { + // 调车信号机 -> 调车信号机/列车兼调车信号机/ 阻挡信号机/出段信号机 + if (Signal.SignalType.SHUNTING.equals(signal.getType()) + || Signal.SignalType.SHUNTING2.equals(signal.getType()) + || Signal.SignalType.BLOCKING.equals(signal.getType()) + || Signal.SignalType.OUTBOUND.equals(signal.getType())) { + routePathList.add(tempPath); return; + } } - if (section.isSwitchTrack()) { - Switch relSwitch = section.getRelSwitch(); - if (relSwitch.isA(section)) { - // 路径存在两种情况,道岔定位从A->C和道岔反位从A->B - // 产生分化递归 - tempPath.addSection(section); - SectionPath npPath = tempPath.cloneNew();// 定位路径 - npPath.addSection(relSwitch.getB()); - npPath.addSwitchElement(new SwitchElement(relSwitch, true)); - getApproachPathOf(relSwitch.getB().getSectionOf(right), right, distance, npPath, config, results); - if (!config.isSignalApproachOnlyNpSwitch()) { - SectionPath rpPath = tempPath.cloneNew();// 反位路径 - rpPath.addSection(relSwitch.getC()); - rpPath.addSwitchElement(new SwitchElement(relSwitch, false)); - getApproachPathOf(relSwitch.getC().getSectionOf(right), right, distance, rpPath, config, results); - } - } else if (relSwitch.isB(section)) { - // 只有一条路径,从B->A,道岔定位 - tempPath.addSection(section); - tempPath.addSection(relSwitch.getA()); - tempPath.addSwitchElement(new SwitchElement(relSwitch, true)); - getApproachPathOf(relSwitch.getA().getSectionOf(right), right, distance, tempPath, config, results); - } else if (relSwitch.isC(section)) { - if (!config.isSignalApproachOnlyNpSwitch() || CollectionUtils.isEmpty(tempPath.getSectionList())) { - // 只有一条路径,从C->A,道岔反位 - tempPath.addSection(section); - tempPath.addSection(relSwitch.getA()); - tempPath.addSwitchElement(new SwitchElement(relSwitch, false)); - getApproachPathOf(relSwitch.getA().getSectionOf(right), right, distance, tempPath, config, results); - } else { - results.add(tempPath); - return; - } - } else { - throw BusinessExceptionAssertEnum.DATA_ERROR.exception( - String.format("地图基础数据有错误:区段[%s(%s)]关联了道岔[%s(%s)],却不是此道岔的关联区段", - section.getName(), section.getCode(), - relSwitch.getName(), relSwitch.getCode())); - } - } else { - tempPath.addSection(section); - getApproachPathOf(section.getSectionOf(right), right, distance, tempPath, config, results); + if (Objects.isNull(section)) { + // 尽头有反向信号机 + if (Objects.nonNull(tempPath.getLastSection().getSignalOf(!right))) { + routePathList.add(tempPath); + } + return; } - + } } - - /** - * 生成自动信号 - * - * @param signal - * @param autoSignalGenerator - * @param errorList - */ - private AutoSignal generateAutoSignal(Signal signal, CodeGenerator autoSignalGenerator, List errorList) { - AutoSignal autoSignal = new AutoSignal(autoSignalGenerator.next()); - autoSignal.setSignal(signal); - List
sectionList = new ArrayList<>(); - autoSignal.setSectionList(sectionList); - Section section = signal.getSection(); - if (section.isStandTrack()) { - autoSignal.setStandHoldList(section.getStandList()); + tempPath.addSection(section); + if (section.isSwitchTrack()) { + Switch relSwitch = section.getRelSwitch(); + Switch linkedSwitch = relSwitch.queryLinkedSwitch(); + if (relSwitch.isA(section)) { + // 路径存在两种情况,道岔定位从A->B和道岔反位从A->C + // 产生分化递归 + SectionPath npPath = tempPath.cloneNew();// 定位路径 + npPath.addSection(relSwitch.getB()); + npPath.addSwitchElement(new SwitchElement(relSwitch, true)); + // 联动道岔存在 + if (Objects.nonNull(linkedSwitch)) { + npPath.addSwitchElement(new SwitchElement(linkedSwitch, true)); } - boolean right = signal.isRight(); - Section start = section.getSectionOf(right); - Section temp = start; - while (Objects.nonNull(temp)) { - sectionList.add(temp); - if (Objects.nonNull(temp.getSignalOf(right))) { - Section next = temp.getSectionOf(right); - sectionList.add(next); - if (next.isSwitchTrack()) { - Switch relSwitch = next.getRelSwitch(); - Section nextSwitchSection = relSwitch.getNextSectionOnBaseSectionAndPosition(next, true); - if (relSwitch.isC(next)) { - nextSwitchSection = relSwitch.getNextSectionOnBaseSectionAndPosition(next, false); - } - if (Objects.isNull(nextSwitchSection)) { - throw new SimulationException(SimulationExceptionType.Simulation_Map_Data_Error); - } - sectionList.add(nextSwitchSection); - Section next2 = nextSwitchSection.getSectionOf(right); - if (Objects.nonNull(next2) && Objects.equals(next2.getParent(), nextSwitchSection.getParent())) { - // 是同一计轴区段,添加下一个道岔区段 - sectionList.add(next2); - sectionList.add(next2.getRelSwitch().getNextSectionOnBaseSectionAndPosition(next2, true)); - } - } + getRoutePathOfDepot(startSignal, relSwitch.getB().getSectionOf(right), npPath, + routePathList, config, errorList); + SectionPath rpPath = tempPath.cloneNew();// 反位路径 + rpPath.addSection(relSwitch.getC()); + rpPath.addSwitchElement(new SwitchElement(relSwitch, false)); + // 如果是同一道岔计轴,添加另一道岔定位 + Switch otherSwitch = relSwitch.queryAxleRelatedOtherSwitch(); + if (Objects.nonNull(otherSwitch) && relSwitch.isBConnectTo(otherSwitch)) { + rpPath.addSwitchElement(new SwitchElement(otherSwitch, true)); + // 另一道岔联动道岔也需要 + Switch otherLinkSwitch = otherSwitch.queryLinkedSwitch(); + if (otherLinkSwitch != null) { + rpPath.addSwitchElement(new SwitchElement(otherLinkSwitch, true)); + } + } + getRoutePathOfDepot(startSignal, relSwitch.getC().getSectionOf(right), rpPath, + routePathList, config, errorList); + } else if (relSwitch.isB(section)) { + // 只有一条路径,从B->A,道岔定位 + tempPath.addSection(relSwitch.getA()); + tempPath.addSwitchElement(new SwitchElement(relSwitch, true)); + // 没有侧防,且联动道岔存在 + if (Objects.nonNull(linkedSwitch)) { + tempPath.addSwitchElement(new SwitchElement(linkedSwitch, true)); + } + getRoutePathOfDepot(startSignal, relSwitch.getA().getSectionOf(right), tempPath, + routePathList, config, errorList); + } else if (relSwitch.isC(section)) { + // 只有一条路径,从C->A,道岔反位 + tempPath.addSection(relSwitch.getA()); + tempPath.addSwitchElement(new SwitchElement(relSwitch, false)); + // 如果是同一道岔计轴,添加另一道岔定位 + Switch otherSwitch = relSwitch.queryAxleRelatedOtherSwitch(); + if (Objects.nonNull(otherSwitch)) { + tempPath.addSwitchElement(new SwitchElement(otherSwitch, true)); + // 另一道岔联动道岔也需要 + Switch otherLinkSwitch = otherSwitch.queryLinkedSwitch(); + if (otherLinkSwitch != null) { + tempPath.addSwitchElement(new SwitchElement(otherLinkSwitch, true)); + } + } + getRoutePathOfDepot(startSignal, relSwitch.getA().getSectionOf(right), tempPath, + routePathList, config, errorList); + } else { + errorList.add(String.format( + "地图基础数据有错误:区段[%s(%s)]关联了道岔[%s(%s)],却不是此道岔的关联区段", + section.getName(), section.getCode(), + relSwitch.getName(), relSwitch.getCode())); + return; + } + } else { + // 非道岔区段 + Section next = section.getSectionOf(right); + getRoutePathOfDepot(startSignal, next, tempPath, routePathList, config, errorList); + } + } + + /** + * 生成接近区段 + * + * @param signal + * @param config + */ + private void generateApproachSection(Signal signal, MapCiGenerateConfig config) { + List approachPathList = new ArrayList<>(); + boolean right = !signal.isRight(); // 信号机反方向 + Section section = signal.getSection(); + if (config.isSignalApproachOnlyOne()) { + approachPathList.add(new SectionPath(right, null, Arrays.asList(section), new ArrayList<>())); + } else { + float l = 600; // 接近距离默认600m + getApproachPathOf(section, right, l, new SectionPath(right), config, approachPathList); + } + for (SectionPath sectionPath : approachPathList) { + float len = 0; + List
logicApproachList = new ArrayList<>(); + List
sectionList = sectionPath.getSectionList(); + for (Section phySection : sectionList) { + if (len >= 600) { + break; + } + if (phySection.isSwitchTrack()) { + len += phySection.getLen(); + logicApproachList.add(phySection); + continue; + } + List
logicList = phySection.getLogicList(); + if (CollectionUtils.isEmpty(logicList)) { + len += phySection.getLen(); + logicApproachList.add(phySection); + continue; + } + List
sortedList = new ArrayList<>(logicList); + if (signal.isRight()) { + Collections.reverse(sortedList); + } + for (Section logic : sortedList) { + logicApproachList.add(logic); + len += logic.getLen(); + if (len >= 600) { break; - } else { - temp = temp.getSectionOf(right); } } - if (sectionList.size() > 3) { - log.debug(String.format("自动信号[%s(%s)]区段数量[%s]大于3", - signal.getName(), signal.getCode(), sectionList.size())); - } - List psdList = new ArrayList<>(); - List espList = new ArrayList<>(); - for (Section track : sectionList) { - if (track.isStandTrack()) { - for (Stand stand : track.getStandList()) { - if (stand.hasDoor()) { - psdList.add(stand.getPsd()); - } - if (!stand.isSmall()) { - espList.add(stand.getEsp()); - } - } - } - } - autoSignal.setPsdList(psdList); - autoSignal.setEspList(espList); - return autoSignal; + } + sectionPath.setLogicList(logicApproachList); } + signal.setApproachPathList(approachPathList); + signal.setRouteReleaseTime(config.getRouteReleaseTime()); + } + + public void getApproachPathOf(Section section, boolean right, Float distance, + SectionPath tempPath, MapCiGenerateConfig config, List results) { + if (!CollectionUtils.isEmpty(tempPath.getSectionList())) { + // 已经有区段了 + if (Objects.isNull(section)) { + results.add(tempPath); + return; + } else if (config.isSignalApproachOnlyNpSwitch()) { + if (section.isSwitchTrack() && section.getRelSwitch().isC(section)) { + results.add(tempPath); + return; + } + } + if (config.isSignalApproachNotPassPreSignal() && Objects.nonNull( + section.getSignalOf(!right))) { + results.add(tempPath); + return; + } + if (tempPath.getTotalLen() > distance) { + results.add(tempPath); + return; + } + } else if (Objects.isNull(section)) { + // 直接空区段,数据有问题 + return; + } + if (section.isSwitchTrack()) { + Switch relSwitch = section.getRelSwitch(); + if (relSwitch.isA(section)) { + // 路径存在两种情况,道岔定位从A->C和道岔反位从A->B + // 产生分化递归 + tempPath.addSection(section); + SectionPath npPath = tempPath.cloneNew();// 定位路径 + npPath.addSection(relSwitch.getB()); + npPath.addSwitchElement(new SwitchElement(relSwitch, true)); + getApproachPathOf(relSwitch.getB().getSectionOf(right), right, distance, npPath, config, + results); + if (!config.isSignalApproachOnlyNpSwitch()) { + SectionPath rpPath = tempPath.cloneNew();// 反位路径 + rpPath.addSection(relSwitch.getC()); + rpPath.addSwitchElement(new SwitchElement(relSwitch, false)); + getApproachPathOf(relSwitch.getC().getSectionOf(right), right, distance, rpPath, config, + results); + } + } else if (relSwitch.isB(section)) { + // 只有一条路径,从B->A,道岔定位 + tempPath.addSection(section); + tempPath.addSection(relSwitch.getA()); + tempPath.addSwitchElement(new SwitchElement(relSwitch, true)); + getApproachPathOf(relSwitch.getA().getSectionOf(right), right, distance, tempPath, config, + results); + } else if (relSwitch.isC(section)) { + if (!config.isSignalApproachOnlyNpSwitch() || CollectionUtils.isEmpty( + tempPath.getSectionList())) { + // 只有一条路径,从C->A,道岔反位 + tempPath.addSection(section); + tempPath.addSection(relSwitch.getA()); + tempPath.addSwitchElement(new SwitchElement(relSwitch, false)); + getApproachPathOf(relSwitch.getA().getSectionOf(right), right, distance, tempPath, config, + results); + } else { + results.add(tempPath); + return; + } + } else { + throw BusinessExceptionAssertEnum.DATA_ERROR.exception( + String.format( + "地图基础数据有错误:区段[%s(%s)]关联了道岔[%s(%s)],却不是此道岔的关联区段", + section.getName(), section.getCode(), + relSwitch.getName(), relSwitch.getCode())); + } + } else { + tempPath.addSection(section); + getApproachPathOf(section.getSectionOf(right), right, distance, tempPath, config, results); + } + + } + + /** + * 生成自动信号 + * + * @param signal + * @param autoSignalGenerator + * @param errorList + */ + private AutoSignal generateAutoSignal(Signal signal, CodeGenerator autoSignalGenerator, + List errorList) { + AutoSignal autoSignal = new AutoSignal(autoSignalGenerator.next()); + autoSignal.setSignal(signal); + List
sectionList = new ArrayList<>(); + autoSignal.setSectionList(sectionList); + Section section = signal.getSection(); + if (section.isStandTrack()) { + autoSignal.setStandHoldList(section.getStandList()); + } + boolean right = signal.isRight(); + Section start = section.getSectionOf(right); + Section temp = start; + while (Objects.nonNull(temp)) { + sectionList.add(temp); + if (Objects.nonNull(temp.getSignalOf(right))) { + Section next = temp.getSectionOf(right); + sectionList.add(next); + if (next.isSwitchTrack()) { + Switch relSwitch = next.getRelSwitch(); + Section nextSwitchSection = relSwitch.getNextSectionOnBaseSectionAndPosition(next, true); + if (relSwitch.isC(next)) { + nextSwitchSection = relSwitch.getNextSectionOnBaseSectionAndPosition(next, false); + } + if (Objects.isNull(nextSwitchSection)) { + throw new SimulationException(SimulationExceptionType.Simulation_Map_Data_Error); + } + sectionList.add(nextSwitchSection); + Section next2 = nextSwitchSection.getSectionOf(right); + if (Objects.nonNull(next2) && Objects.equals(next2.getParent(), + nextSwitchSection.getParent())) { + // 是同一计轴区段,添加下一个道岔区段 + sectionList.add(next2); + sectionList.add( + next2.getRelSwitch().getNextSectionOnBaseSectionAndPosition(next2, true)); + } + } + break; + } else { + temp = temp.getSectionOf(right); + } + } + if (sectionList.size() > 3) { + log.debug(String.format("自动信号[%s(%s)]区段数量[%s]大于3", + signal.getName(), signal.getCode(), sectionList.size())); + } + List psdList = new ArrayList<>(); + List espList = new ArrayList<>(); + for (Section track : sectionList) { + if (track.isStandTrack()) { + for (Stand stand : track.getStandList()) { + if (stand.hasDoor()) { + psdList.add(stand.getPsd()); + } + if (!stand.isSmall()) { + espList.add(stand.getEsp()); + } + } + } + } + autoSignal.setPsdList(psdList); + autoSignal.setEspList(espList); + return autoSignal; + } } diff --git a/src/main/java/club/joylink/rtss/vo/map/MapCiGenerateConfig.java b/src/main/java/club/joylink/rtss/vo/map/MapCiGenerateConfig.java index 468597bbe..ccaf4303f 100644 --- a/src/main/java/club/joylink/rtss/vo/map/MapCiGenerateConfig.java +++ b/src/main/java/club/joylink/rtss/vo/map/MapCiGenerateConfig.java @@ -1,140 +1,145 @@ package club.joylink.rtss.vo.map; -import lombok.Getter; -import lombok.Setter; - import java.util.HashSet; import java.util.Set; +import lombok.Getter; +import lombok.Setter; @Getter @Setter public class MapCiGenerateConfig { - //--------------------联锁数据生成配置start------------------- - /** - *是否类似哈尔滨一号线,联锁分为ATP信号、地面信号、引导信号 - */ - private boolean likeHa1; + //--------------------联锁数据生成配置start------------------- + /** + * 是否类似哈尔滨一号线,联锁分为ATP信号、地面信号、引导信号 + */ + private boolean likeHa1; - /** - *是否生成侧防:true-生成侧防,不要联动道岔,false-不生成侧防,用联动道岔 - */ - private boolean generateFls; + /** + * 是否生成侧防:true-生成侧防,不要联动道岔,false-不生成侧防,用联动道岔 + */ + private boolean generateFls; - /** - *信号机接近区段只取最近的一个 - */ - private boolean signalApproachOnlyOne; + /** + * 信号机接近区段只取最近的一个 + */ + private boolean signalApproachOnlyOne; - /** - *信号机接近区段仅考虑定位道岔 - */ - private boolean signalApproachOnlyNpSwitch; + /** + * 信号机接近区段仅考虑定位道岔 + */ + private boolean signalApproachOnlyNpSwitch; - /** - *信号机接近区段不跨过前方同向信号机 - */ - private boolean signalApproachNotPassPreSignal = true; + /** + * 信号机接近区段不跨过前方同向信号机 + */ + private boolean signalApproachNotPassPreSignal = true; - /** - *进路名称使用终端信号机同区段反向信号机名称命名:true-使用反向(如果存在的话),false-使用终端信号机命名 - */ - private boolean routeNameUseEndOppositeSignalName; + /** + * 进路名称使用终端信号机同区段反向信号机名称命名:true-使用反向(如果存在的话),false-使用终端信号机命名 + */ + private boolean routeNameUseEndOppositeSignalName; - /** - *是否生成折返进路 - */ - private boolean generateTbRoute; + /** + * 是否生成折返进路 + */ + private boolean generateTbRoute; - /** - *折返进路名称使用终端信号机反向信号机名称 - */ - private boolean tbRouteNameUseEndOppositeSignalName; + /** + * 折返进路名称使用终端信号机反向信号机名称(并且终端按钮亦使用反向信号机-成都三联锁) + */ + private boolean tbRouteNameUseEndOppositeSignalName; - /** - *进路始端防护信号机是否总是绿灯:true-总是开绿灯,false-根据进路中有无反位道岔生成绿灯或黄灯 - */ - private boolean routeSignalAlwaysGreen; + /** + * 进路始端防护信号机是否总是绿灯:true-总是开绿灯,false-根据进路中有无反位道岔生成绿灯或黄灯 + */ + private boolean routeSignalAlwaysGreen; - /** - *多个延续保护路径生成多条进路:true-生成多条进路,false-生成一条进路 - */ - private boolean routeApartByOverlap; + /** + * 多个延续保护路径生成多条进路:true-生成多条进路,false-生成一条进路 + */ + private boolean routeApartByOverlap; - /** - *延续保护是否只构建道岔 - */ - private boolean overlapOnlySwitch; + /** + * 延续保护是否只构建道岔 + */ + private boolean overlapOnlySwitch; // // @ApiModelProperty(value = "延续保护构建是否只考虑一个道岔计轴") // private boolean overlapOnlyOneSwitch; - /** - * 延续保护最小长度 - */ - private float overlapMinLen = 55; + /** + * 延续保护最小长度 + */ + private float overlapMinLen = 55; - /** - *延续保护道岔是否只构建定位道岔 - */ - private boolean overlapSwitchNpOnly; + /** + * 延续保护道岔是否只构建定位道岔 + */ + private boolean overlapSwitchNpOnly; - /** - *延续保护道岔在防护信号机与所属区段方向相反时,只构建定位道岔 - */ - private boolean overlapSignalOppositeSwitchNpOnly; + /** + * 延续保护道岔在防护信号机与所属区段方向相反时,只构建定位道岔 + */ + private boolean overlapSignalOppositeSwitchNpOnly; - /** - *延续保护的建立方式:true-通过触发建立,false-随进路建立 - */ - private boolean overlapSettingByTrigger; + /** + * 延续保护的建立方式:true-通过触发建立,false-随进路建立 + */ + private boolean overlapSettingByTrigger; - /** - *默认延续保护解锁时间 - */ - private int overlapReleaseTime = 60; + /** + * 默认延续保护解锁时间 + */ + private int overlapReleaseTime = 60; - /** - *默认进路解锁时间 - */ - private int routeReleaseTime = 45; + /** + * 默认进路解锁时间 + */ + private int routeReleaseTime = 45; - /** - *是否生成自动折返 - */ - private boolean generateCycle; + /** + * 是否生成自动折返 + */ + private boolean generateCycle; - /** - *是否生成进路信号按钮 - */ - private boolean routeButton; + /** + * 是否生成进路信号按钮 + */ + private boolean routeButton; - /** - *若生成进路信号按钮,进路信号按钮是否取最近的一个信号机 - */ - private boolean getNearlySignal; + /** + * 若生成进路信号按钮,进路信号按钮是否取最近的一个信号机 + */ + private boolean getNearlySignal; - /** - *是否生成目的地码定义(泰雷兹式) - */ - private boolean generateDestination; + /** + * 是否生成目的地码定义(泰雷兹式) + */ + private boolean generateDestination; - /** 上下行站台共享紧急关闭效果的车站 */ - private Set sharingECStations = new HashSet<>(); + /** + * 上下行站台共享紧急关闭效果的车站 + */ + private Set sharingECStations = new HashSet<>(); - /** 进路联锁不包含站台扣车 */ - private boolean routeInterlockDoNotIncludeStandHoldTrain; + /** + * 进路联锁不包含站台扣车 + */ + private boolean routeInterlockDoNotIncludeStandHoldTrain; // @ApiModelProperty(value = "是否分开生成ATP联锁和地面信号联锁") // private boolean apartGroundAndAtp; - /** 是否处理停车场/车辆段逻辑 */ - private boolean handleDepot; + /** + * 是否处理停车场/车辆段逻辑 + */ + private boolean handleDepot; - /** - * 是大铁线路? - */ - private boolean railway; + /** + * 是大铁线路? + */ + private boolean railway; - //--------------------联锁数据生成配置end------------------- + //--------------------联锁数据生成配置end------------------- }