Package org.geotools.geometry.jts

Source Code of org.geotools.geometry.jts.GeometryUtils

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2004-2008, Open Source Geospatial Foundation (OSGeo)
*
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation;
*    version 2.1 of the License.
*
*    This library is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*    Lesser General Public License for more details.
*/
package org.geotools.geometry.jts;

/*import com.polexis.go.FactoryManager;
import com.polexis.go.typical.coord.LatLonAlt;
import com.polexis.referencing.crs.CRSUtils;
import com.polexis.referencing.cs.CSUtils;
import com.polexis.units.UnitUtils;*/

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import javax.measure.converter.UnitConverter;
import javax.measure.unit.NonSI;
import javax.measure.unit.Unit;

//apache dependencies
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

//openGIS dependencies
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.operation.CoordinateOperation;
import org.opengis.referencing.operation.CoordinateOperationFactory;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.Envelope;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.geometry.complex.CompositeCurve;
import org.opengis.geometry.coordinate.GeometryFactory;
import org.opengis.geometry.coordinate.LineString;
import org.opengis.geometry.coordinate.PointArray;
import org.opengis.geometry.coordinate.Polygon;
import org.opengis.geometry.coordinate.PolyhedralSurface;
import org.opengis.geometry.primitive.Curve;
import org.opengis.geometry.primitive.CurveSegment;
import org.opengis.geometry.primitive.PrimitiveFactory;
import org.opengis.geometry.primitive.Ring;
import org.opengis.geometry.primitive.SurfaceBoundary;

//geotools dpendencies
import org.geotools.factory.BasicFactories;
import org.geotools.referencing.CRS;

/**
* @author crossley
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*
*
*
*
* @source $URL$
*/
public final class GeometryUtils {
   

    //*************************************************************************
    //  Static Fields
    //*************************************************************************
   
    private static Envelope WHOLE_WORLD;
   
    public static Envelope getWholeWorld() {
        if (WHOLE_WORLD == null) {
            CoordinateReferenceSystem crs = null;
            try {
                crs = org.geotools.referencing.CRS.decode("EPSG:4326");
            } catch (Exception nsace){
                getLog().warn("could not get crs for EPSG:4326");
            }
           
            final BasicFactories commonFactory = BasicFactories.getDefault();
            final GeometryFactory geometryFactory = commonFactory.getGeometryFactory(crs);
           
            final DirectPosition lowerCorner = geometryFactory.createDirectPosition(new double[] { -90, -180 });
            final DirectPosition upperCorner = geometryFactory.createDirectPosition(new double[] { 90, 180 });
           
            WHOLE_WORLD = geometryFactory.createEnvelope(lowerCorner, upperCorner);
        }
        return WHOLE_WORLD;
    }


    public static CoordinateReferenceSystem getCRS(final Envelope envelope) {
        return envelope.getLowerCorner().getCoordinateReferenceSystem();
    }
   
  // PENDING(jdc): need to respect a given Unit for the return array.
    /**
     * Converts an {@code Envelope} to a "minx, miny, maxx, maxy" array.
     * @param envelope
     * @param unit
     * @return
     */
    public static double[] getBBox(final Envelope envelope, final Unit unit) {
        final double[] returnable = new double[4];
       
        final DirectPosition lowerCorner = envelope.getLowerCorner();
        final DirectPosition upperCorner = envelope.getUpperCorner();
       
        final CoordinateSystem cs = getCRS(envelope).getCoordinateSystem();
        final int xIndex = getDirectedAxisIndex(cs, AxisDirection.EAST);
        final Unit xUnit = getDirectedAxisUnit(cs, AxisDirection.EAST);
        final int yIndex = getDirectedAxisIndex(cs, AxisDirection.NORTH);
        final Unit yUnit = getDirectedAxisUnit(cs, AxisDirection.NORTH);
       
        //edited to use javax.measure.unit.Convertor
        UnitConverter xConverter = xUnit.getConverterTo(unit);
        UnitConverter yConverter = yUnit.getConverterTo(unit);
       
        returnable[0] = xConverter.convert(lowerCorner.getOrdinate(xIndex));
        returnable[1] = yConverter.convert(lowerCorner.getOrdinate(yIndex));
        returnable[2] = xConverter.convert(upperCorner.getOrdinate(xIndex));
        returnable[3] = yConverter.convert(upperCorner.getOrdinate(yIndex));
       
        return returnable;
    }
   
    public static Envelope createCRSEnvelope(
            final CoordinateReferenceSystem crs,
            final double minx,
            final double miny,
            final double maxx,
            final double maxy) {
        final BasicFactories commonFactory = BasicFactories.getDefault();
        final GeometryFactory geometryFactory = commonFactory.getGeometryFactory(crs);
       
        final DirectPosition lowerCorner = geometryFactory.createDirectPosition();
        lowerCorner.setOrdinate(0, minx);
        lowerCorner.setOrdinate(1, miny);
       
        final DirectPosition upperCorner = geometryFactory.createDirectPosition();
        upperCorner.setOrdinate(0, maxx);
        upperCorner.setOrdinate(1, maxy);
       
        return geometryFactory.createEnvelope(lowerCorner, upperCorner);
    }
   
    /**
     * DOCUMENT ME.
     * @param crs
     * @param minx
     * @param miny
     * @param maxx
     * @param maxy
     * @param unit
     * @return
     */
    public static Envelope createEnvelope(
            final CoordinateReferenceSystem crs,
            final double minx,
            final double miny,
            final double maxx,
            final double maxy,
            final Unit unit) {
        final BasicFactories commonFactory = BasicFactories.getDefault();
        final GeometryFactory geometryFactory = commonFactory.getGeometryFactory(crs);
       
        final CoordinateSystem cs = crs.getCoordinateSystem();
       
        final int xIndex = getDirectedAxisIndex(cs, AxisDirection.EAST);
        final Unit xUnit = getDirectedAxisUnit(cs, AxisDirection.EAST);
        final int yIndex = getDirectedAxisIndex(cs, AxisDirection.NORTH);
        final Unit yUnit = getDirectedAxisUnit(cs, AxisDirection.NORTH);
       
        // HACK(jdc): need to determine the order of the axes...
        /*int[] indices = CSUtils.getDirectedAxisIndices(
                crs.getCoordinateSystem(),
                new AxisDirection[] { AxisDirection.EAST, AxisDirection.NORTH });*/
       
        //edited to use javax.measure.unit.Convertor
        UnitConverter xConverter = xUnit.getConverterTo(unit);
        UnitConverter yConverter = yUnit.getConverterTo(unit);
       
        double[] lowerOrdinates = new double[crs.getCoordinateSystem().getDimension()];
        lowerOrdinates[xIndex] = xConverter.convert(minx);
        lowerOrdinates[yIndex] = yConverter.convert(miny);
       
        /*for (int i = 0; i < lowerOrdinates.length; i++) {
            // the east or x ordinate
            if (i == indices[0]) {
                lowerOrdinates[i] = minx;
            // the north or y ordinate   
            } else if (i == indices[1]) {
                lowerOrdinates[i] = miny;
            } else {
                lowerOrdinates[i] = 0;
            }
        }*/
        double[] upperOrdinates = new double[crs.getCoordinateSystem().getDimension()];
        upperOrdinates[xIndex] = xConverter.convert(maxx);
        upperOrdinates[yIndex] = yConverter.convert(maxy);
       
        /*for (int i = 0; i < upperOrdinates.length; i++) {
            // the east or x ordinate
            if (i == indices[0]) {
                upperOrdinates[i] = maxx;
            // the north or y ordinate   
            } else if (i == indices[1]) {
                upperOrdinates[i] = maxy;
            } else {
                upperOrdinates[i] = 0;
            }
        }*/
        final DirectPosition lowerCorner = geometryFactory.createDirectPosition(lowerOrdinates);
        final DirectPosition upperCorner = geometryFactory.createDirectPosition(upperOrdinates);
       
        return geometryFactory.createEnvelope(lowerCorner, upperCorner);
    }
   
   
   
    /**
     * DOCUMENT ME.
     * @param envelope
     * @param crs
     * @param minx
     * @param miny
     * @param maxx
     * @param maxy
     * @return
     */
    public static boolean within(
            final Envelope envelope,
            final CoordinateReferenceSystem crs,
            final double minx,
            final double miny,
            final double maxx,
            final double maxy) {
       
       
        final CoordinateSystem cs = crs.getCoordinateSystem();
        final int xIndex = getDirectedAxisIndex(cs, AxisDirection.EAST);
        final int yIndex = getDirectedAxisIndex(cs, AxisDirection.NORTH);
        return ( (minx <= envelope.getMinimum(xIndex)) && (maxx >= envelope.getMaximum(xIndex)) &&
                 (miny <= envelope.getMinimum(yIndex)) && (maxy >= envelope.getMaximum(yIndex)) );
       
    }
   
    /*public static boolean overlaps(
            final Envelope envelope,
            final CoordinateReferenceSystem crs,
            final double minx,
            final double miny,
            final double maxx,
            final double maxy) {
       
       
        final CoordinateSystem cs = crs.getCoordinateSystem();
        final int xIndex = CSUtils.getDirectedAxisIndex(cs, AxisDirection.EAST);
        final int yIndex = CSUtils.getDirectedAxisIndex(cs, AxisDirection.NORTH);
        return ( (minx <= envelope.getMinimum(xIndex)) || (maxx >= envelope.getMaximum(xIndex)) ||
                 (miny <= envelope.getMinimum(yIndex)) || (maxy >= envelope.getMaximum(yIndex)) );
       
    }*/
   
