All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geotools.geometry.jts.CompoundCurve Maven / Gradle / Ivy

Go to download

The main module contains the GeoTools public interfaces that are used by other GeoTools modules (and GeoTools applications). Where possible we make use industry standard terms as provided by OGC and ISO standards. The formal GeoTools public api consists of gt-metadata, jts and the gt-main module. The main module contains the default implementations that are available provided to other GeoTools modules using our factory system. Factories are obtained from an appropriate FactoryFinder, giving applications a chance configure the factory used using the Factory Hints facilities. FilterFactory ff = CommonFactoryFinder.getFilterFactory(); Expression expr = ff.add( expression1, expression2 ); If you find yourself using implementation specific classes chances are you doing it wrong: Expression expr = new AddImpl( expression1, expressiom2 );

There is a newer version: 24.2-oss84-1
Show newest version
/*
 *    GeoTools - The Open Source Java GIS Toolkit
 *    http://geotools.org
 *
 *    (C) 2014 - 2015, 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 java.util.ArrayList;
import java.util.List;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.CoordinateFilter;
import org.locationtech.jts.geom.CoordinateSequence;
import org.locationtech.jts.geom.CoordinateSequenceComparator;
import org.locationtech.jts.geom.CoordinateSequenceFilter;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryComponentFilter;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.GeometryFilter;
import org.locationtech.jts.geom.IntersectionMatrix;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.PrecisionModel;

/**
 * A CompoundCurve is a connected sequence of circular arcs and linear segments.
 *
 * @author Andrea Aime - GeoSolutions
 */
public class CompoundCurve extends LineString implements CompoundCurvedGeometry {

    private static final long serialVersionUID = -5796254063449438787L;

    List components;

    LineString linearized;

    double tolerance;

    public CompoundCurve(List components, GeometryFactory factory, double tolerance) {
        super(CircularString.FAKE_STRING_2D, factory);
        this.tolerance = tolerance;

        // sanity check, we don't want compound curves containing other compound curves
        this.components = new ArrayList<>();
        for (LineString ls : components) {
            if (ls instanceof CompoundCurve) {
                CompoundCurve cc = (CompoundCurve) ls;
                this.components.addAll(cc.components);
            } else {
                this.components.add(ls);
            }
        }

        // check connectedness
        if (components.size() > 1) {
            LineString prev = components.get(0);
            for (int i = 1; i < components.size(); i++) {
                LineString curr = components.get(i);
                Coordinate endPoint = prev.getCoordinateN(prev.getNumPoints() - 1);
                Coordinate startPoint = curr.getCoordinateN(0);
                if (!endPoint.equals(startPoint)) {
                    throw new IllegalArgumentException(
                            "Found two elements that are not connected, " + prev + " and " + curr);
                }
                prev = curr;
            }
        }
    }

    @Override
    public int getCoordinatesDimension() {
        if (components.size() == 0) {
            return 2;
        }
        int dimension = Integer.MAX_VALUE;
        for (LineString component : components) {
            int curr;
            if (component instanceof CurvedGeometry) {
                curr = ((CurvedGeometry) component).getCoordinatesDimension();
            } else {
                curr = component.getCoordinateSequence().getDimension();
            }
            dimension = Math.min(curr, dimension);
        }

        return dimension;
    }

    @Override
    public LineString linearize() {
        return linearize(this.tolerance);
    }

    public LineString linearize(double tolerance) {
        // use the cached one if we are asked for the default geometry tolerance
        boolean isDefaultTolerance = CircularArc.equals(tolerance, this.tolerance);
        if (linearized != null && isDefaultTolerance) {
            return linearized;
        }

        CoordinateSequence cs = getLinearizedCoordinateSequence(tolerance);
        LineString result = new LineString(cs, factory);
        if (isDefaultTolerance) {
            linearized = result;
        }

        return result;
    }

    protected CoordinateSequence getLinearizedCoordinateSequence(final double tolerance) {
        // collect all the points of all components
        final GrowableOrdinateArray gar = new GrowableOrdinateArray();
        for (LineString component : components) {
            // the last point of the previous element is the first point of the next one,
            // remove the duplication
            if (gar.size() > 0) {
                gar.setSize(gar.size() - 2);
            }
            // linearize with tolerance the circular strings, take the linear ones as is
            if (component instanceof SingleCurvedGeometry) {
                SingleCurvedGeometry curved = (SingleCurvedGeometry) component;
                CoordinateSequence cs = curved.getLinearizedCoordinateSequence(tolerance);
                gar.addAll(cs);
            } else {
                CoordinateSequence cs = component.getCoordinateSequence();
                for (int i = 0; i < cs.size(); i++) {
                    gar.add(cs.getX(i), cs.getY(i));
                }
            }
        }

        CoordinateSequence cs = gar.toCoordinateSequence(getFactory());
        return cs;
    }

