Package bs.bs2d.geom

Source Code of bs.bs2d.geom.JTSUtils

package bs.bs2d.geom;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.geom.PrecisionModel;
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

/**
*
* @author Djen
*/
public class JTSUtils {
   
    public static PrecisionModel FLOAT_PRECISION_MODEL = new PrecisionModel(PrecisionModel.FLOATING_SINGLE);
    private static GeometryFactory GEOMETRY_FACTORY;
   
    /**
     * Returns a shared instance of GeometryFactoy with a float precision model.
     * @return a float precision GeometryFactory
     */
    public static GeometryFactory getFactory(){
        if(GEOMETRY_FACTORY == null)
            GEOMETRY_FACTORY = new GeometryFactory(FLOAT_PRECISION_MODEL);
        return GEOMETRY_FACTORY;
    }
   
    /**
     * Creates a MultiPolygon from the given shape. All subpaths of shape are
     * closed to form Polygon outlines. An even-odd winding rule is assumed
     * regardless of the shape's winding rule property.
     * @param shape the shape to convert to a MultiPolygon
     * @return a MultiPolygon representation of shape
     */
    public static MultiPolygon createMultiPolygon(Shape shape){
        PathIterator it = shape.getPathIterator(null);
        ArrayList<Polygon> rings = new ArrayList<>();
        LinkedList<Coordinate> loop = new LinkedList<>();
        float[] coords = new float[6];
       
        while(!it.isDone()){
            int seg = it.currentSegment(coords);
            if(seg == PathIterator.SEG_MOVETO){
                // add polyline, start new loop
                if(!loop.isEmpty()){
                    // close loop if necessary
                    if(!loop.getFirst().equals(loop.getLast()))
                        loop.add(new Coordinate(loop.get(0)));
                    Coordinate[] c = loop.toArray(new Coordinate[loop.size()]);
                    rings.add(getFactory().createPolygon(c));
                    loop.clear();
                }
               
                loop.add(new Coordinate(coords[0], coords[1]));
            } else if(seg == PathIterator.SEG_LINETO){
                loop.add(new Coordinate(coords[0], coords[1]));
            } else if(seg == PathIterator.SEG_QUADTO){
                loop.add(new Coordinate(coords[2], coords[3]));
            } else if(seg == PathIterator.SEG_CUBICTO){
                loop.add(new Coordinate(coords[4], coords[5]));
            }
            it.next();
        }
       
        // add last loop
        if(!loop.isEmpty()){
            if(!loop.getFirst().equals(loop.getLast()))
                loop.add(new Coordinate(loop.get(0)));
            Coordinate[] c = loop.toArray(new Coordinate[loop.size()]);
            rings.add(getFactory().createPolygon(c));
        }
       
       
       
//        Geometry geom = rings.get(0);
        Geometry geom = getFactory().createMultiPolygon(new Polygon[0]);
        for (int i = 0; i < rings.size(); i++) {
            Polygon ring = rings.get(i);
            geom = geom.symDifference(ring);
        }
       
        if(!geom.isSimple()){
            System.out.println("!unsimple geometry!");
        }
       
        if(geom instanceof MultiPolygon){
            return (MultiPolygon) geom;
        } else { // Polygon
            Polygon[] p = new Polygon[]{(Polygon)geom};
            return getFactory().createMultiPolygon(p);
        }
       
    }
   
    /**
     * Convers the given Geometry to a Java2D shape.
     * @param geom the geometry to convert
     * @return a Shape representation of geom
     */
    public static Shape toShape(Geometry geom){
        GeneralPath p = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
       
        int count = geom.getNumGeometries();
        for (int i = 0; i < count; i++) {
            Geometry g = geom.getGeometryN(i);
           
            if(g instanceof GeometryCollection){
                p.append(toShape(geom), false);
            } else if (g instanceof Polygon){
                p.append(toShape((Polygon)g), false);
            } else if (g instanceof LineString){
                p.append(toShape((LineString)g), false);
            } else {
                throw new IllegalArgumentException("Unknown Geometry type!");
            }
        }
       
        return p;
    }
   
    private static Shape toShape(Polygon poly){
        GeneralPath p = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
       
        if(poly.isEmpty())
            return p;
       
        p.append(toShape(poly.getExteriorRing()), false);
       
        for (int i = 0; i < poly.getNumInteriorRing(); i++) {
            p.append(toShape(poly.getInteriorRingN(i)), false);
        }
       
        return p;
    }
   
    private static Shape toShape(LineString lines){
        GeneralPath p = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
       
        if(lines.isEmpty())
            return p;
       
        Coordinate[] coords = lines.getCoordinates();
        Coordinate c = coords[0];
        p.moveTo(c.x, c.y);

        for (int j = 1; j < coords.length; j++) {
            c = coords[j];
            p.lineTo(c.x, c.y);
        }

        if(coords[0].equals(c))
            p.closePath();
       
        return p;
    }

    /**
     * Generates an array of LineStrings consisting of all single line strings
     * and polygon bounds in the given geometry.
     * @param geom the Geometry to split
     * @return an array of singular line strings
     */
    public static LineString[] getLineStrings(Geometry geom) {
        ArrayList<LineString> lines = new ArrayList<>();
        int num = geom.getNumGeometries();
       
        for (int i = 0; i < num; i++) {
            Geometry g = geom.getGeometryN(i);
            if(g instanceof LineString){
                lines.add((LineString) g);
            } else if (g instanceof Polygon){
                lines.addAll(getLineStrings((Polygon) g));
            } else if (g instanceof GeometryCollection) {
                lines.addAll(Arrays.asList(getLineStrings(geom)));
            } else if (g instanceof Point) {
                // ignore
            } else {
                throw new UnsupportedOperationException("Unsupported geometry type:" + g.getGeometryType());
            }
        }
       
        return lines.toArray(new LineString[lines.size()]);
    }
   
    private static List<LineString> getLineStrings(Polygon poly){
        ArrayList<LineString> lines = new ArrayList<>();
        lines.add(poly.getExteriorRing());
        for (int i = 0; i < poly.getNumInteriorRing(); i++) {
            lines.add(poly.getInteriorRingN(i));
        }
       
        return lines;
    }

    /**
     * Generates an array of singular Polygons from a Multipolygon
     * @param multi the Multipolygon to split
     * @return an array of singular Polygons
     */
    public static Polygon[] getPolygons(MultiPolygon multi) {
        Polygon[] polys = new Polygon[multi.getNumGeometries()];
        for (int i = 0; i < polys.length; i++) {
            polys[i] = (Polygon) multi.getGeometryN(i);
        }
        return polys;
    }

    /**
     * Returns a MultiPolygon containig the given Geometry, assuming the
     * argument is either a Polygon or Multipolygon. This method can be used to
     * quickly cast the result of a boolean operation on a MultiPolygon back to
     * a MultiPolygon instance.
     * @param geom Geometry containing either a Polygon or MultiPolygon
     * @return a Multipolygon containing all geometry from geom
     */
    public static MultiPolygon toMultiPolygon(Geometry geom) {
        if (geom instanceof MultiPolygon) {
            return (MultiPolygon) geom;
        } else {
            Polygon[] p = new Polygon[]{(Polygon) geom};
            return getFactory().createMultiPolygon(p);
        }
    }
   
    public static Point createPoint2D(double x, double y){
        return GEOMETRY_FACTORY.createPoint(new Coordinate(x, y));
    }
   
}
TOP

Related Classes of bs.bs2d.geom.JTSUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.