    /**
     * DOCUMENT ME.
     * @param envelope1
     * @param envelope2
     * @return
     */
    public static boolean equals(final Envelope envelope1, final Envelope envelope2) {
        //getLog().debug("PENDING(jdc): implement the method instead of returning false...");
        if (envelope1 == null || envelope2 == null) {
            return false;
        }
        final double[] bbox1 = getBBox(envelope1, NonSI.DEGREE_ANGLE);
        final double[] bbox2 = getBBox(envelope2, NonSI.DEGREE_ANGLE);
        return
            bbox1[0] == bbox2[0] &&
            bbox1[1] == bbox2[1] &&
            bbox1[2] == bbox2[2] &&
            bbox1[3] == bbox2[3];
    }

    /**
     * Determines whether or not the two specified Envelopes intersect.
     * Currently this method requires that the defining corners of the two Envelopes
     * must all have the same CRS, otherwise an Exception is thrown.
     * @param envelope1
     * @param envelope2
     * @return True if the Envelopes overlap
     */
    public static boolean intersects(final Envelope envelope1, final Envelope envelope2) {
        DirectPosition top1 = envelope1.getUpperCorner();
        DirectPosition bot1 = envelope1.getLowerCorner();
        DirectPosition top2 = envelope2.getUpperCorner();
        DirectPosition bot2 = envelope2.getLowerCorner();
        CoordinateReferenceSystem crs = top1.getCoordinateReferenceSystem();
        if (!crs.equals(bot1.getCoordinateReferenceSystem())
            || !crs.equals(top2.getCoordinateReferenceSystem())
            || !crs.equals(bot2.getCoordinateReferenceSystem())) {
          throw new IllegalArgumentException(
            "Current implementation of GeoemtryUtils.intersect requires that the corners of both Envelopes have the same CRS");
        }
        double minx1 = bot1.getOrdinate(0);
        double maxx1 = top1.getOrdinate(0);
        double miny1 = bot1.getOrdinate(1);
        double maxy1 = top1.getOrdinate(1);
        double minx2 = bot2.getOrdinate(0);
        double maxx2 = top2.getOrdinate(0);
        double miny2 = bot2.getOrdinate(1);
        double maxy2 = top2.getOrdinate(1);
        boolean xoverlap = minx2 < maxx1 && maxx2 > minx1;
        return xoverlap && (miny2 < maxy1 && maxy2 > miny1);
    }

    /**
     * Converts a double array to an array of {@code DirectPosition}s.
     * @param points the source data
     * @param sourceDirections the source data's axes' directions
     * @param sourceUnits the source data's axes' units
     * @param crs the target {@code CoordinateReferenceSystem}.  the {@code crs}'s
     *        dimension must match the 'dimension' in the source double array.
     * @return an array of DirectPositions
     */
    public static DirectPosition[] getDirectPositions(
            final double[] points,
            final AxisDirection[] sourceDirections,
            final Unit[] sourceUnits,
            final CoordinateReferenceSystem crs) {
        int dimension = crs.getCoordinateSystem().getDimension();
        int length = points.length / dimension;
        DirectPosition[] returnable = new DirectPosition[length];
        for (int i = 0; i < length; i++) {
           
            getLog().debug("need to make a DirectPosition");
            // umm, how am i gonna make a DirectPosition here?
            //FactoryManager.getCommonFactory().getGeometryFactory(crs).createDirectPosition
        }
        return returnable;
    }

    /**
     * Converts an array of {@code DirectPosition}s to a double array.
     * @param positions the source data
     * @param targetDirections the target data's axes' directions
     * @param targetUnits the target data's axes' units
     * @return an array of doubles
     */
    public static double[] getPoints(
            final DirectPosition[] positions,
            final AxisDirection[] targetDirections,
            final Unit[] targetUnits) {
       
        // make our returnable array of doubles
        int length = positions.length * targetDirections.length;
        double[] returnable = new double[length];
       
        // just get the first CRS from the first position
        // these should be homogenous DirectPositions
        CoordinateReferenceSystem crs = positions[0].getCoordinateReferenceSystem();
        CoordinateSystem cs = crs.getCoordinateSystem();
        int dimension = cs.getDimension();

        // find the indices for the axes we want
        int[] axisIndices = new int[targetDirections.length];
        // also need the unit converters
        UnitConverter[] converters = new UnitConverter[targetUnits.length];

        // loop through the directions that were passed in
        for (int i = 0; i < targetDirections.length; i++) {
           
            // loop through the cs' axes, checking their direction.
            // store the index once we've found it
            boolean notfound = true;
            for (int j = 0; notfound && j < dimension; j++) {
               
                // if we match, store the axis' index and the converter
                if (cs.getAxis(j).getDirection().equals(targetDirections[i])) {
                    axisIndices[i] = j;
                    converters[i] = cs.getAxis(j).getUnit().getConverterTo(targetUnits[i]);
                    notfound = false;
                }
            }
        }
       
        // now loop through the given directpositions
        for (int i = 0; i < positions.length; i++) {

            // loop through the position by dimension and store the converted ordinate
            for (int j = 0; j < axisIndices.length; j++) {
                returnable[(i * dimension) + j] = converters[j].convert(positions[i].getOrdinate(axisIndices[j]));
            }
        }
       
        // return our fancy, new array of doubles
        return returnable;
    }
   
