Version bump, and fixed some small issues with rendering and creating switches.
This commit is contained in:
parent
cb8eed835a
commit
99f438161f
2
pom.xml
2
pom.xml
|
@ -10,7 +10,7 @@
|
|||
</parent>
|
||||
<groupId>nl.andrewl</groupId>
|
||||
<artifactId>rail-signal-api</artifactId>
|
||||
<version>2.1.0</version>
|
||||
<version>2.2.0</version>
|
||||
<name>rail-signal-api</name>
|
||||
<description>A simple API for tracking rail traffic in signalled blocks.</description>
|
||||
<properties>
|
||||
|
|
|
@ -70,7 +70,7 @@ export default {
|
|||
message: "Are you sure you want to remove this component? This cannot be undone.",
|
||||
cancel: true
|
||||
}).onOk(() => {
|
||||
removeComponent(this.railSystem, component.id)
|
||||
removeComponent(this.rsStore.selectedRailSystem, component.id)
|
||||
.then(() => {
|
||||
this.quasar.notify({
|
||||
color: "positive",
|
||||
|
|
|
@ -127,7 +127,19 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
setActiveSwitchConfig(configId) {
|
||||
updateSwitchConfiguration(this.railSystem, this.sw, configId);
|
||||
updateSwitchConfiguration(this.rsStore.selectedRailSystem, this.sw, configId)
|
||||
.then(() => {
|
||||
this.quasar.notify({
|
||||
color: "positive",
|
||||
message: "Sent switch configuration update request."
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
this.quasar.notify({
|
||||
color: "negative",
|
||||
message: "An error occurred: " + error.response.data.message
|
||||
});
|
||||
});
|
||||
},
|
||||
isConfigActive(config) {
|
||||
return this.sw.activeConfiguration !== null && this.sw.activeConfiguration.id === config.id;
|
||||
|
|
|
@ -23,3 +23,28 @@ export function mulberry32(a) {
|
|||
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
||||
}
|
||||
}
|
||||
|
||||
export function sortPoints(points) {
|
||||
points = points.splice(0);
|
||||
const p0 = {};
|
||||
p0.y = Math.min.apply(null, points.map(p=>p.y));
|
||||
p0.x = Math.max.apply(null, points.filter(p=>p.y === p0.y).map(p=>p.x));
|
||||
points.sort((a,b)=>angleCompare(p0, a, b));
|
||||
return points;
|
||||
}
|
||||
|
||||
function angleCompare(p0, a, b) {
|
||||
const left = isLeft(p0, a, b);
|
||||
if (left === 0) return distCompare(p0, a, b);
|
||||
return left;
|
||||
}
|
||||
|
||||
function isLeft(p0, a, b) {
|
||||
return (a.x-p0.x)*(b.y-p0.y) - (b.x-p0.x)*(a.y-p0.y);
|
||||
}
|
||||
|
||||
function distCompare(p0, a, b) {
|
||||
const distA = (p0.x-a.x)*(p0.x-a.x) + (p0.y-a.y)*(p0.y-a.y);
|
||||
const distB = (p0.x-b.x)*(p0.x-b.x) + (p0.y-b.y)*(p0.y-b.y);
|
||||
return distA - distB;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ Helper functions to actually perform rendering of different components.
|
|||
*/
|
||||
|
||||
import { getScaleFactor, getWorldTransform, isComponentHovered, isComponentSelected } from "./mapRenderer";
|
||||
import { circle, roundedRect } from "./canvasUtils";
|
||||
import { circle, roundedRect, sortPoints } from "./canvasUtils";
|
||||
import randomColor from "randomcolor";
|
||||
|
||||
export function drawMap(ctx, rs) {
|
||||
|
@ -16,6 +16,7 @@ export function drawMap(ctx, rs) {
|
|||
|
||||
function drawSegments(ctx, rs) {
|
||||
const segmentPoints = new Map();
|
||||
// Gather for each segment a set of points representing its bounds.
|
||||
rs.segments.forEach(segment => segmentPoints.set(segment.id, []));
|
||||
for (let i = 0; i < rs.components.length; i++) {
|
||||
const c = rs.components[i];
|
||||
|
@ -25,6 +26,11 @@ function drawSegments(ctx, rs) {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Sort the points to make regular convex polygons.
|
||||
for (let i = 0; i < rs.segments.length; i++) {
|
||||
const unsortedPoints = segmentPoints.get(rs.segments[i].id);
|
||||
segmentPoints.set(rs.segments[i].id, sortPoints(unsortedPoints));
|
||||
}
|
||||
|
||||
for (let i = 0; i < rs.segments.length; i++) {
|
||||
const color = randomColor({ luminosity: 'light', format: 'rgb', seed: rs.segments[i].id });
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
package nl.andrewl.railsignalapi.rest.dto.component.in;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
public class SwitchPayload extends ComponentPayload {
|
||||
@NotEmpty @Size(min = 2, max = 10)
|
||||
@NotNull @Size(max = 10)
|
||||
public SwitchConfigurationPayload[] possibleConfigurations;
|
||||
|
||||
public static class SwitchConfigurationPayload {
|
||||
@NotEmpty @Size(min = 2, max = 10)
|
||||
@NotEmpty @Size(min = 2, max = 2)
|
||||
public NodePayload[] nodes;
|
||||
|
||||
public static class NodePayload {
|
||||
|
|
|
@ -87,9 +87,6 @@ public class ComponentCreationService {
|
|||
}
|
||||
s.getPossibleConfigurations().add(new SwitchConfiguration(s, pathNodes));
|
||||
}
|
||||
if (s.getPossibleConfigurations().size() < 2) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "At least two switch configurations are needed.");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import nl.andrewl.railsignalapi.dao.ComponentRepository;
|
|||
import nl.andrewl.railsignalapi.dao.RailSystemRepository;
|
||||
import nl.andrewl.railsignalapi.dao.SegmentRepository;
|
||||
import nl.andrewl.railsignalapi.live.ComponentDownlinkService;
|
||||
import nl.andrewl.railsignalapi.live.dto.ErrorMessage;
|
||||
import nl.andrewl.railsignalapi.live.dto.SegmentBoundaryUpdateMessage;
|
||||
import nl.andrewl.railsignalapi.live.dto.SegmentStatusMessage;
|
||||
import nl.andrewl.railsignalapi.live.websocket.AppUpdateService;
|
||||
|
@ -83,8 +84,21 @@ public class SegmentService {
|
|||
public void onBoundaryUpdate(SegmentBoundaryUpdateMessage msg) {
|
||||
var segmentBoundary = segmentBoundaryRepository.findById(msg.cId)
|
||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
||||
switch (msg.eventType) {
|
||||
segmentRepository.findByIdAndRailSystemId(msg.toSegmentId, segmentBoundary.getRailSystem().getId())
|
||||
.ifPresentOrElse(
|
||||
segment -> handleSegmentBoundaryMessage(msg.eventType, segmentBoundary, segment),
|
||||
() -> downlinkService.sendMessage(new ErrorMessage(msg.cId, "Invalid toSegmentId."))
|
||||
);
|
||||
}
|
||||
|
||||
private void handleSegmentBoundaryMessage(
|
||||
SegmentBoundaryUpdateMessage.Type type,
|
||||
SegmentBoundaryNode segmentBoundary,
|
||||
Segment toSegment
|
||||
) {
|
||||
switch (type) {
|
||||
case ENTERING -> {
|
||||
log.info("Train entering segment {} in rail system {}.", toSegment.getName(), segmentBoundary.getRailSystem().getName());
|
||||
for (var segment : segmentBoundary.getSegments()) {
|
||||
if (!segment.isOccupied()) {
|
||||
segment.setOccupied(true);
|
||||
|
@ -94,20 +108,17 @@ public class SegmentService {
|
|||
}
|
||||
}
|
||||
case ENTERED -> {
|
||||
log.info("Train has entered segment {} in rail system {}.", toSegment.getName(), segmentBoundary.getRailSystem().getName());
|
||||
List<Segment> otherSegments = new ArrayList<>(segmentBoundary.getSegments());
|
||||
// Set the "to" segment as occupied.
|
||||
segmentRepository.findById(msg.toSegmentId).ifPresent(segment -> {
|
||||
segment.setOccupied(true);
|
||||
segmentRepository.save(segment);
|
||||
sendSegmentOccupiedStatus(segment);
|
||||
otherSegments.remove(segment);
|
||||
});
|
||||
toSegment.setOccupied(true);
|
||||
segmentRepository.save(toSegment);
|
||||
otherSegments.remove(toSegment);
|
||||
// And all others as no longer occupied.
|
||||
for (var segment : otherSegments) {
|
||||
if (segment.isOccupied()) {
|
||||
log.info("Train has left segment {} in rail system {}.", segment.getName(), segmentBoundary.getRailSystem().getName());
|
||||
segment.setOccupied(false);
|
||||
segmentRepository.save(segment);
|
||||
}
|
||||
sendSegmentOccupiedStatus(segment);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue