/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2005-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.topology;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import org.geotools.geometry.iso.util.algorithm2D.AlgoPoint2D;
/**
* @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 extends BRepFace2D {
protected BRepNode2D[] node;
protected Object[] side;
public abstract int n();
public abstract byte side(int s);
protected Simplex2D(BRepNode2D[] p) {
int n = n();
node = new BRepNode2D[n];
side = new Object[n];
for (int i = 0; i<n; ++i) {
node[i] = p[i];
}
}
public BRepNode2D[] getNodes() {
return node;
}
public BRepNode2D getNode(int s) {
return this.node[s];
}
public Object[] getSides() {
return this.side;
}
public Object getSide(int s) {
return this.side[s];
}
public BRepEdge2D getEdge(int s) {
return (isEdgeSide(s)) ? (BRepEdge2D)side[s] : null;
}
public Simplex2D getSimplex(int s) {
return (isSimplexSide(s)) ? (Simplex2D)side[s] : null;
}
public boolean isEdgeSide(int i) {
return side[i] instanceof BRepEdge2D;
}
public boolean isSimplexSide(int i) {
return side[i] instanceof BRepFace2D;
}
public boolean hasNode(BRepNode2D v0) {
for (int i = 0; i < n(); ++i) {
if (v0 == node[i]) return true;
}
return false;
}
public boolean hasEdge(BRepEdge2D e) {
for (int i = 0; i < n(); ++i) {
if (side[i]==e) return true;
}
return false;
}
public boolean hasFace(BRepFace2D f) {
for (int i = 0, n=n(); i < n; ++i) {
if (this.isEdgeSide(i)) {
if (this.getNeighborFace((BRepEdge2D)side[i])==f) return true;
} else {
if (side[i]==f) return true;
}
}
return false;
}
public int getSide(Point2D p0, Point2D p1) {
byte flag = 0;
for (int i = 0; i < n(); ++i) {
if (p0.equals(node[i])) {
flag |= (1 << i);
break;
}
}
for (int i = 0; i < n(); ++i) {
if (p1.equals(node[i])) {
flag |= (1 << i);
break;
}
}
for (int i = 0; i < n(); ++i)
if (flag == side(i))
return i;
throw new IllegalArgumentException("error on get_side(GenVertex *v0, GenVertex *v1)");
}
public int getSide(BRepEdge2D e) {
return getSide(e.getP1(), e.getP2());
}
public int getSide(BRepFace2D f) {
if ((f==this) || (f==null)) {
throw new IllegalArgumentException("GenSimplex2D f");
}
for (int i = 0; i < n(); ++i) {
if (this.isSimplexSide(i)) {
if (side[i]==f) return i;
} else {
BRepEdge2D e = (BRepEdge2D)side[i];
if ((e != null) && getNeighborFace(e) == f)
return i;
}
}
return -1;
}
public BRepFace2D getNeighborFace(BRepEdge2D e) {
return (e.getSurfaceLeft()==this) ? e.getSurfaceRight() : e.getSurfaceLeft();
}
public BRepNode2D getNextPoint(BRepNode2D v0, BRepNode2D v1) {
// returns the next vertex after v0 and v1
for (int i = 0; i < n(); ++i) {
if (node[i] == v0) {
if (node[(i + 1) % n()] == v1)
return node[(i + 2) % n()];
else if (node[(i + n() - 1) % n()] == v1)
return node[(i + n() - 2) % n()];
else
return null;
}
}
return null;
}
public ArrayList getAllSimpliciesOnSimplex() {
ArrayList result = new ArrayList();
for (int i = 0; i < n(); ++i) {
Simplex2D simplex = getSimplex(i);
if (simplex!=null) result.add(simplex);
}
return result;
}
public ArrayList getAllEdgesOnFace() {
ArrayList result = new ArrayList();
for (int i = 0; i < n(); ++i) {
BRepEdge2D e = getEdge(i);
if (e!=null) result.add(e);
}
return result;
}
public ArrayList getAllPointsOnFace() {
ArrayList result = new ArrayList();
for (int i = 0; i < n(); ++i)
result.add(node[i]);
return result;
}
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.node[s0] == f.node[s1]) {
return -1; // opposite orientation
} else {
return 1; // same orientation
}
}
public Point2D getCentroid() {
Point2D result = new Point2D.Double(this.node[0].getX(),this.node[0].getY());
int n = this.n();
for (int i = 1; i<n; ++i) {
AlgoPoint2D.createAdd(result,node[i]);
}
return AlgoPoint2D.scale(result,1./n);
}
protected void linkSimplex(int s, Simplex2D f) {
side[s]=f;
}
protected void linkEdge(int s, BRepEdge2D e) {
side[s]=e;
}
protected void linkEdge(BRepEdge2D e) {
Point2D p0 = e.getP1();
Point2D p1 = e.getP2();
linkEdge(getSide(p0, p1), e);
}
protected void unlinkEdge(int s, BRepEdge2D e) {
if (getEdge(s) != e) {
throw new IllegalArgumentException("error on unlink_edge");
}
resetSide(s);
}
protected void unlinkEdge(BRepEdge2D e) {
for (int i = 0; i < n(); ++i)
if (side[i]==e) {
resetSide(i);
}
}
protected void swapSide(BRepEdge2D e, Simplex2D f) {
for (int i = 0; i < n(); ++i) {
if (side[i]==e) {
side[i]=f;
return;
}
}
}
private void resetSide(int s) {
this.side[s] = null;
}
}