    /**
     * Verifies the CRS of the specified {@code DirectPosition} is
     * WGS84, and returns it unmodified if it is.
     * If not, transforms the input into a new DirectPosition
     * with a WGS84 CRS.  Returns it as a LatLonAlt if input was LatLonAlt.
     * @param dp The DirectPosition to examine and transform if necessary
     * @return The original DirectPosition if it was already WGS84,
     * or the transformed DirectPosition.
     */
    public static DirectPosition ensureWGS84(DirectPosition dp) {
      CoordinateReferenceSystem crs = dp.getCoordinateReferenceSystem();
      int dim = crs.getCoordinateSystem().getDimension();
      boolean isProjectedCRS = crs instanceof ProjectedCRS;
      CoordinateReferenceSystem bcrs = crs instanceof ProjectedCRS
      ? ((ProjectedCRS) crs).getBaseCRS() : crs;
     
  GeographicCRS wgs84crs = null;
        try {
                wgs84crs = (GeographicCRS) CRS.decode("EPSG:4327");
        } catch (Exception nsace){
                getLog().warn("could not get crs for EPSG:4327");
        }
     
        //have doubts about following line, was the commented out 2nd clause to condition doing anything - colin      
        if (bcrs.equals(wgs84crs)) {    // || bcrs.equals(CRSUtils.WGS84_PROJ)) {
        return dp;
      }
        //again, what does the follllowing achieve? - colin
      if (bcrs.toWKT().indexOf("WGS84") > -1) {
        return dp;
      }
      if (bcrs instanceof GeographicCRS) {
        if (((GeographicCRS) bcrs).getDatum().equals(wgs84crs.getDatum())) {
          return dp;
        }
      }
        //not going to need CommonFactory.getCoordinateOperationFactory(),
        //can use transform util in org.geotools.referencing.CRS instaed
        //CoordinateReferenceSystem crs2 = dim == 2 ? wgs84crs : CRSUtils.WGS84_PROJ;
        //same equality issues as above
        DirectPosition dp2 = BasicFactories.getDefault().getGeometryFactory(wgs84crs).createDirectPosition();
        try{
            MathTransform transform = CRS.findMathTransform(crs, wgs84crs);
            transform.transform(dp, dp2);
        } catch (FactoryException fe) {
          getLog().warn("Could not create CoordinateOperation to convert DirectPosition CRS "
            + crs.getName() + " to WGS84, using original ordinates", fe);
          //throw new IllegalArgumentException("Unconvertible coordinate CRS");
        } catch (TransformException e) {
          getLog().warn("Could not transform DirectPosition CRS "
            + crs.getName() + " to WGS84, using original ordinates", e);
          //throw new IllegalArgumentException("Unconvertible coordinate CRS");
        } catch (MismatchedDimensionException e) {
          // PENDING(NL): There's probably something better we can do here
          // than just throw an exception.  Normally we only care about lat and lon,
          // and if one has altitude and the other doesn't that shouldn't
          // be a showstopper.
          getLog().warn("Dimension mismatch prevented conversion of DirectPosition CRS "
            + crs.getName() + " to WGS84, using original ordinates", e);
          //throw new IllegalArgumentException("Unconvertible coordinate CRS");
        }
        return dp2;
       
        //hmm, not sure about following line,
        //think the LatLongAlt class was specific to how the polexis code works
        //and is not needed here
        //boolean wasLatLonAlt = dp instanceof LatLongAlt;
        /*
        if (wasLatLonAlt) {
          dp = commonFactory.getGeometryFactory(crs).createDirectPosition();
        }
        */
        /*
        CommonFactory commonFactory = FactoryManager.getCommonFactory();
        CoordinateOperationFactory coopFactory = commonFactory.getCoordinateOperationFactory();
        try {
          CoordinateReferenceSystem crs2 = dim == 2 ? wgs84crs : CRSUtils.WGS84_PROJ;
          CoordinateOperation coOp = coopFactory.createOperation(crs, crs2);
          DirectPosition dp2 = commonFactory.getGeometryFactory(crs2).createDirectPosition();
            dp2 = coOp.getMathTransform().transform(dp, dp2);
          if (dp2.getCoordinateReferenceSystem() != null) {
            if (wasLatLonAlt) {
              dp2 = new LatLonAlt(dp2);
            }
            return dp2;
          } else {
            getLog().warn(
              "Attempted to convert coordinate CRS, transform method returned DirectPosition with null CRS, using original ordinates",
          new IllegalArgumentException("Unconvertible coordinate CRS"));
          }
        } catch (FactoryException fe) {
          getLog().warn("Could not create CoordinateOperation to convert DirectPosition CRS "
            + crs.getName() + " to WGS84, using original ordinates", fe);
          //throw new IllegalArgumentException("Unconvertible coordinate CRS");
        } catch (TransformException e) {
          getLog().warn("Could not transform DirectPosition CRS "
            + crs.getName() + " to WGS84, using original ordinates", e);
          //throw new IllegalArgumentException("Unconvertible coordinate CRS");
        } catch (MismatchedDimensionException e) {
          // PENDING(NL): There's probably something better we can do here
          // than just throw an exception.  Normally we only care about lat and lon,
          // and if one has altitude and the other doesn't that shouldn't
          // be a showstopper.
          getLog().warn("Dimension mismatch prevented conversion of DirectPosition CRS "
            + crs.getName() + " to WGS84, using original ordinates", e);
          //throw new IllegalArgumentException("Unconvertible coordinate CRS");
        } catch (RuntimeException e) {
          getLog().warn("Could not convert DirectPosition CRS "
            + crs.getName() + " to WGS84, using original ordinates", e);
          //throw e;
        }
        return dp;*/
    }
   
