/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2001-2006 Vivid Solutions
* (C) 2001-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.iso.util.algorithmND;
import java.util.Iterator;
import java.util.List;
import org.geotools.geometry.iso.aggregate.MultiCurveImpl;
import org.geotools.geometry.iso.complex.CompositeCurveImpl;
import org.geotools.geometry.iso.coordinate.DirectPositionImpl;
import org.geotools.geometry.iso.primitive.CurveImpl;
import org.geotools.geometry.iso.primitive.RingImpl;
import org.geotools.geometry.iso.primitive.RingImplUnsafe;
import org.geotools.geometry.iso.root.GeometryImpl;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.Geometry;
import org.opengis.geometry.primitive.OrientableCurve;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
/**
* Computes the centroid of a linear geometry.
* <h2>Algorithm</h2>
* Compute the average of the midpoints of all line segments weighted by the
* segment length.
*
* @source $URL$
*/
public class CentroidLine {
//private FeatGeomFactoryImpl factory = null;
private CoordinateReferenceSystem crs = null;
DirectPositionImpl centSum = null;
private double totalLength = 0.0;
/**
* Creates a new Centroid operation
*
* @param crs
*/
public CentroidLine(CoordinateReferenceSystem crs) {
this.crs = crs;
this.centSum = new DirectPositionImpl(crs); //this.factory.getGeometryFactoryImpl().createDirectPosition();
}
/**
* Adds the linestring(s) defined by a Geometry to the centroid total. If
* the geometry is not linear it does not contribute to the centroid
*
* @param geom
* the geometry to add
*/
public void add(Geometry geom) {
if (geom instanceof CurveImpl) {
this.addCurve((CurveImpl) geom);
} else if (geom instanceof RingImpl) {
this.addCurveIter(((RingImplUnsafe)geom).getGenerators().iterator());
} else if (geom instanceof MultiCurveImpl) {
this.addCurveIter(((MultiCurveImpl)geom).getElements().iterator());
} else if (geom instanceof CompositeCurveImpl) {
this.addCurveIter(((CompositeCurveImpl)geom).getGenerators().iterator());
}
}
private void addCurveIter(Iterator<OrientableCurve> curveIter) {
while (curveIter.hasNext()) {
this.addCurve((CurveImpl) curveIter.next());
}
}
private void addCurve(CurveImpl curve) {
this.addPointSequence(curve.asDirectPositions());
}
/**
* Adds the length defined by an array of coordinates.
*
* @param pts
* an array of {@link Coordinate}s
*/
public void addPointSequence(List<DirectPosition> pts) {
DirectPositionImpl dpAct = new DirectPositionImpl( pts.get(0) );
DirectPositionImpl directPositionNext;
for (int i = 0; i < pts.size()-1; i++) {
directPositionNext = new DirectPositionImpl( pts.get(i+1) );
double segmentLen = dpAct.distance(directPositionNext);
this.totalLength += segmentLen;
DirectPositionImpl tempMid = dpAct.clone();
tempMid.add( directPositionNext);
tempMid.divideBy(2);
tempMid.scale(segmentLen);
this.centSum.add(tempMid);
dpAct = directPositionNext;
}
}
/**
* Returns the centroid for the added curves
*
* @return Centroid position
*/
public DirectPositionImpl getCentroid() {
this.centSum.divideBy(this.totalLength);
return this.centSum;
}
}