/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2006-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.elem2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import org.geotools.geometry.iso.util.algorithm2D.AlgoPoint2D; import org.geotools.geometry.iso.util.algorithm2D.AlgoRectangle2D; /** * @author roehrig * * TODO To change the template for this generated type comment go to Window - * Preferences - Java - Code Style - Code Templates * * * * @source $URL$ */ public abstract class Simplex2D { protected Node2D[] point; protected Object[] neighbour; public int id = -1; public Object object = null; protected Simplex2D(Node2D[] p) { this.initialize(); //assert p.length >= n(); for (int i = 0, n=n(); i<n; ++i) { point[i] = p[i]; } } protected Simplex2D(Node2D[] p, int n) { this.initialize(n); //assert p.length >= n; for (int i = 0; i< n; ++i) { point[i] = new Node2D(p[i]); } } // ABSTRACT protected abstract int n(); // ABSTRACT public abstract int sideBits(int s); private void initialize() { point = new Node2D[n()]; neighbour = new Object[n()]; } private void initialize(int n) { point = new Node2D[n]; neighbour = new Object[n()]; } /** * @return Returns the object. */ public Object getObject() { return object; } /** * @param object The object to set. */ public void setObject(Object object) { this.object = object; } public Node2D[] getPoints() { return this.point; } public Node2D getPoint(int n) { // assert(n<=n()); return this.point[n]; } public Node2D[] getPointFromSide(int side) { // assert(n<=n()); return new Node2D[] {this.point[side], this.point[(side+1)%n()]}; } public Object[] getNeighbours() { return this.neighbour; } public Rectangle2D getRectangle() { return AlgoRectangle2D.createRectangle(point); } public void setRectangle(Rectangle2D r) { AlgoRectangle2D.setValues(r,point); } public double getSizeSq() { double sizeSq = Double.MIN_VALUE; for (int i = 0, n = n(); i < n; ++i) { double distSq = this.point[i].distanceSq(this.point[(i+1)%n]); if ( distSq > sizeSq ) sizeSq = distSq; } return sizeSq; } public double getSize() { return Math.sqrt(getSizeSq()); } /** A simplex has at least three points */ boolean hasNeighbour(int side) { return (this.neighbour[side] != null); } boolean hasEdge(Edge2D e) { for (int i = 0, n = n(); i < n; ++i) { if (this.neighbour[i]==e) { return true; } } return false; } public boolean hasPoint(Node2D p) { for (int i = 0, n=n(); i < n; ++i) { if (p == point[i]) { return true; } } return false; } public boolean hasEqualPoint(Point2D p){ for(int i = 0, n = n(); i < n; ++i){ if (p.equals(this.point[i])) return true; } return false; } public int getSide(Point2D p0, Point2D p1) { int flag = 0; int n = n(); for (int i = 0; i < n; ++i) { if (p0.equals(point[i])) { flag |= (1 << i); break; } } for (int i = 0; i < n; ++i) { if (p1.equals(point[i])) { flag |= (1 << i); break; } } for (int i = 0; i < n; ++i) { if (flag == sideBits(i)) { return i; } } return -1; } public int[] getSides(Node2D node) { int n = n(); if (node == this.point[0]) { return new int[] {n-1,0}; } else { for (int i = 1; i < n; ++i) { if (node == this.point[i]) { return new int[] {(i-1)%n,i}; } } } return null; } public int getSide(Edge2D e) { return getSide(e.getP1(), e.getP2()); } public int getSide(Simplex2D f) { if (f != this) { for (int i = 0, n = n(); i < n; ++i) { if (this.neighbour[i]==f) return i; if (this.neighbour[i] instanceof Edge2D) { Edge2D e = (Edge2D)this.neighbour[i]; if (e.hasSimplex(f)) return i; } } } throw new IllegalArgumentException("getSide(Simplex2D f)"); } public Simplex2D getNeighbourSimplex(int side) { if (this.neighbour[side] instanceof Simplex2D) { return (Simplex2D)this.neighbour[side]; } else { Edge2D e = (Edge2D)this.neighbour[side]; return (e==null) ? null : e.getNeighborSimplex(this); } } public Edge2D getNeighbourEdge(int side) { return (this.neighbour[side] instanceof Edge2D) ? (Edge2D)this.neighbour[side] : null; } public Node2D getNextPoint(Point2D p0, Point2D p1) { // returns the next vertex after v0 and v1 for (int i = 0, n = n(); i < n; ++i) { if (point[i] == p0) { if (point[(i + 1) % n] == p1) return point[(i + 2) % n]; else if (point[(i + n - 1) % n] == p1) return point[(i + n - 2) % n]; else return null; } } return null; } protected void linkSimplex(int side, Simplex2D s) { this.neighbour[side] = s; } protected boolean linkSimplex(Simplex2D other) { for (int thisSide = 0, thisN = this.n(); thisSide < thisN; ++thisSide) { for (int otherSide = 0, otherN = other.n(); otherSide < otherN; ++otherSide) { if ( (this.point[thisSide]==other.point[otherSide] && this.point[(thisSide+1)%thisN]==other.point[(otherSide+1)%otherN]) || (this.point[thisSide]==other.point[(otherSide+1)%otherN] && this.point[(thisSide+1)%thisN]==other.point[otherSide]) ) { this.neighbour[thisSide] = other; other.neighbour[otherSide] = this; return true; } } } return false; } protected void linkEdge(int side, Edge2D e) { this.neighbour[side] = e; } protected void linkEdge(Edge2D e) { linkEdge(getSide(e.getP1(), e.getP2()), e); } protected void unlinkEdge(int side, Edge2D e) { if (this.neighbour[side] != e) { throw new IllegalArgumentException("error on unlink_edge"); } this.neighbour[side] = null; } protected void unlinkEdge(Edge2D e) { for (int i = 0, n = n(); i < n; ++i) if (this.neighbour[i] == e) { this.neighbour[i] = null; return; } } protected void swapSide(Edge2D e, Simplex2D f) { for (int i = 0; i < n(); ++i) { if (this.neighbour[i] == e) { this.neighbour[i] = f; } } } public ArrayList<Simplex2D> getAllSimpliciesOnSimplex() { int n = n(); ArrayList<Simplex2D> result = new ArrayList<Simplex2D>(n); for (int i = 0; i < n; ++i) { Simplex2D s = this.getNeighbourSimplex(i); if (s != null) result.add(s); } return result; } public ArrayList<Edge2D> getAllEdgesOnFace() { int n = n(); ArrayList<Edge2D> result = new ArrayList<Edge2D>(n); for (int i = 0; i < n; ++i) { Edge2D e = this.getNeighbourEdge(i); if (e != null) result.add(e); } return result; } public ArrayList<Node2D> getAllPointsOnFace() { int n = n(); ArrayList<Node2D> result = new ArrayList<Node2D>(n); for (int i = 0; i < n; ++i) { result.add(point[i]); } return result; } public int getOrientation(Node2D n0, Node2D n1) { for (int i=0, n=n(); i<n; ++i) { if (point[i]==n0 && point[(i+1)%n]==n1) { return 1; } else if (point[i]==n1 && point[(i+1)%n]==n0) { return -1; } } return 0; } public int getOrientation(int s0, int s1) { return (s0 < s1 || (s0 == n() && s1 == 0)) ? 1 : -1; } public int getOrientation(Simplex2D f0, Simplex2D f1) { // get the orientation of the neighbors f0 and f1 w.r.t the // orientation of this Simplex2D. 1 for same, -1 for opposite and 0 for error int s0 = getSide(f0); int s1 = getSide(f1); if ((s0 == -1) || (s1 == -1)) { throw new IllegalArgumentException("error on get_side(GenVertex *v0, GenVertex *v1)"); } return getOrientation(s0, s1); } public int getOrientation(Simplex2D f) { // return 1 for same, -1 for opposite orientation and 0 for error int s0 = this.getSide(f); int s1 = f.getSide(this); if (s0 == -1 || s1 == -1) return 0; if (this.point[s0] == f.point[s1]) { return -1; // opposite orientation } else { return 1; // same orientation } } public Point2D getCentroid() { Point2D result = new Point2D.Double(0.0,0.0); int n = this.n(); for (int i = 0; i<n; ++i) { AlgoPoint2D.add(result,point[i]); } return AlgoPoint2D.scale(result,1./n); } /** * @return */ public boolean hasID() { return id!=-1; } }