gt: 		nbPoints = points2.length / 3;
context: /*******************************************************************************************************
   *
   * msi.gama.common.geometry.UnboundedCoordinateSequence.java, in plugin msi.gama.core, is part of the source code of the
   * GAMA modeling and simulation platform (v. 1.8.1)
   *
   * (c) 2007-2020 UMI 209 UMMISCO IRD/SU & Partners
   *
   * Visit https://github.com/gama-platform/gama for license information and contacts.
   *
   ********************************************************************************************************/
  package msi.gama.common.geometry;
  
  import static com.google.common.collect.Iterators.forArray;
  import static com.google.common.collect.Iterators.limit;
  
  import java.util.Arrays;
  import java.util.Iterator;
  
  import com.vividsolutions.jts.geom.Coordinate;
  import com.vividsolutions.jts.geom.Envelope;
  
  import msi.gama.metamodel.shape.GamaPoint;
  
  public class UnboundedCoordinateSequence implements ICoordinates {
  
  	final static int INITIAL_SIZE = 1000;
  	GamaPoint[] points = null;
  	int nbPoints;
  	final GamaPoint temp = new GamaPoint();
  
  	private void fillFrom(final int begin) {
  		for (int i = begin; i < points.length; i++) {
  			points[i] = new GamaPoint();
  		}
  	}
  
  	public UnboundedCoordinateSequence() {
  		growTo(INITIAL_SIZE);
  	}
  
  	private void growTo(final int size) {
  		int begin = 0;
  		if (points == null) {
  			points = new GamaPoint[size];
  		} else {
  			if (size <= points.length) { return; }
  			begin = points.length;
  			points = Arrays.copyOf(points, Math.max(size, begin + begin / 2));
  		}
  		fillFrom(begin);
  	}
  
  	@Override
  	public int getDimension() {
  		return 3;
  	}
  
  	UnboundedCoordinateSequence(final boolean copy, final int size, final GamaPoint[] points2) {
  		growTo(size);
  		nbPoints = size;
  		for (int i = 0; i < size; i++) {
  			points[i].setLocation(points2[i]);
  		}
  		if (copy) {
  			ensureClockwiseness();
  		}
  	}
  
  	@Override
  	public final UnboundedCoordinateSequence clone() {
  		return new UnboundedCoordinateSequence(true, nbPoints, points);
  	}
  
  	@Override
  	public Coordinate getCoordinateCopy(final int i) {
  		return points[i].clone();
  	}
  
  	@Override
  	public void getCoordinate(final int index, final Coordinate coord) {
  		coord.setCoordinate(points[index]);
  	}
  
  	@Override
  	public double getX(final int index) {
  		return points[index].x;
  	}
  
  	@Override
  	public double getY(final int index) {
  		return points[index].y;
  	}
  
  	@Override
  	public double getOrdinate(final int index, final int ordinateIndex) {
  		return points[index].getOrdinate(ordinateIndex);
  	}
  
  	@Override
  	public int size() {
  		return nbPoints;
  	}
  
  	@Override
  	public void setOrdinate(final int index, final int ordinateIndex, final double value) {
  		points[index].setOrdinate(ordinateIndex, value);
  
  	}
  
  	@Override
  	public Envelope expandEnvelope(final Envelope env) {
  		for (int i = 0; i < nbPoints - 1; i++) {
  			env.expandToInclude(points[i]);
  		}
  		return env;
  	}
  
  	@Override
  	public Iterator<GamaPoint> iterator() {
  		return limit(forArray(points), nbPoints);
  	}
  
  	@Override
  	public void addCenterTo(final GamaPoint other) {
  		final int size = isRing() ? nbPoints - 1 : nbPoints;
  		double x = 0, y = 0, z = 0;
  		for (int i = 0; i < size; i++) {
  			final GamaPoint p = points[i];
  			x += p.x;
  			y += p.y;
  			z += p.z;
  		}
  		x /= size;
  		y /= size;
  		z /= size;
  		other.x += x;
  		other.y += y;
  		other.z += z;
  	}
  
  	@Override
  	public GamaPoint getCoordinate(final int i) {
  		return points[i];
  	}
  
  	@Override
  	public ICoordinates yNegated() {
  		final int size = points.length;
  		final GamaPoint[] points2 = new GamaPoint[size];
  		for (int i = 0; i < size; i++) {
  			// CW property is ensured by reversing the resulting array
  			points2[i] = points[size - i - 1].yNegated();
  		}
  		return new GamaCoordinateSequence(false, points2);
  
  	}
  
  	@Override
  	public GamaPoint[] toCoordinateArray() {
  		return points;
  	}
  
  	@Override
  	public void visit(final IndexedVisitor v, final int max, final boolean clockwise) {
  		final int limit = max < 0 || max > nbPoints ? nbPoints : max;
  		final boolean reversed = isRing() && !clockwise;
  		if (reversed) {
  			reverseVisit(v, limit);
  		} else {
  			visit(v, limit);
  		}
  	}
  
  	private void visit(final IndexedVisitor v, final int max) {
  		for (int i = 0; i < max; i++) {
  			final GamaPoint p = points[i];
  			v.process(i, p.x, p.y, p.z);
  		}
  	}
  
  	private void reverseVisit(final IndexedVisitor v, final int max) {
  		for (int i = max - 1, j = 0; i >= 0; i--, j++) {
  			final GamaPoint p = points[i];
  			v.process(j, p.x, p.y, p.z);
  		}
  	}
  
  	@Override
  	public void visitClockwise(final VertexVisitor v) {
  		final int max = isRing() ? nbPoints - 1 : nbPoints;
  		for (int i = 0; i < max; i++) {
  			final GamaPoint p = points[i];
  			v.process(p.x, p.y, p.z);
  		}
  
  	}
  
  	@Override
  	public void visitYNegatedCounterClockwise(final VertexVisitor v) {
  		final int max = isRing() ? nbPoints - 1 : nbPoints;
  		for (int i = 0; i < max; i++) {
  			final GamaPoint p = points[i];
  			v.process(p.x, -p.y, p.z);
  		}
  
  	}
  
  	@Override
  	public void visit(final PairVisitor v) {
  		for (int i = 0; i < nbPoints - 1; i++) {
  			v.process(points[i], points[i + 1]);
  		}
  	}
  
  	@Override
  	public void getNormal(final boolean clockwise, final double factor, final GamaPoint normal) {
  		normal.setLocation(0, 0, 0);
  		if (nbPoints < 3) { return; }
  		for (int i = 0; i < nbPoints - 1; i++) {
  			final GamaPoint v0 = points[i];
  			final GamaPoint v1 = points[i + 1];
  			normal.x += (v0.y - v1.y) * (v0.z + v1.z);
  			normal.y += (v0.z - v1.z) * (v0.x + v1.x);
  			normal.z += (v0.x - v1.x) * (v0.y + v1.y);
  		}
  		if (!isRing()) {
  			final GamaPoint v0 = points[0];
  			final GamaPoint v1 = points[1];
  			normal.x += (v0.y - v1.y) * (v0.z + v1.z);
  			normal.y += (v0.z - v1.z) * (v0.x + v1.x);
  			normal.z += (v0.x - v1.x) * (v0.y + v1.y);
  		}
  		final double norm = clockwise ? -normal.norm() : normal.norm();
  		normal.divideBy(norm / factor);
  	}
  
  	@Override
  	public Envelope3D getEnvelopeInto(final Envelope3D envelope) {
  		envelope.setToNull();
  		expandEnvelope(envelope);
  		return envelope;
  	}
  
  	@Override
  	public double averageZ() {
  		double sum = 0d;
  		if (nbPoints == 0) { return sum; }
  		for (int i = 0; i < nbPoints; i++) {
  			sum += points[i].z;
  		}
  		return sum / nbPoints;
  	}
  
  	@Override
  	public ICoordinates setTo(final GamaPoint... points2) {
  		growTo(points2.length);
  		nbPoints = points2.length;
  		for (int i = 0; i < nbPoints; i++) {
  			points[i].setLocation(points2[i]);
  		}
  		return this;
  	}
  
  	@Override
  	public ICoordinates setTo(final double... points2) {
  		growTo(points2.length / 3);
  