    @Override
    public double getTolerance() {
        return tolerance;
    }

    /**
     * Returns the components of this compound curve, which will be a list of straight LineString
     * objects and CircularString/CircularRing
     */
    public List getComponents() {
        return components;
    }

    /* Optimized overridden methods */

    public boolean isClosed() {
        LineString firstComponent = components.get(0);
        LineString lastComponent = components.get(components.size() - 1);
        return firstComponent.getStartPoint().equals(lastComponent.getEndPoint());
    }

    public int getDimension() {
        return super.getDimension();
    }

    public int getBoundaryDimension() {
        return super.getDimension();
    }

    public boolean isEmpty() {
        for (LineString ls : components) {
            if (!ls.isEmpty()) {
                return false;
            }
        }
        return true;
    }

    public String getGeometryType() {
        return "CompoundCurve";
    }

    public CompoundCurve reverse() {
        return (CompoundCurve) super.reverse();
    }

    // should be protected when fixed in LinearRing
    public CompoundCurve reverseInternal() {
        // reverse the component, and reverse each component internal elements
        List reversedComponents = new ArrayList<>(components.size());
        for (LineString ls : components) {
            LineString reversed = (LineString) ls.reverse();
            reversedComponents.add(0, reversed);
        }
        return new CompoundCurve(reversedComponents, getFactory(), tolerance);
    }

    public Point getInteriorPoint() {
        return components.get(components.size() / 2).getInteriorPoint();
    }

    public Geometry getEnvelope() {
        return super.getEnvelope();
    }

    public Envelope getEnvelopeInternal() {
        return super.getEnvelopeInternal();
    }

    @Override
    protected Envelope computeEnvelopeInternal() {
        final Envelope result = new Envelope();
        for (LineString ls : components) {
            result.expandToInclude(ls.getEnvelopeInternal());
        }
        return result;
    }

    public int getNumGeometries() {
        return components.size();
    }

    public Geometry getGeometryN(int n) {
        return components.get(n);
    }

    public void setUserData(Object userData) {
        super.setUserData(userData);
    }

    public int getSRID() {
        return super.getSRID();
    }

    public void setSRID(int SRID) {
        super.setSRID(SRID);
    }

    public GeometryFactory getFactory() {
        return super.getFactory();
    }

    public Object getUserData() {
        return super.getUserData();
    }

    public PrecisionModel getPrecisionModel() {
        return super.getPrecisionModel();
    }

    public boolean equalsExact(Geometry other) {
        return equalsExact(other, 0);
    }

    public boolean equalsExact(Geometry other, double tolerance) {
        if (other instanceof CompoundCurve) {
            CompoundCurve ccOther = (CompoundCurve) other;
            if (ccOther.components.size() != components.size()) {
                return false;
            }
            for (int i = 0; i < components.size(); i++) {
                LineString ls1 = components.get(i);
                LineString ls2 = ccOther.components.get(i);
                if (!ls1.equalsExact(ls2, tolerance)) {
                    return false;
                }
            }

            return true;
        }
        return linearize(tolerance).equalsExact(other, tolerance);
    }

    public boolean equals(Geometry other) {
        if (other instanceof CompoundCurve) {
            CompoundCurve ccOther = (CompoundCurve) other;
            if (ccOther.components.size() != components.size()) {
                return false;
            }
            for (int i = 0; i < components.size(); i++) {
                LineString ls1 = components.get(i);
                LineString ls2 = ccOther.components.get(i);
                if (!ls1.equals(ls2)) {
                    return false;
                }
            }

            return true;
        }
        return linearize().equals(other);
    }

    public boolean equalsTopo(Geometry other) {
        if (other instanceof CompoundCurve) {
            CompoundCurve ccOther = (CompoundCurve) other;
            if (ccOther.components.size() != components.size()) {
                return false;
            }
            for (int i = 0; i < components.size(); i++) {
                LineString ls1 = components.get(i);
                LineString ls2 = ccOther.components.get(i);
                if (!ls1.equalsTopo(ls2)) {
                    return false;
                }
            }

            return true;
        }
        return linearize().equalsTopo(other);
    }

    public boolean equals(Object o) {
        if (o instanceof Geometry) {
            return equals((Geometry) o);
        } else {
            return false;
        }
    }

    public int hashCode() {
        return super.hashCode();
    }

    public String toString() {
        return toCurvedText();
    }

    public String toCurvedText() {
        StringBuilder sb = new StringBuilder("COMPOUNDCURVE ");

        if (components.size() == 0) {
            sb.append("EMPTY");
        } else {
            sb.append("(");
            for (int k = 0; k < components.size(); k++) {
                LineString component = components.get(k);
                if (component instanceof SingleCurvedGeometry) {
                    SingleCurvedGeometry curved = (SingleCurvedGeometry) component;
                    sb.append(curved.toCurvedText());
                } else {
                    sb.append("(");
                    CoordinateSequence cs = component.getCoordinateSequence();
                    for (int i = 0; i < cs.size(); i++) {
                        sb.append(cs.getX(i) + " " + cs.getY(i));
                        if (i < cs.size() - 1) {
                            sb.append(", ");
                        }
                    }
                    sb.append(")");
                }
                if (k < components.size() - 1) {
                    sb.append(", ");
                }
            }
            sb.append(")");
        }
        return sb.toString();
    }