    /**
     * Populates the specified PointArray with the specified points.  Any and all preexisting
     * points in the PointArray will be overwritten.
     * @param pointArray The PointArray to be populated.  This must not be null.
     * @param newPts The list of new points
     * /
    public static void populatePointArray(PointArray pointArray, List newPts) {
      List pts = pointArray.positions();
      pts.clear();
      // PENDING(NL): Verify points are really DirectPositions --
      // convert from Positions if not
      // Probably should save this method for when we can use 1.5
      pts.addAll(newPts);
    }
*/   
    /**
     * Populates the specified PointArray with the specified points.  Any and all preexisting
     * points in the PointArray will be overwritten.
     * @param pointArray The PointArray to be populated.  This must not be null.
     * @param dps The new array of points
     */
    public static void populatePointArray(PointArray pointArray, DirectPosition[] dps) {
      pointArray.clear();
      int count = dps.length;
      for (int i = 0; i < count; i++) {
        pointArray.add(dps[i]);
      }
    }
   
    /**
     * Populates the specified PointArray with the specified points, starting at
     * the specified index.  Overwrites points with the specified index or higher.
     * @param pointArray The PointArray to be populated.  This must not be null.
     * @param dps The array of points to be added
     * @param startIndex The first position in the PointArray to overwrite
     * @throws ArrayIndexOutOfBoundsException if the start index is negative or
     * exceeds the number of points initially in the PointArray
     * /
    public static void populatePointArray(PointArray pointArray, DirectPosition[] dps,
        int startIndex) {
      if (startIndex < 0 || startIndex > pointArray.length()) {
        throw new ArrayIndexOutOfBoundsException("Specified start index was "
            + startIndex + ", PointArray size was " + pointArray.length());
      }
      List pts = pointArray.positions();
      pts.clear();
      int count = dps.length;
      for (int i = 0; i < count; i++) {
        pointArray.set(i, dps[i]);
      }
    }
*/   
   
    /**
     * Returns an array of LineStrings corresponding
     * to the primitive elements of the specified CompositeCurve.
     * This will be empty if the CompositeCurve is empty.
     * Throws an exception if any element of the CompositeCurve cannot be converted
     * to a LineString.
     * @param cc The CompositeCurve of interest
     * @return an array of LineStrings
     * @throws IllegalArgumentException if any element cannot be converted.
     * For the present version, only Curves that wrap only LineStrings are convertible.
     */
    public static LineString[] getLineStrings(CompositeCurve cc) {
      ArrayList lsList = getLineStrings(cc, new ArrayList());
      if (lsList == null) {
        throw new IllegalArgumentException(
            "Unable to convert all elements of CompositeCurve to LineString");
      }
      return (LineString[]) lsList.toArray(new LineString[lsList.size()]);
    }
   
    /**
     * Recursively populates the specified List with LineStrings corresponding
     * to the primitive elements of the specified CompositeCurve.
     * Returns null if any element of the CompositeCurve cannot be converted
     * to a LineString.
     * @param cc The CompositeCurve of interest
     * @param lsList The ArrayList to be populated
     * @return The populated List, or null if not valid
     */
    private static ArrayList getLineStrings(CompositeCurve cc, ArrayList lsList) {
        // Cast below can be removed when GeoAPI will be allowed to abandon Java 1.4 support.
      List elements = (List) cc.getGenerators();
      boolean valid = true;
      if (!elements.isEmpty()) {
        Iterator it = elements.iterator();
        LineString ls = null;
        while (it.hasNext() && valid) {
          Object element = it.next();
          if (element instanceof CompositeCurve) {
            valid = getLineStrings((CompositeCurve) element, lsList) != null;
          } else if (element instanceof Curve) {
            // PENDING(NL):  When we have arc geometries implemented,
            // make provision to pass in real parameters for spacing and offset.
            // What we have below essentially just returns start and end points
            // if it's not a LineString
            ls = ((Curve) element).asLineString(Double.MAX_VALUE, Double.MAX_VALUE);
            if (ls != null) {
              lsList.add(ls);
            } else {
              valid = false;
            }
          } else {
            valid = false;
          }         
        }
      }
      if (valid) {
        return null;
      }
      return lsList;
    }
   
