fix: expose and apply control marking handles

This commit is contained in:
2026-08-28 17:45:03 +08:00
parent 7c45c21f8c
commit 11f4d748a7
3 changed files with 41 additions and 4 deletions

View File

@@ -653,12 +653,23 @@ function makeJunctionHandles(model, junctionData, constraints) {
const normal = (tangent + 90) % 360;
const anchor = { type: 'junction-approach', nodeId: String(nodeId), segmentId: approach.segmentId };
const affects = junctionAffects(model, nodeId, segmentIds);
const add = (kind, value, min, max, axis, constraint) => {
// Control markings are positioned by their distance back from the junction,
// rather than at the approach cutback point shared by shape handles. Keeping
// these positions distinct is important: otherwise the later stop-line
// feature covers the crosswalk handle and neither target is discoverable.
const controlPoint = (offsetMeters, lateralMeters = 0) => {
const coordinate = coordinateAt(
line,
Math.min(0.98, Math.max(0.02, offsetMeters / Math.max(approach.length, 1))),
);
return lateralMeters ? offsetCoordinate(coordinate, normal, lateralMeters) : coordinate;
};
const add = (kind, value, min, max, axis, constraint, position = point) => {
handles.push({
handleId: `handle:${kind}:node/${nodeId}:${approach.segmentId}`,
kind,
anchor,
position: point,
position,
axisAzimuth: ((axis % 360) + 360) % 360,
value: { current: value, min, max, unit: 'meter' },
...(constraint ? { constraintId: constraint.id } : {}),
@@ -696,8 +707,12 @@ function makeJunctionHandles(model, junctionData, constraints) {
numericValue(crosswalkConstraint, 'insetMeters', CROSSWALK_JUNCTION_INSET_METERS),
0,
MAX_CROSSWALK_INSET_METERS,
tangent,
// The approach tangent points away from the junction. Increasing an
// inset moves the crosswalk toward the junction, so expose the inverse
// axis to keep positive drag values aligned with the handle's meaning.
(tangent + 180) % 360,
crosswalkConstraint,
controlPoint(numericValue(crosswalkConstraint, 'insetMeters', CROSSWALK_JUNCTION_INSET_METERS), -1),
);
const stopLineConstraint = constraintFor(constraints, 'junction-stop-line-offset', anchor);
add(
@@ -707,6 +722,7 @@ function makeJunctionHandles(model, junctionData, constraints) {
Math.max(MIN_STOP_LINE_OFFSET_METERS, approach.length * 0.45),
tangent,
stopLineConstraint,
controlPoint(numericValue(stopLineConstraint, 'offsetMeters', STOP_LINE_OFFSET_METERS), 1),
);
}
const ordered = [...approaches].sort((a, b) => a.segmentId.localeCompare(b.segmentId));