Search code examples
openlayerspolygongwt-openlayers

openlayers polygon displays difference not union


In OpenLayers, I create a polygon consisting of two LinearRing objects, using code of the form (this is in Java+GWT, but the same principle applies to JS):

List<LinearRing> linearRingList = new ArrayList<LinearRing>();

List<Point> points1 = new ArrayList<Point>();
... populate points1 ...;
linearRingList.add(new LinearRing(points1.toArray(new Point[points.size()])));

List<Point> points2 = new ArrayList<Point>();
... populate points2 ...;
linearRingList.add(new LinearRing(points2.toArray(new Point[points.size()])));

Polygon poly = new Polygon(linearRingList.toArray(new LinearRing[linearRingList.size()]));
VectorFeature feature = new VectorFeature(poly);
myLayer.addFeature(feature);

When I view this layer on a map, if the polygons defined by points1 and points2 overlap, I see a hole:

polygon hole http://www.jackhollow.co.uk/misc/polygon.png

I'm seeing the "xor" of the two polygons, where I want to see the "or" of them instead, ie with that hole in the middle filled in green.

How do I do this? I'm sure it's just a display issue in Openlayers, but I can't find a flag to control it anywhere.

The original two polygons are as:

polygon hole http://www.jackhollow.co.uk/misc/polygon2.png

if displayed together on a single layer they overlap, but Openlayers is not filling in the intersecting parts.


Solution

  • The problem is that you are adding both LinearRings to the same Polygon. All rings, after the first, are defined as inner rings of a polygon (ie, internal holes), which explains the strange intersection behavior you are seeing -- an attempt to draw an inner ring, which is not in fact inside. See components in the documentation. To fix your problem, you need to create two separate Geometry.Polygons and two separate Feature.Vectors and add both of these to your Layer.Vector.

     var linearRing1 = new OpenLayers.Geometry.LinearRing(pointList1);
     var feature1 = new OpenLayers.Feature.Vector(
              new OpenLayers.Geometry.Polygon([linearRing1]));
    
     var linearRing2 = new OpenLayers.Geometry.LinearRing(pointList2);
     var feature2 = new OpenLayers.Feature.Vector(
              new OpenLayers.Geometry.Polygon([linearRing2]));
    
    
    var layer = new OpenLayers.Layer.Vector("layername");
    layer.addFeatures([feature1, feature2]);
    

    where you create your point lists as before. You can also add attributes and styles to each feature vector, or a style to the layer vector, but I left this out for clarity.

    There is no explicit check in OpenLayers that your geometry is correct, ie, that the inner rings are actually inside the outer ring, so if you hand an array of line strings to a polygon constructor, an attempt will be made to convert this to the appropriate SVG or VML objects, with unpredictable results.