    public static DirectPosition[] getDirectPositions(final LineString lineString) {
        final PointArray controlPoints = lineString.getControlPoints();
        final DirectPosition[] returnable = new DirectPosition[controlPoints.size()];
        for (int i = 0; i < controlPoints.size(); i++) {
            returnable[i] = controlPoints.getDirectPosition(i, null);
        }
        return returnable;
    }
   
    public static DirectPosition[] getDirectPositions(final Ring ring) {
        final List directPositionList = new ArrayList();
        // Cast below can be removed when GeoAPI will be allowed to abandon Java 1.4 support.
        final List/*<Curve>*/ generators = (List) ring.getGenerators();
        for (int i = 0; i < generators.size(); i++) {
            final Curve curve = (Curve) generators.get(i);
            final List/*<CurveSegments>*/ segments = curve.getSegments();
            for (int j = 0; j < segments.size(); j++) {
                final CurveSegment curveSegment = (CurveSegment) segments.get(j);
                if (curveSegment instanceof LineString) {
                    final LineString lineString = (LineString) curveSegment;
                    final DirectPosition[] positions = getDirectPositions(lineString);
                    directPositionList.addAll(Arrays.asList(positions));
                    /*final List<Position> positions = lineString.getControlPoints().positions();
                    for (int k = 0; k < positions.size(); k++) {
                        Position position = (Position) positions.get(k);
                        directPositionList.add(position.getPosition());
                    }*/
                   
                }
            }           
        }       
        if (directPositionList.size() > 0) {
            return (DirectPosition[]) directPositionList.toArray(new DirectPosition[directPositionList.size()]);
        }
        return new DirectPosition[0];
    }
   
    public static DirectPosition[] getExteriorDirectPositions(final Polygon polygon) {
        final SurfaceBoundary surfaceBoundary = polygon.getBoundary();
        final Ring exteriorRing = surfaceBoundary.getExterior();
        return GeometryUtils.getDirectPositions(exteriorRing);
    }
   
    public static DirectPosition[][] getInteriorDirectPositions(final Polygon polygon) {
        final SurfaceBoundary surfaceBoundary = polygon.getBoundary();
        final List interiorRings = surfaceBoundary.getInteriors();
        final DirectPosition[][] returnable = new DirectPosition[interiorRings.size()][];
        for (int i = 0; i < interiorRings.size(); i++) {
            returnable[i] = getDirectPositions((Ring)interiorRings.get(i));
        }
        return returnable;
    }
   
    public static PolyhedralSurface createPolyhedralSurface(final DirectPosition[][] patchPoints) {
        // get the crs and factories
        final CoordinateReferenceSystem crs = patchPoints[0][0].getCoordinateReferenceSystem();
        final BasicFactories commonFactory = BasicFactories.getDefault();
        final GeometryFactory geometryFactory = commonFactory.getGeometryFactory(crs);
       
        // create polygons from each of the arrays of directPositions
        final List polygons = new ArrayList(patchPoints.length);
        for (int i = 0; i < patchPoints.length; i++) {
            final Polygon polygon = createPolygon(patchPoints[i]);
            polygons.add(polygon);           
        }       
        return geometryFactory.createPolyhedralSurface(polygons);
    }
   
    public static Polygon createPolygon(
            final DirectPosition[] exteriorRing) {
        return createPolygon(exteriorRing, new DirectPosition[0][0]);
    }
   
    public static Polygon createPolygon(
            final DirectPosition[] exteriorRingPoints,
            final DirectPosition[][] interiorRingsPoints) {
       
        final CoordinateReferenceSystem crs = exteriorRingPoints[0].getCoordinateReferenceSystem();
        final BasicFactories commonFactory = BasicFactories.getDefault();
        final GeometryFactory geometryFactory = commonFactory.getGeometryFactory(crs);
        final PrimitiveFactory primitiveFactory = commonFactory.getPrimitiveFactory(crs);
       
        final Ring exteriorRing = createRing(primitiveFactory, exteriorRingPoints);
       
        List interiorRingList = interiorRingsPoints.length == 0 ?
                Collections.EMPTY_LIST :
                    new ArrayList(interiorRingsPoints.length);
        for (int i = 0; i < interiorRingsPoints.length; i++) {
            final DirectPosition[] interiorRingPoints = interiorRingsPoints[i];
            interiorRingList.add(createRing(primitiveFactory,interiorRingPoints));
        }
       
        final SurfaceBoundary surfaceBoundary =
            primitiveFactory.createSurfaceBoundary(exteriorRing, interiorRingList);
       
        return geometryFactory.createPolygon(surfaceBoundary);
    }
   
    public static SurfaceBoundary createSurfaceBoundary(
            final DirectPosition[] exteriorRingPoints,
            final DirectPosition[][] interiorRingsPoints) {
        final CoordinateReferenceSystem crs = exteriorRingPoints[0].getCoordinateReferenceSystem();
        final BasicFactories commonFactory = BasicFactories.getDefault();
        final PrimitiveFactory primitiveFactory = commonFactory.getPrimitiveFactory(crs);
        return createSurfaceBoundary(primitiveFactory, exteriorRingPoints, interiorRingsPoints);
    }
   
    private static SurfaceBoundary createSurfaceBoundary(
            final PrimitiveFactory primitiveFactory,
            final DirectPosition[] exteriorRingPoints,
            final DirectPosition[][] interiorRingsPoints) {
       
        final Ring exteriorRing = createRing(primitiveFactory, exteriorRingPoints);
       
        final List interiorRingList = interiorRingsPoints.length == 0 ?
                Collections.EMPTY_LIST :
                    new ArrayList();
        for (int i = 0; i < interiorRingsPoints.length; i++) {
            interiorRingList.add(createRing(primitiveFactory, interiorRingsPoints[i]));
        }
       
        final SurfaceBoundary surfaceBoundary =
            primitiveFactory.createSurfaceBoundary(exteriorRing, interiorRingList);
        return surfaceBoundary;
    }
   
    public static Ring createRing(final DirectPosition[] points) {
        final CoordinateReferenceSystem crs = points[0].getCoordinateReferenceSystem();
        final BasicFactories commonFactory = BasicFactories.getDefault();
        final PrimitiveFactory primitiveFactory = commonFactory.getPrimitiveFactory(crs);
        return createRing(primitiveFactory, points);
    }
   
    private static Ring createRing(
            final PrimitiveFactory primitiveFactory,
            final DirectPosition[] points) {
       
        final List curveList = Collections.singletonList(createCurve(primitiveFactory, points));
       
        final Ring ring = primitiveFactory.createRing(curveList);
        return ring;
    }
   
    public static Curve createCurve(final DirectPosition[] points) {
        final CoordinateReferenceSystem crs = points[0].getCoordinateReferenceSystem();
        final BasicFactories commonFactory = BasicFactories.getDefault();
        final PrimitiveFactory primitiveFactory = commonFactory.getPrimitiveFactory(crs);
        return createCurve(primitiveFactory, points);
    }
   
    private static Curve createCurve(
            final PrimitiveFactory primitiveFactory,
            final DirectPosition[] points) {
       
        final BasicFactories commonFactory = BasicFactories.getDefault();
        final GeometryFactory geometryFactory = commonFactory.getGeometryFactory(primitiveFactory.getCoordinateReferenceSystem());
       
        final List curveSegmentList = Collections.singletonList(createLineString(geometryFactory, points));
       
        final Curve curve = primitiveFactory.createCurve(curveSegmentList);
        return curve;
    }

    public static LineString createLineString(final DirectPosition[] points) {
        final CoordinateReferenceSystem crs = points[0].getCoordinateReferenceSystem();
        final BasicFactories commonFactory = BasicFactories.getDefault();
        final GeometryFactory geometryFactory = commonFactory.getGeometryFactory(crs);
        return createLineString(geometryFactory, points);
    }
   
    private static LineString createLineString(
            final GeometryFactory geometryFactory,
            final DirectPosition[] points) {
       
        final LineString lineString = geometryFactory.createLineString(new ArrayList(Arrays.asList(points)));
        return lineString;
    }
   
   
    //*************************************************************************
    //  private static methods
    //*************************************************************************
   
    /**
     * Gets the log.
     * @return the log
     */
    protected static Log getLog() {
        if (log == null) {
            log = LogFactory.getLog(GeometryUtils.class);
        }
        return log;
    }
   
    //*************************************************************************
    //  Static Fields
    //*************************************************************************
   
    /**
     * commons log.
     */
    private static transient Log log;
   
    //*************************************************************************
    //  Constructors
    //*************************************************************************
   
    /**
     * Prevents creating a new {@code GeometryUtils}.
     */
    private GeometryUtils() { }

