take invalid polygon polygon((0 100, 100 100, 0 0, 100 0, 0 100)) - egg timer shape undeclared point of intersection

many instructions jts can create valid version of using buffer method:
geometry input = new wktreader().read("polygon((0 100, 100 100, 0 0, 100 0, 0 100))"); geometry output = geom.buffer(0); return output; however, produces output polygon ((0 100, 100 100, 50 50, 0 100)) part of polygon lost:

is there way jts validate polygons such produce output multipolygon(((0 100, 100 100, 50 50, 0 100)), ((0 0, 100 0, 50 50, 0 0))) input given?

this seems should built in api (maybe behaviour bug) - have missed something?
thank you.
jts seems offer behaviour require, though had little legwork in own code. validate function wrote breaks down polygon/multipolygon collection of non self intersecting linestrings, , uses polygonizer class build polygons result. have tested on following (limited) set of inputs, , seems behave way require:
polygon((0 100, 100 100, 0 0, 100 0, 0 100)) polygon((0 0, 0 100, 100 100, 100 0, 0 0)) multipolygon(((0 0, 0 100, 100 100, 100 0, 0 0)),((50 50, 50 150, 150 150, 150 50, 50 50))) polygon((0 0, 50 50, 100 0, 150 0, 200 50, 250 0, 0 0)) code:
/** * / create valid version of geometry given. if geometry polygon or multi polygon, self intersections / * inconsistencies fixed. otherwise geometry returned. * * @param geom * @return geometry */ public static geometry validate(geometry geom){ if(geom instanceof polygon){ if(geom.isvalid()){ geom.normalize(); // validate not pick rings in wrong order - fix return geom; // if polygon valid return } polygonizer polygonizer = new polygonizer(); addpolygon((polygon)geom, polygonizer); return topolygongeometry(polygonizer.getpolygons(), geom.getfactory()); }else if(geom instanceof multipolygon){ if(geom.isvalid()){ geom.normalize(); // validate not pick rings in wrong order - fix return geom; // if multipolygon valid return } polygonizer polygonizer = new polygonizer(); for(int n = geom.getnumgeometries(); n-- > 0;){ addpolygon((polygon)geom.getgeometryn(n), polygonizer); } return topolygongeometry(polygonizer.getpolygons(), geom.getfactory()); }else{ return geom; // in case, care polygon / multipolygon geometries } } /** * add line strings polygon given polygonizer given * * @param polygon polygon extract line strings * @param polygonizer polygonizer */ static void addpolygon(polygon polygon, polygonizer polygonizer){ addlinestring(polygon.getexteriorring(), polygonizer); for(int n = polygon.getnuminteriorring(); n-- > 0;){ addlinestring(polygon.getinteriorringn(n), polygonizer); } } /** * add linestring given polygonizer * * @param linestring line string * @param polygonizer polygonizer */ static void addlinestring(linestring linestring, polygonizer polygonizer){ if(linestring instanceof linearring){ // linearrings treated differently line strings : need linestring not linearring linestring = linestring.getfactory().createlinestring(linestring.getcoordinatesequence()); } // unioning linestring point makes self intersections explicit. point point = linestring.getfactory().createpoint(linestring.getcoordinaten(0)); geometry toadd = linestring.union(point); //add result polygonizer polygonizer.add(toadd); } /** * geometry collection of polygons. * * @param polygons collection * @param factory factory generate multipolygon if required * @return null if there no polygons, polygon if there one, or multipolygon containing polygons otherwise */ static geometry topolygongeometry(collection<polygon> polygons, geometryfactory factory){ switch(polygons.size()){ case 0: return null; // no valid polygons! case 1: return polygons.iterator().next(); // single polygon - no need wrap default: //polygons may still overlap! need sym difference them iterator<polygon> iter = polygons.iterator(); geometry ret = iter.next(); while(iter.hasnext()){ ret = ret.symdifference(iter.next()); } return ret; } }
Comments
Post a Comment