    public boolean equalsNorm(Geometry g) {
        return super.equalsNorm(g);
    }

    /*
     * Simple linearized delegate methods
     */

    public boolean isRectangle() {
        return linearize().isRectangle();
    }

    public Coordinate[] getCoordinates() {
        return linearize().getCoordinates();
    }

    public CoordinateSequence getCoordinateSequence() {
        return linearize().getCoordinateSequence();
    }

    public Coordinate getCoordinateN(int n) {
        return linearize().getCoordinateN(n);
    }

    public Coordinate getCoordinate() {
        return linearize().getCoordinate();
    }

    public int getNumPoints() {
        return linearize().getNumPoints();
    }

    public Point getPointN(int n) {
        return linearize().getPointN(n);
    }

    public Point getStartPoint() {
        return linearize().getStartPoint();
    }

    public Point getEndPoint() {
        return linearize().getEndPoint();
    }

    public boolean isRing() {
        return linearize().isRing();
    }

    public double getLength() {
        // todo: maybe compute the actual circular length?
        return linearize().getLength();
    }

    public Geometry getBoundary() {
        return linearize().getBoundary();
    }

    public boolean isCoordinate(Coordinate pt) {
        return linearize().isCoordinate(pt);
    }

    public void apply(CoordinateFilter filter) {
        linearize().apply(filter);
    }

    public void apply(CoordinateSequenceFilter filter) {
        linearize().apply(filter);
    }

    public void apply(GeometryFilter filter) {
        linearize().apply(filter);
    }

    public void apply(GeometryComponentFilter filter) {
        linearize().apply(filter);
    }

    @Override
    public CompoundCurve copyInternal() {
        return new CompoundCurve(components, factory, tolerance);
    }

    public void normalize() {
        linearize().normalize();
    }

    public boolean isSimple() {
        return linearize().isSimple();
    }

    public boolean isValid() {
        return linearize().isValid();
    }

    public double distance(Geometry g) {
        return linearize().distance(g);
    }

    public boolean isWithinDistance(Geometry geom, double distance) {
        return linearize().isWithinDistance(geom, distance);
    }

    public double getArea() {
        return linearize().getArea();
    }

    public Point getCentroid() {
        return linearize().getCentroid();
    }

    public void geometryChanged() {
        linearize().geometryChanged();
    }

    public boolean disjoint(Geometry g) {
        return linearize().disjoint(g);
    }

    public boolean touches(Geometry g) {
        return linearize().touches(g);
    }

    public boolean intersects(Geometry g) {
        return linearize().intersects(g);
    }

    public boolean crosses(Geometry g) {
        return linearize().crosses(g);
    }

    public boolean within(Geometry g) {
        return linearize().within(g);
    }

    public boolean contains(Geometry g) {
        return linearize().contains(g);
    }

    public boolean overlaps(Geometry g) {
        return linearize().overlaps(g);
    }

    public boolean covers(Geometry g) {
        return linearize().covers(g);
    }

    public boolean coveredBy(Geometry g) {
        return linearize().coveredBy(g);
    }

    public boolean relate(Geometry g, String intersectionPattern) {
        return linearize().relate(g, intersectionPattern);
    }

    public IntersectionMatrix relate(Geometry g) {
        return linearize().relate(g);
    }

    public Geometry buffer(double distance) {
        return linearize().buffer(distance);
    }

    public Geometry buffer(double distance, int quadrantSegments) {
        return linearize().buffer(distance, quadrantSegments);
    }

    public Geometry buffer(double distance, int quadrantSegments, int endCapStyle) {
        return linearize().buffer(distance, quadrantSegments, endCapStyle);
    }

    public Geometry convexHull() {
        return linearize().convexHull();
    }

    public Geometry intersection(Geometry other) {
        return linearize().intersection(other);
    }

    public Geometry union(Geometry other) {
        return linearize().union(other);
    }

    public Geometry difference(Geometry other) {
        return linearize().difference(other);
    }

    public Geometry symDifference(Geometry other) {
        return linearize().symDifference(other);
    }

    public Geometry union() {
        return linearize().union();
    }

    public Geometry norm() {
        return linearize().norm();
    }

    public int compareTo(Object o) {
        return linearize().compareTo(o);
    }

    public int compareTo(Object o, CoordinateSequenceComparator comp) {
        return linearize().compareTo(o, comp);
    }

    @Override
    public String toText() {
        return linearize().toText();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy