Skip to content

Instantly share code, notes, and snippets.

@dbaston
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dbaston/d3f8f873f8b9e10569e3 to your computer and use it in GitHub Desktop.
Save dbaston/d3f8f873f8b9e10569e3 to your computer and use it in GitHub Desktop.
package com.maponics.algorithm;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.operation.polygonize.Polygonizer;
import com.vividsolutions.jts.operation.union.UnaryUnionOp;
import java.util.*;
import java.util.concurrent.Callable;
/**
*
* @author dbaston
*/
public class PolygonBuilder implements Callable<Geometry> {
private final Polygonizer polygen;
public PolygonBuilder(Collection<Geometry> inputs) {
this.polygen = new Polygonizer();
// Inputs that are incorrectly noded or may have duplicate geometry
// can cause the polygonizer to fail. Since polygonization is often
// at the end of a long process, the price of UnaryUnionOp.Union()
// is well worth it.
//this.polygen.add(inputs);
this.polygen.add(UnaryUnionOp.union(inputs));
}
@Override
public Geometry call() {
return this.getResult();
}
/** Given a collection of JTS Geometry objects, returns the subset of
* Geometries that have at least one vertex that is not shared by
* any other Geometry in the input set.
* @param polys
* @return
*/
public static Collection<Geometry> getNonRedundantGeom(Collection<Geometry> polys) {
HashSet<Coordinate> uniqueVertices = new HashSet<>();
HashSet<Coordinate> duplicateVertices = new HashSet<>();
for (Geometry p : polys) {
HashSet<Coordinate> verticesInThisPolygon = new HashSet<>(Arrays.asList(p.getCoordinates()));
for (Coordinate c : verticesInThisPolygon) {
if (!uniqueVertices.contains(c) && !duplicateVertices.contains(c)) {
uniqueVertices.add(c);
} else {
uniqueVertices.remove(c);
duplicateVertices.add(c);
}
}
}
Set<Geometry> exteriorPolys = new HashSet<>();
for (Geometry p : polys) {
for (Coordinate c : p.getCoordinates()) {
if (!duplicateVertices.contains(c)) {
// If this poly has at least one unique vertex, it must be exterior
exteriorPolys.add(p);
break;
}
}
}
return exteriorPolys;
}
/** Uses a JTS Polygonizer to identify all possible polygons from a set
* of input linework, then uses an iterative algorithm to determine which
* of the returned polygons represent holes. The algorithm is:
* 1. Identify the outermost polygons in the returned set (those polygons
* that have at least one unique vertex). These polygons cannot
* be holes.
* 2. Classify as a "hole" any polygon that has a linear intersection with
* a non-hole polygon.
* 3. Classify as "non-hole" any polygon that has a linear intersection
* with a hole polygon.
* 4. Repeat steps 2-3 until all polygons have been classified.
*
* @return A single Geometry representing the union of all non-hole polygons.
*/
public Geometry getResult() {
Collection<Geometry> polys = polygen.getPolygons();
Set<Geometry> exteriorPolys = new HashSet<>(getNonRedundantGeom(polys));
Set<Geometry> unknownPolys = new HashSet<>(polys);
Set<Geometry> interiorPolys = new HashSet<>();
unknownPolys.removeAll(exteriorPolys);
Geometry mainPoly = UnaryUnionOp.union(exteriorPolys);
Geometry holePoly = null;
boolean changed = true;
while (!unknownPolys.isEmpty() && changed) {
interiorPolys.clear();
exteriorPolys.clear();
changed = false;
for (Geometry p : unknownPolys) {
if (p.intersects(mainPoly) && p.intersection(mainPoly).getDimension() > 0) {
changed = true;
interiorPolys.add(p);
} else if (holePoly != null && p.intersects(holePoly) && p.intersection(holePoly).getDimension() > 0) {
changed = true;
exteriorPolys.add(p);
}
}
unknownPolys.removeAll(exteriorPolys);
unknownPolys.removeAll(interiorPolys);
if (!exteriorPolys.isEmpty()) {
exteriorPolys.add(mainPoly);
mainPoly = UnaryUnionOp.union(exteriorPolys);
}
if (!interiorPolys.isEmpty()) {
if (holePoly != null) {
interiorPolys.add(holePoly);
}
holePoly = UnaryUnionOp.union(interiorPolys);
}
}
return mainPoly;
}
}
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.PrecisionModel;
import com.vividsolutions.jts.geom.util.LinearComponentExtracter;
import com.vividsolutions.jts.noding.snapround.GeometryNoder;
import java.util.ArrayList;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.assertTrue;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/**
*
* @author dbaston
*/
public class PolygonBuilderTest {
public PolygonBuilderTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
private static Geometry getPolygonsFromGeometryCollection(String wkt) throws Exception {
ArrayList<Geometry> components = new ArrayList<>();
GeometryCollection coll = (GeometryCollection) geomFromWKT(wkt);
for (int i=0; i < coll.getNumGeometries(); i++) {
components.add(coll.getGeometryN(i));
}
PolygonBuilder pb = new PolygonBuilder(components);
return pb.getResult();
}
private static void checkInputMatchesOutput(String wkt) throws Exception {
Geometry input = geomFromWKT(wkt);
GeometryNoder gn = new GeometryNoder(new PrecisionModel(1e6));
Geometry poly = new PolygonBuilder(
gn.node(LinearComponentExtracter.getLines(input, true))).getResult();
assertTrue(input.equalsTopo(poly));
}
/**
* Test of isHole method, of class PolygonBuilder.
*/
@Test
public void testIsHoleDonut() throws Exception {
checkInputMatchesOutput(
"POLYGON ((0 0, 0 20, 20 20, 20 0, 0 0), " +
" (5 5, 15 5, 15 15, 5 15, 5 5))");
}
/**
* Three polygon components, in which a "top" and "bottom" each touch at
* two single points. A third "middle" is situated in between.
*
* ___________
* | |
* | /\ |
* | / \ |
* | / \ |
* | / \ |
* |/ \|
* |\ /|
* | \ / |
* | \ / |
* | \ / |
* | \/ |
* |__________|
*
* @throws Exception
*/
@Test
public void testIsHoleBetweenTwoPieces() throws Exception {
checkInputMatchesOutput(
"MULTIPOLYGON (((0 0, 0 10, 5 5, 10 10, 10 0, 0 0)), " +
"((0 10, 0 20, 10 20, 10 10, 5 15, 0 10)))");
}
/** ____________________
* | ______________ |
* | | ________ | |
* | | | | | |
* | | |______| | |
* | |____________| |
* |__________________|
*
* @throws Exception
*/
@Test
public void testBullsEye() throws Exception {
checkInputMatchesOutput(
"MULTIPOLYGON (((0 0, 0 20, 20 20, 20 0, 0 0), " +
" (5 5, 15 5, 15 15, 5 15, 5 5))," +
" ((8 8, 8 12, 12 12, 12 8, 8 8)))"
);
}
/** ____________________
* | _____________ |
* | | ___ | |
* | | |__|___| |
* | |________| |
* |__________________|
*/
@Test
public void testConnectedComponentInsideHole() throws Exception {
checkInputMatchesOutput(
"MULTIPOLYGON (((0 0, 0 20, 40 20, 40 0, 0 0)," +
" (30 10, 35 10, 35 15, 5 15, 5 5, 30 5, 30 10))," +
" ((20 10, 20 12, 30 12, 30 10, 20 10)))");
}
@Test
public void testMultipleIterationsNeededToSolve() throws Exception {
checkInputMatchesOutput(
"MULTIPOLYGON (((0 0, 0 70, 70 70, 70 0, 0 0), " +
"(20 10, 30 10, 30 20, 40 20, 40 10, 50 10, 50 20, 60 20, 60 30, 50 30, 50 40, 60 40, 60 50, 50 50, 50 60, 40 60, 40 50, 30 50, 30 60, 20 60, 20 50, 10 50, 10 40, 20 40, 20 30, 10 30, 10 20, 20 20, 20 10))," +
" ((20 20, 20 30, 30 30, 30 20, 20 20))," +
" ((40 20, 40 30, 50 30, 50 20, 40 20))," +
" ((30 30, 30 40, 40 40, 40 30, 30 30))," +
" ((20 40, 20 50, 30 50, 30 40, 20 40))," +
" ((40 40, 40 50, 50 50, 50 40, 40 40)))");
}
@Test
public void testRegrNoTopologyException() throws Exception {
Geometry poly = getPolygonsFromGeometryCollection("GEOMETRYCOLLECTION (LINESTRING (-82.727094 42.720942, -82.727089 42.720841, -82.727083 42.720756, -82.727079 42.720704, -82.72707 42.720533, -82.727071 42.720477, -82.72707 42.720422, -82.727068 42.720365, -82.727063 42.720303, -82.727054 42.720171, -82.72705 42.720107, -82.727047 42.720044, -82.727043 42.71998, -82.72704 42.719914, -82.727036 42.719846, -82.727031 42.719773, -82.727027 42.719696, -82.727017 42.719536, -82.727007 42.719382, -82.727003 42.719307, -82.72699 42.71909, -82.726987 42.719022, -82.726981 42.718893, -82.72698 42.718791, -82.726988 42.718728, -82.727011 42.718673, -82.727069 42.718633, -82.727145 42.718613, -82.724705 42.718701, -82.723486 42.718744, -82.723567 42.721062), LINESTRING (-82.624127 42.664958, -82.625148 42.665203, -82.62525 42.665784, -82.625086 42.666494, -82.625375 42.666948, -82.625385 42.667085, -82.625857 42.667638, -82.625809 42.667759, -82.625545 42.667917, -82.626493 42.668687, -82.626869 42.668576, -82.628547 42.670132, -82.628313 42.670165, -82.628591 42.67039, -82.62864 42.670364, -82.62881 42.670376, -82.628864 42.670438, -82.628901 42.670577, -82.628662 42.670715, -82.628727 42.670903, -82.628975 42.671178, -82.629518 42.671814, -82.629927 42.672149, -82.630327 42.672422, -82.630541 42.672597, -82.63081 42.672744, -82.630881 42.672908, -82.630851 42.673169, -82.630937 42.673281, -82.631498 42.673604, -82.631838 42.673889, -82.632415 42.674124, -82.633028 42.674037, -82.633755 42.674095, -82.635325 42.674712, -82.635292 42.674868, -82.635124 42.674987, -82.634934 42.675107, -82.634955 42.675301, -82.635147 42.675479, -82.635472 42.675565, -82.635915 42.675602, -82.63634 42.675719, -82.636564 42.675758, -82.636756 42.675784, -82.636979 42.675774, -82.637168 42.67575, -82.637265 42.675712, -82.637306 42.675503, -82.638014 42.675507, -82.638109 42.675667, -82.638302 42.675775, -82.639643 42.67572, -82.639681 42.675505, -82.640246 42.675471, -82.640413 42.675622, -82.640535 42.675623, -82.640595 42.675516, -82.640803 42.675506, -82.641248 42.675432, -82.641144 42.675022, -82.641479 42.675095, -82.641596 42.675439, -82.642113 42.67547, -82.642711 42.675586, -82.643163 42.67561, -82.64357 42.67558, -82.643799 42.675767, -82.643932 42.675883, -82.644195 42.675907, -82.644473 42.675899, -82.644621 42.676012, -82.644855 42.676136, -82.645069 42.675972, -82.645268 42.675874, -82.645319 42.676052, -82.645471 42.676209, -82.645638 42.676194, -82.645754 42.676042, -82.645904 42.675957, -82.646105 42.675854, -82.646105 42.675768, -82.646138 42.675734, -82.646561 42.675761, -82.646851 42.675761, -82.647062 42.675719, -82.647167 42.676719, -82.647263 42.676819, -82.647343 42.676762, -82.647336 42.676625, -82.647282 42.67637, -82.647292 42.676188, -82.64728 42.675989, -82.647285 42.675636, -82.647291 42.675514, -82.647266 42.675282, -82.647521 42.675238, -82.647817 42.675216, -82.647975 42.675225, -82.64803 42.675294, -82.647969 42.675885, -82.647884 42.675977, -82.647868 42.676047, -82.647921 42.676115, -82.648221 42.676271, -82.648359 42.676224, -82.648449 42.676343, -82.648524 42.676499), LINESTRING (-82.65818 42.680572, -82.657964 42.680598, -82.657413 42.680784, -82.657274 42.680696, -82.657224 42.680671, -82.656415 42.680355, -82.656041 42.680202, -82.655663 42.68004, -82.655839 42.679766, -82.655433 42.679667, -82.655224 42.679611, -82.654592 42.679445, -82.654419 42.679404, -82.652374 42.678871, -82.651727 42.678714, -82.651292 42.678596, -82.650367 42.678362, -82.649361 42.678117, -82.648497 42.677895, -82.647506 42.677659, -82.646492 42.677404, -82.646034 42.677279, -82.644643 42.676941, -82.64395 42.676767, -82.643424 42.676652, -82.64295 42.676564, -82.642353 42.676471, -82.641933 42.676416, -82.641509 42.676379, -82.640839 42.676342, -82.640352 42.676327, -82.63915 42.676318, -82.636744 42.676282, -82.636023 42.676186, -82.635207 42.676057, -82.632128 42.675505, -82.629298 42.674949, -82.628949 42.674869, -82.628524 42.674739, -82.628335 42.675071, -82.628303 42.675158, -82.628281 42.675247, -82.628275 42.675336, -82.628335 42.676821, -82.628443 42.679048, -82.628472 42.679858, -82.628299 42.679858, -82.627798 42.679847, -82.623083 42.679981, -82.617169 42.680147, -82.608563 42.680387), LINESTRING (-82.710803 42.690242, -82.712767 42.691845, -82.713885 42.692758, -82.714947 42.693624, -82.716103 42.694569, -82.716697 42.695053, -82.723317 42.700441, -82.723108 42.700579, -82.723035 42.700606, -82.722697 42.700703, -82.722212 42.700981, -82.721459 42.701556, -82.720797 42.701991, -82.720684 42.702058, -82.720356 42.702229, -82.720028 42.702565, -82.719752 42.702945, -82.719664 42.703042, -82.720988 42.70344, -82.722822 42.703991, -82.729277 42.706059), LINESTRING (-82.710008 42.721563, -82.710484 42.721554, -82.71084 42.721543, -82.712128 42.721471, -82.712167 42.7221, -82.712412 42.722096, -82.715509 42.721974, -82.715486 42.721604, -82.715497 42.721357, -82.715847 42.721336, -82.716298 42.721323, -82.717156 42.721291, -82.718741 42.721236, -82.719591 42.7212, -82.721027 42.721148, -82.723567 42.721062), LINESTRING (-82.7087 42.688529, -82.709056 42.688816, -82.709608 42.689267, -82.710246 42.689788, -82.710803 42.690242), LINESTRING (-82.709261 42.706841, -82.709272 42.707067, -82.709362 42.708806, -82.709451 42.710546, -82.709751 42.715916, -82.709815 42.717805, -82.709916 42.719694, -82.710008 42.721563), LINESTRING (-82.620323 42.66498, -82.620349 42.665148, -82.620047 42.665119, -82.616443 42.665223, -82.616015 42.665202, -82.615652 42.665181, -82.615532 42.665085, -82.607999 42.665245, -82.607712 42.665457), LINESTRING (-82.729277 42.706059, -82.729292 42.706354, -82.729564 42.711595, -82.729641 42.713423, -82.729867 42.718623, -82.729964 42.720843), LINESTRING (-82.607712 42.665457, -82.607944 42.665541, -82.607711 42.666149, -82.607734 42.666336, -82.608111 42.672826, -82.608563 42.680387), LINESTRING (-82.661314 42.681232, -82.661667 42.680659, -82.661799 42.680405, -82.66181 42.680361, -82.661806 42.680317, -82.661786 42.680272, -82.661753 42.680235, -82.661666 42.680173, -82.661478 42.680056, -82.661253 42.679904, -82.661038 42.679744, -82.660945 42.679686, -82.660896 42.67966, -82.660812 42.679625, -82.660756 42.67966, -82.660648 42.679961, -82.660597 42.680242, -82.660422 42.680963), LINESTRING (-82.624127 42.664958, -82.622927 42.665116, -82.622719 42.664753, -82.622592 42.664321, -82.620241 42.664387, -82.620323 42.66498), LINESTRING (-82.650359 42.67448, -82.650506 42.674472, -82.650593 42.674512, -82.650735 42.674546, -82.650862 42.674586, -82.652214 42.674799, -82.651784 42.673702, -82.652493 42.67378, -82.652842 42.674786, -82.653149 42.674788, -82.653188 42.674947, -82.653224 42.675097, -82.653721 42.675057, -82.653825 42.675056, -82.654064 42.675093, -82.654277 42.675148, -82.654428 42.675223, -82.654395 42.675454, -82.654289 42.675584, -82.654224 42.675699, -82.654179 42.675804, -82.654245 42.675913, -82.654558 42.676204, -82.654624 42.676332, -82.655051 42.677079, -82.655241 42.677539, -82.655274 42.67775, -82.655376 42.677947, -82.655564 42.678176, -82.655551 42.678295, -82.655457 42.678458, -82.655266 42.678659, -82.655157 42.678812, -82.655065 42.678925, -82.655018 42.679008, -82.655023 42.679121, -82.655128 42.679242, -82.655283 42.679325, -82.655454 42.679372, -82.655546 42.679256, -82.655377 42.679207, -82.655257 42.679136, -82.655304 42.679027, -82.655507 42.679023, -82.65565 42.678773, -82.655728 42.678703, -82.655958 42.678692, -82.656217 42.678777, -82.656411 42.67887, -82.656412 42.679033, -82.656776 42.679435, -82.657411 42.679849, -82.657619 42.680019, -82.657789 42.680284, -82.65792 42.680314, -82.658094 42.680354, -82.65818 42.680572), LINESTRING (-82.660422 42.680963, -82.661314 42.681232), LINESTRING (-82.727094 42.720942, -82.729964 42.720843), LINESTRING (-82.7087 42.688529, -82.70823 42.688655, -82.708049 42.688697, -82.707071 42.688913, -82.706476 42.689045, -82.70452 42.689478, -82.703777 42.689632, -82.705063 42.690695), LINESTRING (-82.718569 42.719613, -82.718492 42.718705, -82.718119 42.718175, -82.717913 42.718079, -82.713845 42.718228, -82.713701 42.71827, -82.713296 42.718827, -82.713297 42.719174, -82.713273 42.719651, -82.713442 42.719937, -82.713632 42.71996, -82.714196 42.719929, -82.715455 42.719857, -82.71573 42.719845, -82.717066 42.7198, -82.717111 42.7198, -82.717676 42.719742, -82.718133 42.719712, -82.718537 42.719639, -82.718569 42.719613), LINESTRING (-82.705063 42.690695, -82.705001 42.690773, -82.704963 42.690808, -82.704641 42.691018, -82.704492 42.691119, -82.70424 42.691316, -82.704166 42.691387, -82.704112 42.691468, -82.704079 42.691555, -82.704048 42.691691, -82.704011 42.691866, -82.704129 42.692074, -82.70417 42.692159, -82.704255 42.692278, -82.704322 42.692354, -82.7044 42.692422, -82.704546 42.692524, -82.705468 42.69184, -82.705993 42.691436, -82.706642 42.691949, -82.707288 42.692462, -82.707546 42.692668, -82.70847 42.693408, -82.708519 42.693538, -82.708538 42.693626, -82.708599 42.694123, -82.708732 42.696953, -82.708925 42.699792, -82.708926 42.700144, -82.709261 42.706841), LINESTRING (-82.650151 42.674732, -82.650367 42.674716, -82.650481 42.674584, -82.650468 42.674518, -82.650359 42.67448), LINESTRING (-82.650151 42.674732, -82.650045 42.674741, -82.650133 42.676008, -82.649736 42.676309, -82.649434 42.676516, -82.649296 42.676587, -82.649131 42.676674, -82.648874 42.676688, -82.648632 42.676654, -82.648524 42.676499), LINESTRING (-82.646707 42.675761, -82.646039 42.675235, -82.64609 42.67516, -82.646208 42.675123, -82.646378 42.675073, -82.646496 42.674985, -82.646581 42.67496, -82.646648 42.674998, -82.64667 42.675288, -82.646707 42.675761))");
}
@Test
public void testRegrNoTopologyException2() throws Exception {
Geometry poly = getPolygonsFromGeometryCollection("GEOMETRYCOLLECTION(LINESTRING (-114.978838 36.076338, -114.978723 36.076413, -114.978602 36.07648, -114.978428 36.076581, -114.978375 36.076608, -114.978174 36.076707, -114.97809 36.076738, -114.977839 36.076885, -114.977817 36.076897, -114.977712 36.076774, -114.977625 36.076694, -114.977533 36.07662, -114.97735 36.076465, -114.97726 36.07639, -114.977092 36.076253, -114.977013 36.07619, -114.976936 36.07613, -114.976787 36.07601, -114.976712 36.075949, -114.976632 36.075886, -114.976557 36.075942, -114.976449 36.076027, -114.976396 36.076062, -114.976353 36.076138, -114.976302 36.076197, -114.976275 36.076251, -114.976247 36.076317, -114.976224 36.076396, -114.97621 36.076486, -114.976203 36.076586, -114.976204 36.076693, -114.976216 36.07692, -114.976224 36.077159, -114.976231 36.077281, -114.976239 36.077405, -114.976248 36.077531, -114.976278 36.077919, -114.976296 36.078185, -114.976302 36.078285, -114.976305 36.078318, -114.976319 36.078577, -114.976324 36.078704, -114.976328 36.078829, -114.97633 36.078952, -114.97633 36.079073, -114.976328 36.079191, -114.976325 36.079309, -114.976323 36.079425, -114.976322 36.079541, -114.976323 36.079657, -114.976323 36.079772, -114.976322 36.079884, -114.976322 36.079992, -114.976329 36.080096, -114.976345 36.080196, -114.976371 36.080294, -114.976408 36.080389, -114.976457 36.08048, -114.976518 36.080565, -114.976592 36.080644, -114.976678 36.08072, -114.976773 36.080791, -114.976877 36.08086, -114.977203 36.08107, -114.977314 36.081141, -114.977529 36.081276, -114.977722 36.081396, -114.977879 36.081496, -114.977991 36.081571, -114.978046 36.081609, -114.978105 36.081648, -114.978164 36.08169, -114.978128 36.08175, -114.978057 36.081882, -114.977992 36.082019, -114.977932 36.082159, -114.977879 36.082294, -114.977833 36.082431, -114.977789 36.082575, -114.977754 36.08272, -114.977724 36.082861, -114.977702 36.082999, -114.977685 36.08314, -114.977675 36.083278, -114.977666 36.083415, -114.977661 36.083546, -114.97766 36.083677, -114.977663 36.083931, -114.977666 36.084054, -114.977676 36.084293, -114.977679 36.084402, -114.977681 36.084507, -114.977681 36.084632, -114.977684 36.084718, -114.97769 36.084824, -114.977687 36.084929, -114.977683 36.085141, -114.977683 36.085342, -114.977679 36.085427, -114.977674 36.085498, -114.977674 36.085564, -114.977676 36.085624, -114.977679 36.085768, -114.977687 36.085828, -114.977894 36.085853, -114.977975 36.085851, -114.978203 36.085843, -114.978347 36.085839, -114.978666 36.085831, -114.979167 36.08582, -114.979331 36.085817, -114.979498 36.085812, -114.979833 36.0858, -114.979998 36.085797, -114.98016 36.085795, -114.980319 36.085792, -114.980469 36.08579, -114.980885 36.085781, -114.981008 36.085777, -114.981124 36.085774, -114.981324 36.085771, -114.981404 36.085769, -114.981468 36.08577, -114.981558 36.085753, -114.98158 36.085732, -114.981756 36.085733, -114.981736 36.085206, -114.981751 36.085133, -114.981749 36.08508, -114.981743 36.085011, -114.981738 36.08493, -114.981728 36.084743, -114.981725 36.084531, -114.981726 36.084415, -114.981728 36.084298, -114.98173 36.084043, -114.981733 36.08378, -114.981735 36.083645, -114.981742 36.083367, -114.981747 36.083079, -114.981751 36.082782, -114.981752 36.082631, -114.981756 36.082323, -114.981759 36.082168, -114.981763 36.081855, -114.981766 36.081697, -114.981772 36.081221, -114.981773 36.080901, -114.981773 36.080088, -114.981774 36.079773, -114.981776 36.079459, -114.981785 36.078999, -114.981789 36.07885, -114.981793 36.078556, -114.981792 36.078412, -114.981793 36.078271, -114.98179 36.078129, -114.98179 36.077994, -114.981789 36.077747, -114.981789 36.077546, -114.981593 36.077543, -114.981535 36.07754, -114.981443 36.077537, -114.981369 36.077539, -114.981264 36.077545, -114.981149 36.077544, -114.981021 36.077542, -114.980888 36.077539, -114.980628 36.07753, -114.980509 36.077527, -114.980379 36.077527, -114.98038 36.07743, -114.980379 36.077375, -114.980376 36.07732, -114.980376 36.077271, -114.980383 36.077145, -114.980395 36.077082, -114.98042 36.077037, -114.98049 36.07701), LINESTRING (-114.97535 36.089831, -114.975598 36.101595, -114.975985 36.119968, -114.974146 36.120883, -114.97326 36.120316, -114.970433 36.121716, -114.968995 36.12195, -114.96826 36.122662, -114.965879 36.124974, -114.965867 36.125383, -114.965811 36.125591, -114.96426 36.128155, -114.963357 36.129094, -114.962765 36.129689, -114.962144 36.130627, -114.961806 36.131383, -114.961496 36.131749, -114.959944 36.1331, -114.959859 36.13326, -114.959465 36.133421, -114.958848 36.134474, -114.958173 36.135299, -114.957893 36.135871, -114.957561 36.138093, -114.956244 36.141459, -114.954789 36.145741, -114.954227 36.146954, -114.953441 36.148443, -114.952092 36.151731, -114.951648 36.152816, -114.951282 36.153274, -114.949031 36.155084, -114.948948 36.155381, -114.948835 36.155427, -114.948326 36.155565, -114.944248 36.158447, -114.943369 36.1595, -114.943029 36.160118, -114.942831 36.160256, -114.941697 36.161536, -114.941042 36.163528, -114.939738 36.165198, -114.93934 36.165999, -114.938601 36.167761, -114.938569 36.16902, -114.938114 36.169934, -114.937718 36.170346, -114.937406 36.170529, -114.93701 36.170529, -114.936189 36.170186, -114.934095 36.169155, -114.931554 36.169132, -114.931187 36.1692, -114.930227 36.168765, -114.929114 36.168708, -114.927968 36.168651, -114.927855 36.168697, -114.928079 36.169156, -114.927937 36.169248, -114.927116 36.169228, -114.926521 36.16939, -114.925898 36.169758, -114.925245 36.170265, -114.924365 36.171851, -114.919875 36.178356, -114.919194 36.179345, -114.91809 36.179142, -114.91707 36.179214, -114.917087 36.179276, -114.917677 36.17945, -114.918196 36.179626, -114.919968 36.180888, -114.920643 36.181269, -114.922046 36.181773, -114.923434 36.182128, -114.923723 36.182253, -114.923833 36.182749, -114.923892 36.183606, -114.923697 36.183978, -114.923556 36.184529, -114.923307 36.184745, -114.922833 36.184613, -114.921806 36.184713, -114.921001 36.185227, -114.920558 36.185369, -114.918892 36.185515, -114.918421 36.185613, -114.918108 36.184659, -114.917434 36.18272, -114.917323 36.18237), LINESTRING (-114.904899 36.122235, -114.904878 36.122379, -114.904821 36.122688, -114.904737 36.122932, -114.9046 36.123274, -114.904489 36.123463, -114.904394 36.123597, -114.90429 36.123712, -114.903988 36.124018, -114.903712 36.124318, -114.903633 36.124443, -114.903539 36.124665, -114.903516 36.124762, -114.903509 36.124877, -114.903509 36.125095, -114.903522 36.125206, -114.903588 36.125428, -114.903634 36.125536, -114.903741 36.125711, -114.903997 36.125995, -114.904498 36.126509, -114.9048 36.126811, -114.905292 36.12733, -114.906118 36.128163, -114.906401 36.128457, -114.906588 36.128659, -114.90675 36.128872, -114.906875 36.129047, -114.906984 36.129225, -114.907224 36.129719, -114.907284 36.129859, -114.907358 36.1301, -114.907443 36.130499, -114.90745 36.1306, -114.907434 36.131005, -114.907446 36.131134, -114.907532 36.131574, -114.907586 36.131764, -114.907665 36.131953, -114.907735 36.1321, -114.907977 36.132524, -114.908112 36.13277, -114.908174 36.132895, -114.90829 36.13321, -114.908336 36.13342, -114.90835 36.133558, -114.908343 36.133809, -114.908299 36.13406, -114.908261 36.134198, -114.90821 36.134323, -114.908113 36.134512, -114.907953 36.13477, -114.907872 36.134884, -114.907736 36.135026, -114.907538 36.135193, -114.907324 36.135335, -114.907212 36.135393, -114.906974 36.135494, -114.906761 36.135565, -114.905876 36.135827, -114.905178 36.136049, -114.904118 36.136363, -114.903762 36.136472, -114.903279 36.136646, -114.903041 36.136737, -114.902676 36.136888, -114.902294 36.137063, -114.902092 36.137166, -114.900289 36.138121, -114.899628 36.138455, -114.899304 36.138607, -114.898986 36.138742, -114.898398 36.138967, -114.898128 36.139057, -114.897899 36.139124, -114.897666 36.139184, -114.897137 36.139307, -114.896841 36.139368, -114.89614 36.139497, -114.894665 36.139752, -114.894335 36.139816, -114.894046 36.139887, -114.893761 36.139966, -114.893515 36.140041, -114.893038 36.140194, -114.892806 36.140274, -114.892529 36.140384, -114.892257 36.140503, -114.891963 36.140644, -114.891531 36.140859, -114.891256 36.141006, -114.890958 36.141232, -114.890812 36.141334, -114.890364 36.141632, -114.890164 36.141776, -114.889837 36.142029, -114.889707 36.142135, -114.889456 36.142353, -114.889243 36.142555, -114.888818 36.142986, -114.888753 36.143069, -114.889159 36.14327, -114.88959 36.143451, -114.890107 36.143723, -114.890322 36.143877, -114.890671 36.144218, -114.890736 36.144299, -114.890844 36.144482, -114.89092 36.144656, -114.890992 36.144898, -114.891012 36.145029, -114.891026 36.145297, -114.891 36.14554, -114.890941 36.145789, -114.890833 36.146061, -114.890669 36.146313, -114.890445 36.14657, -114.890135 36.146862, -114.889715 36.147199, -114.888481 36.14823, -114.88808 36.148582, -114.887708 36.148973, -114.88759 36.149118, -114.88744 36.149342, -114.887328 36.149568, -114.887248 36.149813, -114.887198 36.150103, -114.887179 36.150539, -114.887208 36.150838, -114.887248 36.151013, -114.887352 36.151282, -114.887449 36.151485, -114.887608 36.151739, -114.887711 36.151873, -114.887793 36.151959, -114.891272 36.152534, -114.894002 36.152342, -114.895204 36.152676, -114.895746 36.152861, -114.896393 36.152872, -114.898644 36.153734, -114.899247 36.154059, -114.899276 36.154463, -114.899592 36.15517, -114.90013 36.156142, -114.900664 36.156904, -114.900941 36.15722, -114.902742 36.158079, -114.904782 36.158129, -114.904821 36.157928, -114.905047 36.157935, -114.905114 36.15746, -114.905602 36.157407, -114.905711 36.157451, -114.905891 36.157331, -114.906142 36.157498, -114.906311 36.157493, -114.907489 36.157696, -114.907987 36.157785, -114.908121 36.157673, -114.908303 36.157612, -114.908451 36.157826, -114.908434 36.158007, -114.908512 36.15847, -114.908738 36.158964, -114.908852 36.160154, -114.909216 36.161367, -114.909357 36.161504, -114.909385 36.161687, -114.909835 36.162489, -114.910764 36.163496, -114.91296 36.165373, -114.913044 36.165738, -114.913042 36.166449, -114.912814 36.167365, -114.912813 36.167869, -114.912953 36.168075, -114.913492 36.168297, -114.913661 36.168562, -114.913374 36.169311, -114.912975 36.16972, -114.912595 36.170065, -114.912568 36.170591, -114.913 36.172421, -114.91283 36.172409, -114.912783 36.172443, -114.912848 36.172658, -114.912825 36.172712, -114.912704 36.17274, -114.913036 36.173806, -114.9132 36.174414, -114.913575 36.175627, -114.913764 36.176192, -114.913931 36.176523, -114.914367 36.177251, -114.915164 36.178446, -114.916325 36.180222, -114.916673 36.180816, -114.91688 36.181206, -114.917104 36.18173, -114.917221 36.182051, -114.917323 36.18237), LINESTRING (-114.904899 36.122235, -114.905259 36.122155, -114.905503 36.122111, -114.905557 36.122078, -114.905631 36.122067, -114.905699 36.122029, -114.906288 36.121782, -114.906417 36.121782, -114.907114 36.121601, -114.907514 36.121463, -114.907785 36.12131, -114.907819 36.121271, -114.907853 36.121172, -114.907846 36.121117, -114.907988 36.121013, -114.908171 36.120793, -114.908401 36.12076, -114.908523 36.120761, -114.907928 36.120403, -114.908151 36.120441, -114.908429 36.120145, -114.90851 36.120107, -114.908598 36.120101, -114.908876 36.120228, -114.909011 36.120206, -114.909316 36.1202, -114.909424 36.120112, -114.909533 36.120074, -114.909648 36.120118, -114.909918 36.120261, -114.910115 36.120332, -114.910189 36.120316, -114.910548 36.120272, -114.910697 36.120316, -114.910887 36.120448, -114.910948 36.120437, -114.911483 36.120217, -114.911828 36.119987, -114.912024 36.119641, -114.912174 36.119509, -114.912411 36.11941, -114.912857 36.119289, -114.913135 36.11907, -114.91323 36.119004, -114.913393 36.118954, -114.91367 36.118938, -114.913799 36.118922, -114.913819 36.118933, -114.914225 36.118889, -114.914422 36.118823, -114.914517 36.118718, -114.914625 36.118427, -114.914673 36.118383, -114.914767 36.118339, -114.915025 36.118153, -114.915126 36.118065, -114.915451 36.117587, -114.915607 36.117472, -114.915966 36.117329, -114.916149 36.117164, -114.9164 36.11684, -114.916494 36.116774, -114.916731 36.11678, -114.916846 36.11673, -114.917138 36.116406, -114.917619 36.115923, -114.917768 36.115698, -114.917781 36.115665, -114.917856 36.115269, -114.91833 36.114621, -114.918574 36.11439, -114.918635 36.114209, -114.918784 36.113984, -114.918858 36.11389, -114.919373 36.113495, -114.919434 36.113467, -114.919779 36.113138, -114.920206 36.11249, -114.920477 36.112188, -114.920646 36.111803, -114.920748 36.111666, -114.921005 36.111463, -114.921256 36.111182, -114.921364 36.110974, -114.92154 36.110886, -114.921621 36.110814, -114.921743 36.110578, -114.921771 36.11049, -114.921974 36.110221, -114.922001 36.110089, -114.921926 36.10987, -114.921845 36.109677, -114.921933 36.109633, -114.922055 36.109628, -114.92213 36.109578, -114.92217 36.109513, -114.922157 36.109392, -114.922184 36.109298, -114.922231 36.109249, -114.92236 36.109238, -114.92259 36.109315, -114.922719 36.109276, -114.92301 36.109068, -114.923315 36.108947, -114.923403 36.108842, -114.923531 36.108584, -114.923606 36.108518, -114.923856 36.108442, -114.923917 36.108431, -114.924026 36.108442, -114.924195 36.108392, -114.924411 36.108288, -114.924608 36.108205, -114.924824 36.108057, -114.92494 36.107964, -114.925177 36.107733, -114.925569 36.107431, -114.925739 36.107156, -114.926057 36.106893, -114.926138 36.106794, -114.926226 36.106558, -114.926328 36.106398, -114.926341 36.106354, -114.926463 36.106195, -114.926545 36.106019, -114.926633 36.105915, -114.928198 36.106961, -114.928624 36.10663, -114.929034 36.106484, -114.929558 36.106266, -114.929575 36.10627, -114.929609 36.106135, -114.929665 36.106037, -114.929803 36.10588, -114.929923 36.105794, -114.93005 36.105732, -114.930213 36.105686, -114.930311 36.105672, -114.930691 36.105653, -114.9308 36.105643, -114.930929 36.105617, -114.933186 36.102976, -114.9332 36.103009, -114.933369 36.103136, -114.933525 36.103399, -114.933735 36.103652, -114.934093 36.103883, -114.934147 36.103872, -114.934337 36.103982, -114.934391 36.103976, -114.934491 36.10403), LINESTRING (-114.978838 36.076338, -114.978915 36.076429, -114.978984 36.076515, -114.979048 36.076601, -114.979108 36.076686, -114.979166 36.076769, -114.979219 36.07685, -114.979266 36.076934, -114.979309 36.077014, -114.97935 36.077087, -114.979363 36.077113, -114.979411 36.077055, -114.979456 36.076999, -114.979557 36.076966, -114.979619 36.076948, -114.97969 36.076922, -114.979765 36.076895, -114.979846 36.076867, -114.979924 36.076839, -114.97999 36.076814, -114.980067 36.076784, -114.980182 36.076713, -114.980229 36.076771, -114.980277 36.076825, -114.980367 36.076917, -114.980441 36.076985, -114.98049 36.07701), LINESTRING (-114.95044 36.095617, -114.956672 36.094768, -114.962145 36.093417, -114.965016 36.092981, -114.967724 36.091925, -114.970443 36.090947, -114.972632 36.090159, -114.972724 36.090194, -114.97292 36.090199, -114.973062 36.090166, -114.973299 36.090062, -114.973509 36.090073, -114.973658 36.090045, -114.973854 36.089941, -114.973922 36.089913, -114.974111 36.089897, -114.974314 36.089847, -114.974443 36.089842, -114.974768 36.089902, -114.974923 36.089897, -114.975248 36.089842, -114.97535 36.089831), LINESTRING (-114.934491 36.10403, -114.934622 36.104119, -114.934351 36.102812, -114.934439 36.102691, -114.93455 36.1026, -114.934709 36.102537, -114.934906 36.102504, -114.934946 36.102488, -114.935068 36.102411, -114.935447 36.102125, -114.935585 36.102106, -114.936031 36.101871, -114.936289 36.101737, -114.938014 36.101698, -114.938483 36.101716, -114.938473 36.102004, -114.938568 36.101982, -114.939001 36.10201, -114.939029 36.102021, -114.939306 36.10201, -114.939597 36.101938, -114.939699 36.101933, -114.939929 36.101955, -114.940098 36.101944, -114.94024 36.101911, -114.940315 36.101916, -114.940355 36.101905, -114.94043 36.101905, -114.940897 36.101806, -114.941364 36.101669, -114.941527 36.101636, -114.941709 36.101526, -114.941926 36.101235, -114.941987 36.101191, -114.942176 36.101103, -114.942441 36.100916, -114.942759 36.100625, -114.943036 36.100493, -114.943219 36.100323, -114.94353 36.10007, -114.943612 36.100021, -114.943706 36.099911, -114.943842 36.099686, -114.944004 36.099285, -114.944058 36.099252, -114.944282 36.099175, -114.944295 36.099142, -114.944295 36.099021, -114.944343 36.098944, -114.944465 36.098862, -114.944871 36.098653, -114.945148 36.098516, -114.945426 36.098307, -114.945764 36.098071, -114.945974 36.097829, -114.946096 36.097604, -114.94615 36.097527, -114.946597 36.097268, -114.946854 36.097219, -114.946895 36.097225, -114.947071 36.097159, -114.947233 36.097038, -114.947294 36.097016, -114.947734 36.097032, -114.947836 36.097016, -114.94833 36.096686, -114.949995 36.095678, -114.95044 36.095617), LINESTRING (-114.938473 36.102004, -114.938456 36.102009, -114.938453 36.102133, -114.938473 36.102004), LINESTRING (-114.903509 36.125038, -114.899374 36.125003, -114.899318 36.125344, -114.90016 36.125357, -114.900783 36.125368, -114.902672 36.125139, -114.903509 36.125038))");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment