package com.revolsys.geometry.model.segment;
import java.util.Iterator;
import java.util.NoSuchElementException;
import com.revolsys.geometry.model.Geometry;
import com.revolsys.geometry.model.GeometryFactory;
import com.revolsys.geometry.model.LineString;
import com.revolsys.geometry.model.LinearRing;
import com.revolsys.geometry.model.Polygon;
import com.revolsys.geometry.model.Polygonal;
import com.revolsys.geometry.model.impl.AbstractLineString;
import com.revolsys.geometry.model.vertex.Vertex;
public class MultiPolygonSegment extends AbstractLineString implements Iterator<Segment>, Segment {
private static final long serialVersionUID = 1L;
private int partIndex;
private int ringIndex;
private int segmentIndex;
private final Polygonal polygonal;
public MultiPolygonSegment(final Polygonal polygonal, final int partIndex, final int ringIndex,
final int segmentIndex) {
this.polygonal = polygonal;
this.partIndex = partIndex;
this.ringIndex = ringIndex;
this.segmentIndex = segmentIndex;
}
@Override
public MultiPolygonSegment clone() {
return (MultiPolygonSegment)super.clone();
}
@Override
public int getAxisCount() {
return this.polygonal.getAxisCount();
}
@Override
public double getCoordinate(final int vertexIndex, final int axisIndex) {
if (vertexIndex < 0 || vertexIndex > 1) {
return Double.NaN;
} else {
final LinearRing ring = getRing();
if (ring == null) {
return Double.NaN;
} else {
return ring.getCoordinate(this.segmentIndex + vertexIndex, axisIndex);
}
}
}
@Override
public double[] getCoordinates() {
final int axisCount = getAxisCount();
final double[] coordinates = new double[axisCount * 2];
for (int vertexIndex = 0; vertexIndex < 2; vertexIndex++) {
for (int axisIndex = 0; axisIndex < axisCount; axisIndex++) {
coordinates[vertexIndex * axisCount + axisIndex] = getCoordinate(vertexIndex, axisIndex);
}
}
return coordinates;
}
@SuppressWarnings("unchecked")
@Override
public <V extends Geometry> V getGeometry() {
return (V)this.polygonal;
}
@Override
public GeometryFactory getGeometryFactory() {
return this.polygonal.getGeometryFactory();
}
@Override
public Vertex getGeometryVertex(final int index) {
final Polygonal polygon = this.polygonal;
if (index == 0) {
return polygon.getVertex(this.partIndex, this.ringIndex, this.segmentIndex);
} else if (index == 1) {
return polygon.getVertex(this.partIndex, this.ringIndex, this.segmentIndex + 1);
} else {
return null;
}
}
@Override
public int getPartIndex() {
return this.partIndex;
}
public Polygon getPolygon() {
final Polygonal polygonal = this.polygonal;
if (polygonal == null) {
return null;
} else {
return polygonal.getPolygon(this.partIndex);
}
}
public Polygonal getPolygonal() {
return (Polygonal)getGeometry();
}
public LinearRing getRing() {
final Polygon polygon = getPolygon();
if (polygon == null) {
return null;
} else {
return polygon.getRing(this.ringIndex);
}
}
@Override
public int getRingIndex() {
return this.ringIndex;
}
@Override
public int[] getSegmentId() {
return new int[] {
this.partIndex, this.ringIndex, this.segmentIndex
};
}
@Override
public int getSegmentIndex() {
return this.segmentIndex;
}
@Override
public double getX(final int vertexIndex) {
if (vertexIndex < 0 || vertexIndex > 1) {
return Double.NaN;
} else {
final LinearRing ring = getRing();
if (ring == null) {
return Double.NaN;
} else {
return ring.getX(this.segmentIndex + vertexIndex);
}
}
}
@Override
public double getY(final int vertexIndex) {
if (vertexIndex < 0 || vertexIndex > 1) {
return Double.NaN;
} else {
final LinearRing ring = getRing();
if (ring == null) {
return Double.NaN;
} else {
return ring.getY(this.segmentIndex + vertexIndex);
}
}
}
@Override
public double getZ(final int vertexIndex) {
if (vertexIndex < 0 || vertexIndex > 1) {
return Double.NaN;
} else {
final LinearRing ring = getRing();
if (ring == null) {
return Double.NaN;
} else {
return ring.getZ(this.segmentIndex + vertexIndex);
}
}
}
@Override
public boolean hasNext() {
final Polygonal polygonal = this.polygonal;
if (polygonal.isEmpty()) {
return false;
} else {
int partIndex = this.partIndex;
int ringIndex = this.ringIndex;
int segmentIndex = this.segmentIndex + 1;
while (partIndex < polygonal.getGeometryCount()) {
final Polygon polygon = getPolygon();
while (ringIndex < polygon.getRingCount()) {
final LinearRing ring = polygon.getRing(ringIndex);
if (segmentIndex < ring.getSegmentCount()) {
return true;
} else {
ringIndex++;
segmentIndex = 0;
}
}
partIndex++;
ringIndex = 0;
segmentIndex = 0;
}
return false;
}
}
@Override
public boolean isLineClosed() {
return true;
}
@Override
public boolean isLineEnd() {
final LineString line = getRing();
return this.segmentIndex == line.getSegmentCount();
}
@Override
public boolean isLineStart() {
return this.segmentIndex == 0;
}
@Override
public Segment next() {
this.segmentIndex++;
final Polygonal polygonal = this.polygonal;
final int geometryCount = polygonal.getGeometryCount();
while (this.partIndex < geometryCount) {
final Polygon polygon = getPolygon();
final int ringCount = polygon.getRingCount();
while (this.ringIndex < ringCount) {
final LinearRing ring = polygon.getRing(this.ringIndex);
if (this.segmentIndex < ring.getSegmentCount()) {
return this;
} else {
this.ringIndex++;
this.segmentIndex = 0;
}
}
this.partIndex++;
this.ringIndex = 0;
this.segmentIndex = 0;
}
throw new NoSuchElementException();
}
@Override
public void remove() {
throw new UnsupportedOperationException("Removing segments not supported");
}
@Override
public void setSegmentId(final int... segmentId) {
this.partIndex = segmentId[0];
this.ringIndex = segmentId[1];
this.segmentIndex = segmentId[2];
}
}