    /*public static void main(String[] args) {
        CoordinateReferenceSystem crs = CRSUtils.createCoordinateReferenceSystem("4327");
        LatLonAlt[] positions = new LatLonAlt[] {
                new LatLonAlt(Math.PI/4, Math.PI/4, 1, SI.RADIAN, NonSI.MILE, crs),
                new LatLonAlt(-Math.PI/4, -Math.PI/4, .5, SI.RADIAN, NonSI.MILE, crs),
                new LatLonAlt(Math.PI/3, Math.PI/3, 0, SI.RADIAN, NonSI.MILE, crs)
        };
        System.out.println("converting "+positions[0]+", "+positions[1]+", "+positions[2]);
        AxisDirection[] targetDirections = new AxisDirection[] {
                AxisDirection.EAST,
                AxisDirection.NORTH,
                AxisDirection.UP
        };
        System.out.println("directions "+targetDirections[0]+", "+targetDirections[1]+", "+targetDirections[2]);
        Unit[] targetUnits = new Unit[] {
                //SI.RADIAN,
                //SI.RADIAN,
                //NonSI.FOOT
                NonSI.DEGREE_ANGLE,
                NonSI.DEGREE_ANGLE,
                SI.METER
        };
        System.out.println("units      "+targetUnits[0]+", "+targetUnits[1]+", "+targetUnits[2]);
       
        double[] points = getPoints(positions, targetDirections, targetUnits);
        System.out.println("response a "+points[0]+", "+points[1]+", "+points[2]);
        System.out.println("response b "+points[3]+", "+points[4]+", "+points[5]);
        System.out.println("response c "+points[6]+", "+points[7]+", "+points[8]);
       
    }*/
   
         /**
     * Check if a reference coordinate system has the expected number of dimensions.
     * - code lifted from com.polexis.referencing.CRSUtils - thanks Jesse!
     * - not sure i see the need for both this method and CRS.ensureDimensionMatch()
     *
     * @param name     The argument name.
     * @param crs      The coordinate reference system to check.
     * @param expected The expected number of dimensions.
     */
    public static void checkDimension(
            final String name,
            final CoordinateReferenceSystem crs,
            final int expected) {
        if (crs != null) {
            final int actual = crs.getCoordinateSystem().getDimension();
            if (actual != expected) {
                throw new IllegalArgumentException(/*Resources.format(
                 ResourceKeys.ERROR_MISMATCHED_DIMENSION_$3,
                 name, new Integer(actual), new Integer(expected))*/"");
            }
        }
    }
   
    /**
     * Convenience method for checking object dimension validity.
     * This method is usually invoked for argument checking.
     *- code lifted from com.polexis.referencing.CRSUtils - thanks Jesse!
     *
     * @param  name The name of the argument to check.
     * @param  dimension The object dimension.
     * @param  expectedDimension The Expected dimension for the object.
     * @throws MismatchedDimensionException if the object doesn't have the expected dimension.
     */
    public static void ensureDimensionMatch(
            final String name,
            final int dimension,
            final int expectedDimension) throws MismatchedDimensionException {
        if (dimension != expectedDimension) {
            throw new MismatchedDimensionException(name + " does not have " + dimension + "dimension(s)"
                                                    /*
                                                    * Resources.format(
                                                    * ResourceKeys.ERROR_MISMATCHED_DIMENSION_$3,
                                                    * name, new
                                                    * Integer(dimension), new
                                                    * Integer(expectedDimension))
                                                    */);
        }
    }

        /**
     * Returns the {@code CoordinateSystemAxis} with the given {@code AxisDirection}.
     * @param cs the {@code CoordinateSystem} to check
     * @param direction the {@code AxisDirection} to check for
     * @return
     */
    public static CoordinateSystemAxis getDirectedAxis(
            final CoordinateSystem cs,
            final AxisDirection direction) {
       
        int dimension = cs.getDimension();
        for (int i = 0; i < dimension; i++) {
            if (cs.getAxis(i).getDirection().equals(direction)) {
                return cs.getAxis(i);
            }
        }
        return null;
    }

    /*
     * reurns the index of an axis in a given coordinate system,
     * axes are specified using org.opengis.referencing.cs.AxisDirection
     * used by JTS geometry wrappers
     * - code from com.polexis.referencing.cs.CSUtils
     * - is AbstractCS a more appropriate place for this?
     */
    public static int getDirectedAxisIndex(
         final CoordinateSystem cs,
         final AxisDirection direction) {
       int dimension = cs.getDimension();
       for (int i = 0; i < dimension; i++) {
       if (cs.getAxis(i).getDirection().equals(direction)) {
            return i;
            }
        }
        return -1;
    }

    /*
     * reurns the index of an axis in a given coordinate system,
     * axes are specified using org.opengis.referencing.cs.AxisDirection
     * used by JTS geometry wrappers
     * - code from com.polexis.referencing.cs.CSUtils
     * - is AbstractCS a more appropriate place for this?
     */   
    public static Unit getDirectedAxisUnit(
            final CoordinateSystem cs,
            final AxisDirection direction) {
        CoordinateSystemAxis axis = getDirectedAxis(cs, direction);
        if (axis != null) {
            return axis.getUnit();
        }
        return null;
    }

}
TOP

Related Classes of org.geotools.geometry.jts.GeometryUtils

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.