Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Droth 3109 lane split problems branched from master #2003

Merged
5 changes: 1 addition & 4 deletions UI/src/controller/laneModellingCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
right.points = split.secondSplitVertices;
right.startMeasure = split.splitMeasure;

if (self.calculateMeasure(left) < self.calculateMeasure(right)) {
if (left.startMeasure < right.startMeasure) {
self.splitLinearAssets.created = left;
self.splitLinearAssets.existing = right;
} else {
Expand All @@ -53,9 +53,6 @@
self.splitLinearAssets.created.id = 0;
self.splitLinearAssets.existing.id = 0;

self.splitLinearAssets.created.marker = 'A';
self.splitLinearAssets.existing.marker = 'B';

self.dirty = true;
callback(self.splitLinearAssets);
};
Expand Down
57 changes: 31 additions & 26 deletions UI/src/model/selectedLaneModelling.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,44 +74,42 @@
return numberOfLanesByLaneCode[key] > 1;
});

var lanesSortedByLaneCode = _.sortBy(lanes, getLaneCodeValue);

var duplicateLaneCounter = 0;
return _.map(lanesSortedByLaneCode, function (lane) {
if(_.includes(laneCodesToPutMarkers, getLaneCodeValue(lane).toString())) {
if (duplicateLaneCounter === 0){
lane.marker = 'A';
duplicateLaneCounter++;
}else{
lane.marker = 'B';
duplicateLaneCounter--;
var lanesSortedByEndMeasure = _.sortBy(lanes, function(lane) {
return lane.endMeasure;
});

_.forEach(laneCodesToPutMarkers, function (laneCode) {
var characterCounterForLaneMarker = 0;
for (var i = 0; i < lanesSortedByEndMeasure.length; i++) {
if (laneCode == getLaneCodeValue(lanesSortedByEndMeasure[i]).toString()) {
//The integer value of 'A' is 65, so every increment in the counter gives the next letter of the alphabet.
lanesSortedByEndMeasure[i].marker = String.fromCharCode(characterCounterForLaneMarker + 65);
characterCounterForLaneMarker += 1;
}
}
return lane;
});

return lanesSortedByEndMeasure;
};

//Outer lanes that are expired are to be considered, the other are updates so we need to take those out
//Here a outer lane is a lane with lane code that existed in the original but not in the modified configuration
function omitIrrelevantExpiredLanes() {
var lanesToBeRemovedFromExpire = _.filter(assetsToBeExpired, function (lane) {
return !_.isUndefined(self.getLane(getLaneCodeValue(lane)));
return !self.isOuterLane(getLaneCodeValue(lane));
});

_.forEach(lanesToBeRemovedFromExpire, function (lane) {
_.remove(assetsToBeExpired, {'id': lane.id});
});
}

self.splitLinearAsset = function(laneNumber, split) {
collection.splitLinearAsset(self.getLane(laneNumber), split, function(splitLinearAssets) {
if (self.getLane(laneNumber).id === 0) {
self.removeLane(laneNumber);
} else {
self.expireLane(laneNumber);
}

self.splitLinearAsset = function(laneNumber, split, laneMarker) {
collection.splitLinearAsset(self.getLane(laneNumber, laneMarker), split, function(splitLinearAssets) {
var laneIndex = getLaneIndex(laneNumber, laneMarker);
self.selection.splice(laneIndex,1);
self.selection.push(splitLinearAssets.created, splitLinearAssets.existing);
self.selection = giveSplitMarkers(self.selection);
self.dirty = true;
eventbus.trigger('laneModellingForm: reload');
});
Expand Down Expand Up @@ -198,18 +196,25 @@

self.lanesCutAreEqual = function() {
var laneNumbers = _.map(self.selection, getLaneCodeValue);
var cuttedLaneNumbers = _.transform(_.countBy(laneNumbers), function(result, count, value) {
var cutLaneNumbers = _.transform(_.countBy(laneNumbers), function(result, count, value) {
if (count > 1) result.push(value);
}, []);

return _.some(cuttedLaneNumbers, function (laneNumber){
return _.some(cutLaneNumbers, function (laneNumber){
var lanes = _.filter(self.selection, function (lane){
return _.find(lane.properties, function (property) {
return property.publicId == "lane_code" && _.head(property.values).value == laneNumber;
});
});

return _.isEqual(lanes[0].properties, lanes[1].properties);
var sortedLanes = _.sortBy(lanes, function (lane) {
return lane.endMeasure;
});
for (var i = 1; i < sortedLanes.length; i++) {
if (_.isEqual(sortedLanes[i - 1].properties, sortedLanes[i].properties)) {
return true;
}
}
return false;
});
};

Expand Down Expand Up @@ -382,7 +387,7 @@

//expiredLane could be modified by the user so we need to fetch the original
var originalExpiredLane = _.find(lanesFetched, {'id': expiredLane.id});
if (linksSelected.length > 1) {
if (linksSelected.length > 1 && _.isUndefined(marker)) {
var expiredGroup = collection.getGroup(originalExpiredLane);
expiredGroup.forEach(function (lane) {
lane.isExpired = true;
Expand Down
21 changes: 9 additions & 12 deletions UI/src/view/linear_asset/laneModellingForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -443,23 +443,20 @@
});
});

asset = _.sortBy(asset, function (lane) {
return lane.marker;
});

var body = createBodyElement(selectedAsset.getCurrentLane());

if(selectedAsset.isSplit()) {
//Render form A
renderFormElements(_.find(asset,{'marker': 'A'}), isReadOnly, 'A', selectedAsset.setValue, selectedAsset.getValue, false, body);

if(!isReadOnly)
renderExpireAndDeleteButtonsElement(selectedAsset, body, 'A');

body.find('.form').append('<hr class="form-break">');
//Render form B
renderFormElements(_.find(asset,{'marker': 'B'}), isReadOnly, 'B', selectedAsset.setValue, selectedAsset.getValue, false, body);

if(!isReadOnly)
renderExpireAndDeleteButtonsElement(selectedAsset, body, 'B');
_.forEach(asset, function (lane) {
renderFormElements(lane, isReadOnly, lane.marker, selectedAsset.setValue, selectedAsset.getValue, false, body);
if(!isReadOnly) renderExpireAndDeleteButtonsElement(selectedAsset, body, lane.marker);
body.find('.form').append('<hr class="form-break">');
});

body.find('.form').append('<hr class="form-break">');
}else{
renderFormElements(asset[0], isReadOnly, '', selectedAsset.setValue, selectedAsset.getValue, isDisabled, body);

Expand Down
85 changes: 65 additions & 20 deletions UI/src/view/linear_asset/laneModellingLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

var LinearAssetCutter = function(eventListener, vectorLayer) {
var scissorFeatures = [];
var CUT_THRESHOLD = 20;
//Max euclidean distance in geometry points allowed between mouse point and the closest linear asset point (the planned cut point).
var CUT_THRESHOLD = 5;
var vectorSource = vectorLayer.getSource();

var moveTo = function(x, y) {
Expand Down Expand Up @@ -81,8 +82,17 @@
return property.publicId === "lane_code";
}).values).value;

return !selectedLane.isOuterLane(laneNumber) || laneNumber == 1 ||
!_.isUndefined(properties.marker) || properties.selectedLinks.length > 1 || selectedLane.isAddByRoadAddress();
var uniqueSelectedRoadLinkIds = _.uniq(_.map(properties.selectedLinks, function (selectedLink) {
return selectedLink.linkId;
}));
if(_.isUndefined(uniqueSelectedRoadLinkIds)) {
return true;
}

var SelectedLaneCannotBeCut = !selectedLane.isOuterLane(laneNumber) || laneNumber == 1 || laneNumber != selectedLane.getCurrentLaneNumber() ||
uniqueSelectedRoadLinkIds.length > 1 || selectedLane.isAddByRoadAddress();

return SelectedLaneCannotBeCut;
})
.map(function(feature) {
var closestP = feature.getGeometry().getClosestPoint(point);
Expand All @@ -100,6 +110,44 @@
.value();
};

var getLanePieceToCut = function (point) {

var minSquaredDistanceBetweenPointAndLane = function (lane, point) {
var min_x_dist = Math.abs(lane.points[0].x - point[0]);
var min_y_dist = Math.abs(lane.points[0].y - point[1]);
for(var i=1; i < lane.points.length; i++) {
min_x_dist = Math.min(min_x_dist, Math.abs(lane.points[i].x - point[0]));
min_y_dist = Math.min(min_y_dist, Math.abs(lane.points[i].y - point[1]));
}
return Math.pow(min_x_dist, 2) + Math.pow(min_y_dist, 2);
};

var selected = selectedLane.get();

selected = _.reject(selected, function (lane) {
var laneNumber = _.head(_.find(lane.properties, function(property){
return property.publicId === "lane_code";
}).values).value;

return !selectedLane.isOuterLane(laneNumber) || laneNumber == 1 ||
laneNumber != selectedLane.getCurrentLaneNumber() || selectedLane.isAddByRoadAddress();
});

selected = _.sortBy(selected, function (lane) {
return minSquaredDistanceBetweenPointAndLane(lane, point);
});

var cutLanes = _.reject(selected, function (lane) {
return _.isUndefined(lane.marker);
});

if (_.isEmpty(cutLanes)) {
return _.head(selected);
}

return _.head(cutLanes);
};

this.updateByPosition = function(mousePoint) {
var closestLinearAssetLink = findNearestLinearAssetLink(mousePoint);
if (closestLinearAssetLink) {
Expand Down Expand Up @@ -128,18 +176,14 @@
return _.merge({ splitMeasure: splitMeasure }, splitVertices);
};

var nearest = findNearestLinearAssetLink([mousePoint.x, mousePoint.y]);

if (_.isUndefined(nearest) || !isWithinCutThreshold(nearest.distance)) {
return;
}
var nearestLinearAsset = getLanePieceToCut([mousePoint.x, mousePoint.y]);
if (_.isUndefined(nearestLinearAsset)) return;

var nearestLinearAsset = nearest.feature.getProperties();
if(authorizationPolicy.formEditModeAccess(nearestLinearAsset)) {
var splitProperties = calculateSplitProperties(laneUtils.offsetByLaneNumber(nearestLinearAsset, false, true), mousePoint);
var splitProperties = calculateSplitProperties(nearestLinearAsset, mousePoint);
selectedLane.splitLinearAsset(_.head(_.find(nearestLinearAsset.properties, function(property){
return property.publicId === "lane_code";
}).values).value, splitProperties);
}).values).value, splitProperties, nearestLinearAsset.marker);

remove();
}
Expand Down Expand Up @@ -296,6 +340,7 @@
};

var drawSplitPoints = function (links) {

function findSplitPoints(links) {
var sortedPoints = _.flatMap(links, function (link) {
return link.points;
Expand Down Expand Up @@ -381,7 +426,7 @@
var linearAssets = _.flatten(linearAssetChains);
var allButSelected = _.filter(linearAssets, function(asset){ return !_.some(selectedLane.get(), function(selectedAsset){
return selectedAsset.linkId === asset.linkId && selectedAsset.sideCode == asset.sideCode &&
selectedAsset.startMeasure === asset.startMeasure && selectedAsset.endMeasure === asset.endMeasure; }) ;
selectedAsset.startMeasure === asset.startMeasure && selectedAsset.endMeasure === asset.endMeasure; }) ;
});
me.vectorSource.addFeatures(style.renderFeatures(allButSelected));
var oneWaySignsDraft = getOneWaySigns(allButSelected);
Expand Down Expand Up @@ -430,17 +475,17 @@
var selectedFeatures = style.renderFeatures(linearAssets, laneNumber);

if (assetLabel) {
var currentFeatures = _.filter(me.vectorSource.getFeatures(), function (layerFeature) {
return _.some(selectedFeatures, function (selectedFeature) {
return me.geometryAndValuesEqual(selectedFeature.values_, layerFeature.values_);
});
var currentFeatures = _.filter(me.vectorSource.getFeatures(), function (layerFeature) {
return _.some(selectedFeatures, function (selectedFeature) {
return me.geometryAndValuesEqual(selectedFeature.values_, layerFeature.values_);
});
});

_.each(currentFeatures, me.removeFeature);
_.each(currentFeatures, me.removeFeature);

selectedFeatures = selectedFeatures.concat(assetLabel.renderFeaturesByLinearAssets(extractMiddleLinksOfChains([_.map(selectedFeatures, function (feature) {
return feature.getProperties();
})]), me.uiState.zoomLevel));
selectedFeatures = selectedFeatures.concat(assetLabel.renderFeaturesByLinearAssets(extractMiddleLinksOfChains([_.map(selectedFeatures, function (feature) {
return feature.getProperties();
})]), me.uiState.zoomLevel));
}

removeOldAssetFeatures();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,12 +277,12 @@ object LaneChangeType {
values.find(_.value == value).getOrElse(Unknown)
}

case object Add extends LaneChangeType { def value = 1; def description = "Lane is added normally";}
case object Lengthened extends LaneChangeType {def value = 2; def description = "Old lane is deleted and then a new lane is created with more length";}
case object Shortened extends LaneChangeType {def value = 3; def description = "Old lane is deleted and then a new lane is created with less length";}
case object Expired extends LaneChangeType {def value = 4; def description = "Lane is expired normally";}
case object LaneCodeTransfer extends LaneChangeType {def value = 5; def description = "Lane with some code was changed to another code";}
case object AttributesChanged extends LaneChangeType {def value = 6; def description = "Lane attributes were changed";}
case object Divided extends LaneChangeType {def value = 7; def description = "Old lane is deleted and then two more appear in same lane code";}
case object Unknown extends LaneChangeType {def value = 99; def description = "Unknown change to lane";}
case object Add extends LaneChangeType { def value = 1; def description = "A new lane is added from scratch";}
case object Lengthened extends LaneChangeType {def value = 2; def description = "The old lane is replaced with a longer new lane";}
case object Shortened extends LaneChangeType {def value = 3; def description = "The old lane is replaced with a shorter new lane";}
case object Expired extends LaneChangeType {def value = 4; def description = "A lane is expired with no replacements";}
case object LaneCodeTransfer extends LaneChangeType {def value = 5; def description = "The lane code is changed";}
case object AttributesChanged extends LaneChangeType {def value = 6; def description = "Some of the lane attributes are changed";}
case object Divided extends LaneChangeType {def value = 7; def description = "The old lane is replaced with two or more lane pieces";}
case object Unknown extends LaneChangeType {def value = 99; def description = "Unknown lane change";}
}
Loading