-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
GEOS-8033: Adding the "kmcentroid" option to KML.
The option provides the capability to specify options that control how the placement of a KML place mark occurs. Namely to clip the geometry before calculating the centroid, and the ability to generate a centroid that falls within a polygon.
- Loading branch information
Showing
6 changed files
with
250 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
src/kml/src/main/java/org/geoserver/kml/utils/KmlCentroidOptions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* (c) 2017 Open Source Geospatial Foundation - all rights reserved | ||
* This code is licensed under the GPL 2.0 license, available at the root | ||
* application directory. | ||
*/ | ||
package org.geoserver.kml.utils; | ||
|
||
import org.geoserver.kml.KmlEncodingContext; | ||
import org.geoserver.ows.util.CaseInsensitiveMap; | ||
import org.geoserver.ows.util.KvpMap; | ||
|
||
import java.util.Collections; | ||
import java.util.Map; | ||
|
||
/** | ||
* Options used for computing geometry centroids by {@link KmlCentroidBuilder}. | ||
*/ | ||
public class KmlCentroidOptions { | ||
|
||
public static final String PREFIX = "kmcentroid"; | ||
public static final String CONTAIN = PREFIX + "_contain"; | ||
public static final String SAMPLE = PREFIX + "_sample"; | ||
public static final String CLIP = PREFIX + "_clip"; | ||
|
||
public static final KmlCentroidOptions DEFAULT = new KmlCentroidOptions(new KvpMap()); | ||
|
||
static final int DEFAULT_SAMPLES = 5; | ||
|
||
/** | ||
* Creates centroid options from the specified encoding context. | ||
*/ | ||
public static KmlCentroidOptions create(KmlEncodingContext context) { | ||
return create(context != null && context.getRequest() != null ? | ||
context.getRequest().getFormatOptions() : Collections.EMPTY_MAP); | ||
} | ||
|
||
/** | ||
* Creates centroid options from the specified format options. | ||
*/ | ||
public static KmlCentroidOptions create(Map formatOptions) { | ||
if (formatOptions != null) { | ||
for (Object key : formatOptions.keySet()) { | ||
if (key.toString().toLowerCase().startsWith(PREFIX)) { | ||
return new KmlCentroidOptions(CaseInsensitiveMap.wrap(formatOptions)); | ||
} | ||
} | ||
} | ||
return KmlCentroidOptions.DEFAULT; | ||
} | ||
|
||
Map raw; | ||
|
||
public KmlCentroidOptions(Map raw) { | ||
this.raw = raw; | ||
} | ||
|
||
/** | ||
* Determines if the "contain" option is set. | ||
* <p> | ||
* This option causes the centroid builder to find a point (via sampling if necessary) that is | ||
* contained within a polygon geometry. | ||
* </p> | ||
* @see #getSamples() | ||
*/ | ||
public boolean isContain() { | ||
return Boolean.valueOf(raw.getOrDefault(CONTAIN, "false").toString()); | ||
} | ||
|
||
/** | ||
* Determines if the "clip" option is set. | ||
* <p> | ||
* This option causes the centroid builder to clip geometries by the request bounding box before | ||
* computing the centroid. | ||
* </p> | ||
*/ | ||
public boolean isClip() { | ||
return Boolean.valueOf(raw.getOrDefault(CLIP, "false").toString()); | ||
} | ||
|
||
/** | ||
* The number of samples to try when computing a centroid when {@link #isContain()} is set. | ||
* <p> | ||
* When unset this falls back to | ||
* </p> | ||
*/ | ||
public int getSamples() { | ||
try { | ||
return Integer.parseInt(raw.getOrDefault(SAMPLE, String.valueOf(DEFAULT_SAMPLES)).toString()); | ||
} | ||
catch(NumberFormatException e) { | ||
return DEFAULT_SAMPLES; | ||
} | ||
} | ||
|
||
} |
73 changes: 73 additions & 0 deletions
73
src/kml/src/test/java/org/geoserver/kml/utils/KmlCentroidBuilderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/* (c) 2017 Open Source Geospatial Foundation - all rights reserved | ||
* This code is licensed under the GPL 2.0 license, available at the root | ||
* application directory. | ||
*/ | ||
package org.geoserver.kml.utils; | ||
|
||
import com.google.common.collect.ImmutableMap; | ||
import com.vividsolutions.jts.geom.Coordinate; | ||
import com.vividsolutions.jts.geom.Envelope; | ||
import com.vividsolutions.jts.geom.Geometry; | ||
import com.vividsolutions.jts.io.WKTReader; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
import static org.geoserver.kml.utils.KmlCentroidOptions.CLIP; | ||
import static org.geoserver.kml.utils.KmlCentroidOptions.CONTAIN; | ||
import static org.geoserver.kml.utils.KmlCentroidOptions.SAMPLE; | ||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertFalse; | ||
import static org.junit.Assert.assertTrue; | ||
|
||
public class KmlCentroidBuilderTest { | ||
|
||
Geometry cShapeGeom; | ||
|
||
@Before | ||
public void setUp() throws Exception { | ||
cShapeGeom = new WKTReader().read("POLYGON ((-112.534433451864 43.8706532611928,-112.499157652296 44.7878240499628,-99.6587666095152 44.7878240499628,-99.7242788087131 43.2155312692142,-111.085391877449 43.099601544023,-110.744593363875 36.1862602686501,-98.6760836215473 35.9436771582516,-98.7415958207452 33.5197257879307,-111.77852346112 33.9783111823157,-111.758573671673 34.6566040234952,-113.088767445077 34.7644575726901,-113.023255245879 43.8706532611928,-112.534433451864 43.8706532611928))"); | ||
} | ||
|
||
@Test | ||
public void testSampleForPoint() throws Exception { | ||
Geometry g = cShapeGeom; | ||
|
||
KmlCentroidOptions opts1 = KmlCentroidOptions.create(ImmutableMap.of(CONTAIN, "true", SAMPLE, "2")); | ||
KmlCentroidOptions opts2 = KmlCentroidOptions.create(ImmutableMap.of(CONTAIN, "true", SAMPLE, "10")); | ||
|
||
KmlCentroidBuilder builder = new KmlCentroidBuilder(); | ||
|
||
Coordinate c = builder.geometryCentroid(g, null, opts1); | ||
assertFalse(g.contains(g.getFactory().createPoint(c))); | ||
|
||
c = builder.geometryCentroid(g, null, opts2); | ||
assertTrue(g.contains(g.getFactory().createPoint(c))); | ||
} | ||
|
||
@Test | ||
public void testClip() { | ||
Geometry g = cShapeGeom; | ||
KmlCentroidOptions opts1 = KmlCentroidOptions.create(ImmutableMap.of()); | ||
KmlCentroidOptions opts2 = KmlCentroidOptions.create(ImmutableMap.of(CLIP, "true")); | ||
opts2.isClip(); | ||
|
||
KmlCentroidBuilder builder = new KmlCentroidBuilder(); | ||
|
||
Coordinate c = builder.geometryCentroid(g, null, opts1); | ||
assertFalse(g.contains(g.getFactory().createPoint(c))); | ||
|
||
Envelope bbox = new Envelope( | ||
-106.603059724489, -103.655010760585, 34.6334331742943, 36.9918723454173); | ||
c = builder.geometryCentroid(g, bbox, opts2); | ||
assertTrue(g.contains(g.getFactory().createPoint(c))); | ||
} | ||
|
||
@Test | ||
public void testCaseInsensitivity() { | ||
KmlCentroidOptions opts = KmlCentroidOptions.create(ImmutableMap.of( | ||
CONTAIN.toUpperCase(), "true", CLIP.toUpperCase(), "true", SAMPLE.toUpperCase(), "12")); | ||
assertTrue(opts.isContain()); | ||
assertTrue(opts.isClip()); | ||
assertEquals(12, opts.getSamples()); | ||
} | ||
} |