I have some polygon features on a map layer in OpenLayers. They are contained within a 'boundary' polygon (a field boundary, for context) and fit together perfectly with no 'holes' inside of the boundary polygon (these are soil type 'zones' within the field boundary).
I need to be able to draw a new polygon and have it be trimmed by the boundary polygon and then trim the polygons it overlaps so there are no overlapping polygons, like a puzzle. I have successfully done this in steps but there's one element of the outcome I'm not happy with and I can't see how to change it. This is the way it currently works:
- This is the starting point.The 'zone' polygons (2 of them) within the field boundary (red).
- I draw a polygon that overlaps the field boundary and the zones. At this point I trim this newly drawn 'zone' polygon to the field boundary using JSTS intersection, and then with the resulting geometry loop through the existing 'zone' features and perform a JSTS difference on each to create new features based on the original 'zone' polygons. Then I remove the original features from the layer and add the new drawn polygon and the edited 'zone' polygons. And this is the result:
...which is exactly what I need it to be, except for one thing. You'll notice that the zone the new polygon split in half (zone #2) is still one zone, just in two parts. If I click on it, it becomes obvious that it's one polygon:
...but zone #1 is correctly edited:
How do I detect when a polygon has been entirely divided by a JSTS difference and return two polygons, rather than the one shown here?
Here is the code I have to achieve what the images demonstrate:
// end drawing if clicked save rather than double click
drawTool.finishDrawing();
// save the drawn feature
drawnFeature = drawing_source.getFeatures()[0];
if(drawnFeature === undefined)
{
// nothing drawn
map.removeInteraction(drawTool);
addSelectAndModifyForZones(highlighted_zone.getId());
}
else
{
// check if zones of the field are greater than 0
if(allSubZones.length > 0)
{
var containingZone;
try {
// read drawn geometry in jsts format
var b = parser.read(drawnFeature.getGeometry());
var drawn_area = get_area(drawnFeature);
// first check the intersection/trim with the field boundary
var field;
$.each(field_hotspot_layer.getSource().getFeatures(), function(index, this_feature) {
if(this_feature.getId().toString() === current_live_field.toString())
{
field = this_feature;
}
});
var a = parser.read(field.getGeometry());
var common_ground = a.intersection(b);
if(parser.write(common_ground).flatCoordinates.length === 0)
{
// drawn area is entirely outside the field boundary!
// warn the user and stop here
map.removeInteraction(drawTool);
addSelectAndModifyForZones(highlighted_zone.getId());
// clear our drawing source
drawing_source.clear();
}
else
{
var temp_feature = new ol.Feature({
geometry: parser.write(common_ground),
description: "TEMP"
});
temp_feature.setStyle(TEMP_style);
// get area
var overlap_area = get_area(temp_feature);
if(drawn_area.toFixed(2) === overlap_area.toFixed(2))
{
// drawn area is inside field boundary
console.log("drawn area is inside field boundary");
}
else
{
// drawn area is at least partially outside the field boundary
console.log("drawn area is at least partially outside the field boundary");
}
// either way the intersection should be the geometry to move forward with
// convert drawn geometry to OL feature and attach default style, white opaque bg and black border
var newPoly = new ol.Feature({
geometry: parser.write(common_ground),
z_index: '1',
zone_border: 'rgba(0,0,0,1)',
zone_border_width: '2',
zone_colour: 'rgba(255,255,255,0.5)',
zone_number: allSubZones.length+1
});
newPoly.setStyle(visible_zone_style);
// add it to the source
currentZoneLayer.getSource().addFeature(newPoly);
// loop through all the zones and find difference with the drawn polygon
for(p = 0; p < allSubZones.length; p++)
{
containingZone = allSubZones[p];
var a = parser.read(containingZone.getGeometry());
var difference = a.difference(common_ground);
// convert difference to OL feature, original geom minus the drawn geom
olPolygon = new ol.Feature({
geometry: parser.write(difference),
description: containingZone.get('description'),
z_index: containingZone.get('z_index'),
zone_border: containingZone.get('zone_border'),
zone_border_width: containingZone.get('zone_border_width'),
zone_colour: containingZone.get('zone_colour'),
zone_number: containingZone.get('zone_number'),
zone_value: containingZone.get('zone_value')
});
olPolygon.setStyle(visible_zone_style);
// add it to the source
currentZoneLayer.getSource().addFeature(olPolygon);
selectZoneControl.setActive(true);
// clear our drawing source
drawing_source.clear();
// remove original old geometry
currentZoneLayer.getSource().removeFeature(containingZone);
}
}
} catch (e) {
console.log(e);
} finally {
}
}
}