/deps/hemesh2010/src/wblut/hemesh/core/HE_Mesh.java
Java | 4265 lines | 3100 code | 319 blank | 846 comment | 640 complexity | 13eb13e1bb95916b982e725eaa14315f MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (c) 2010, Frederik Vanhoutte 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; either version
- * 2.1 of the License, or (at your option) any later version.
- * http://creativecommons.org/licenses/LGPL/2.1/ 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. You should have
- * received a copy of the GNU Lesser General Public License along with this
- * library; if not, write to the Free Software Foundation, Inc., 51 Franklin St,
- * Fifth Floor, Boston, MA 02110-1301 USA
- */
- package wblut.hemesh.core;
-
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
-
- import javolution.util.FastList;
- import javolution.util.FastMap;
- import javolution.util.FastTable;
- import wblut.frame.WB_Frame;
- import wblut.geom.WB_AABB;
- import wblut.geom.WB_ClassifyPointToPlane;
- import wblut.geom.WB_ClosestPoint;
- import wblut.geom.WB_Distance;
- import wblut.geom.WB_ExplicitPolygon;
- import wblut.geom.WB_ExplicitSegment;
- import wblut.geom.WB_IndexedSegment;
- import wblut.geom.WB_IndexedTriangle;
- import wblut.geom.WB_Intersection;
- import wblut.geom.WB_IntersectionResult;
- import wblut.geom.WB_Normal;
- import wblut.geom.WB_Plane;
- import wblut.geom.WB_Point;
- import wblut.geom.WB_Ray;
- import wblut.geom.WB_Transform;
- import wblut.geom.WB_Vector;
- import wblut.geom.WB_XYZ;
- import wblut.geom2D.WB_IndexedTriangle2D;
- import wblut.geom2D.WB_PolygonType2D;
- import wblut.hemesh.creators.HEC_Creator;
- import wblut.hemesh.modifiers.HEM_Modifier;
- import wblut.hemesh.options.HE_CycleOption;
- import wblut.hemesh.subdividors.HES_Subdividor;
- import wblut.math.WB_Epsilon;
- import wblut.tree.WB_KDNeighbor;
- import wblut.tree.WB_KDTree;
-
- /**
- * Half-edge mesh data structure.
- *
- * @author Frederik Vanhoutte (W:Blut)
- *
- */
- public class HE_Mesh extends HE_MeshStructure {
-
- /** Stored mesh center. */
- private WB_Point _center;
-
- /** Status of mesh center. */
- private boolean _centerUpdated;
-
- /** General purpose label. */
- protected int label;
-
- /**
- * Instantiates a new HE_Mesh.
- *
- */
- public HE_Mesh() {
- super();
- _center = new WB_Point();
- _centerUpdated = false;
- label = -1;
- }
-
- public void setLabel(final int lab) {
- label = lab;
-
- }
-
- public int getLabel() {
- return label;
-
- }
-
- // CREATE
-
- /**
- * Constructor.
- *
- * @param creator
- * HE_Creator that generates this mesh
- */
- public HE_Mesh(final HEC_Creator creator) {
- super();
- setNoCopy(creator.create());
- _centerUpdated = false;
- label = -1;
- }
-
- // MODIFY
-
- /**
- * Modify the mesh.
- *
- * @param modifier
- * HE_Modifier to apply
- * @return self
- */
- public HE_Mesh modify(final HEM_Modifier modifier) {
- return modifier.apply(this);
- }
-
- /**
- * Modify selection. Elements should be part of this mesh.
- *
- * @param modifier
- * HE_Modifier to apply
- * @return self
- */
- public HE_Mesh modifySelected(final HEM_Modifier modifier,
- final HE_Selection selection) {
- return modifier.apply(selection.get());
- }
-
- // SUBDIVIDE
-
- /**
- * Subdivide the mesh.
- *
- * @param subdividor
- * HE_Subdividor to apply
- * @return self
- */
- public HE_Mesh subdivide(final HES_Subdividor subdividor) {
- return subdividor.apply(this);
- }
-
- /**
- * Subdivide selection of the mesh.
- *
- * @param subdividor
- * HE_Subdividor to apply
- * @param selection
- * HE_Selection
- * @return self
- */
- public HE_Mesh subdivideSelected(final HES_Subdividor subdividor,
- final HE_Selection selection) {
- return subdividor.apply(selection);
-
- }
-
- /**
- * Subdivide the mesh a number of times.
- *
- * @param subdividor HE_Subdividor to apply
- * @param rep subdivision iterations. WARNING: higher values will lead to
- * unmanageable number of faces.
- * @return self
- */
- public HE_Mesh subdivide(final HES_Subdividor subdividor, final int rep) {
- for (int i = 0; i < rep; i++) {
- subdivide(subdividor);
- }
- return this;
- }
-
- /**
- * Subdivide a selection of the mesh a number of times.
- *
- * @param subdividor
- * HE_Subdividor to apply
- * @param selection
- * HE_Selection initial selection
- * @param rep subdivision iterations
- * @return self
- */
- public HE_Mesh subdivideSelected(final HES_Subdividor subdividor,
- final HE_Selection selection, final int rep) {
- for (int i = 0; i < rep; i++) {
- subdivideSelected(subdividor, selection);
- }
- return this;
-
- }
-
- /**
- * Deep copy of mesh.
- *
- * @return copy as new HE_Mesh, includes selection
- */
- public HE_Mesh get() {
- final HE_Mesh result = new HE_Mesh();
- final HashMap<Integer, Integer> vertexCorrelation = new HashMap<Integer, Integer>();
- final HashMap<Integer, Integer> faceCorrelation = new HashMap<Integer, Integer>();
- final HashMap<Integer, Integer> halfedgeCorrelation = new HashMap<Integer, Integer>();
- final HashMap<Integer, Integer> edgeCorrelation = new HashMap<Integer, Integer>();
- HE_Vertex rv;
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- v = vItr.next();
- rv = new HE_Vertex();
- result.add(rv);
- vertexCorrelation.put(v.key(), rv.key());
- }
- HE_Face rf;
- HE_Face f;
- final Iterator<HE_Face> fItr = fItr();
- while (fItr.hasNext()) {
- f = fItr.next();
- rf = new HE_Face();
- result.add(rf);
- rf.label = f.label;
- faceCorrelation.put(f.key(), rf.key());
- }
- HE_Halfedge rhe;
- HE_Halfedge he;
- final Iterator<HE_Halfedge> heItr = heItr();
- while (heItr.hasNext()) {
- he = heItr.next();
- rhe = new HE_Halfedge();
- result.add(rhe);
- halfedgeCorrelation.put(he.key(), rhe.key());
- }
-
- HE_Edge re;
- final Iterator<HE_Edge> eItr = eItr();
- HE_Edge e;
- while (eItr.hasNext()) {
- e = eItr.next();
- re = new HE_Edge();
- result.add(re);
- edgeCorrelation.put(e.key(), re.key());
-
- }
-
- HE_Vertex sv;
- HE_Vertex tv;
- final Iterator<HE_Vertex> svItr = vItr();
- final Iterator<HE_Vertex> tvItr = result.vItr();
- Integer key;
- while (svItr.hasNext()) {
- sv = svItr.next();
- tv = tvItr.next();
- tv.set(sv);
- if (sv.getHalfedge() != null) {
- key = halfedgeCorrelation.get(sv.getHalfedge().key());
- tv.setHalfedge(result.getHalfedgeByKey(key));
- }
- }
-
- HE_Face sf;
- HE_Face tf;
-
- final Iterator<HE_Face> sfItr = fItr();
- final Iterator<HE_Face> tfItr = result.fItr();
- while (sfItr.hasNext()) {
- sf = sfItr.next();
- tf = tfItr.next();
- if (sf.getHalfedge() != null) {
- key = halfedgeCorrelation.get(sf.getHalfedge().key());
- tf.setHalfedge(result.getHalfedgeByKey(key));
- }
-
- }
-
- final Iterator<HE_Edge> seItr = eItr();
- final Iterator<HE_Edge> teItr = result.eItr();
- HE_Edge se;
- HE_Edge te;
- while (seItr.hasNext()) {
- se = seItr.next();
- te = teItr.next();
- if (se.getHalfedge() != null) {
- key = halfedgeCorrelation.get(se.getHalfedge().key());
- te.setHalfedge(result.getHalfedgeByKey(key));
- }
-
- }
- HE_Halfedge she;
- HE_Halfedge the;
-
- final Iterator<HE_Halfedge> sheItr = heItr();
- final Iterator<HE_Halfedge> theItr = result.heItr();
- while (sheItr.hasNext()) {
- she = sheItr.next();
- the = theItr.next();
- if (she.getPair() != null) {
- key = halfedgeCorrelation.get(she.getPair().key());
- the.setPair(result.getHalfedgeByKey(key));
- }
- if (she.getNextInFace() != null) {
- key = halfedgeCorrelation.get(she.getNextInFace().key());
- the.setNext(result.getHalfedgeByKey(key));
- }
- if (she.getVertex() != null) {
- key = vertexCorrelation.get(she.getVertex().key());
- the.setVertex(result.getVertexByKey(key));
- }
- if (she.getFace() != null) {
- key = faceCorrelation.get(she.getFace().key());
- the.setFace(result.getFaceByKey(key));
- }
-
- if (she.getEdge() != null) {
- key = edgeCorrelation.get(she.getEdge().key());
- the.setEdge(result.getEdgeByKey(key));
- }
- }
- result._center.set(_center);
- result._centerUpdated = _centerUpdated;
- return result;
- }
-
- /**
- * Add all mesh elements to this mesh. No copies are made.
- *
- * @param mesh mesh to add
- */
- public void add(final HE_Mesh mesh) {
- addVertices(mesh.getVerticesAsArray());
- addFaces(mesh.getFacesAsArray());
- addEdges(mesh.getEdgesAsArray());
- addHalfedges(mesh.getHalfedgesAsArray());
-
- }
-
- /**
- * Replace mesh with deep copy of target.
- *
- * @param target
- * HE_Mesh to be duplicated
- */
- public void set(final HE_Mesh target) {
- final HE_Mesh result = target.get();
- replaceVertices(result.getVerticesAsArray());
- replaceFaces(result.getFacesAsArray());
- replaceHalfedges(result.getHalfedgesAsArray());
- replaceEdges(result.getEdgesAsArray());
-
- }
-
- /**
- * Replace mesh with shallow copy of target.
- *
- * @param target
- * HE_Mesh to be duplicated
- */
- private void setNoCopy(final HE_Mesh target) {
- _hashedVertices = target._hashedVertices;
- _hashedHalfedges = target._hashedHalfedges;
- _hashedEdges = target._hashedEdges;
- _hashedFaces = target._hashedFaces;
-
- _center = target._center;
- _centerUpdated = target._centerUpdated;
-
- }
-
- // CONVERT
-
- /**
- * Return all vertex positions as an array .
- *
- * @return 2D array of float. First index gives vertex. Second index gives
- * x-,y- or z-coordinate.
- */
- public float[][] getVerticesAsFloat() {
- final float[][] result = new float[numberOfVertices()][3];
- int i = 0;
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- v = vItr.next();
- result[i][0] = (float) (v.x);
- result[i][1] = (float) (v.y);
- result[i][2] = (float) (v.z);
- i++;
- }
- return result;
- }
-
- /**
- * Return all vertex positions as an array .
- *
- * @return 2D array of double. First index gives vertex. Second index gives
- * x-,y- or z-coordinate.
- */
- public double[][] getVerticesAsDouble() {
- final double[][] result = new double[numberOfVertices()][3];
- int i = 0;
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- v = vItr.next();
- result[i][0] = (float) (v.x);
- result[i][1] = (float) (v.y);
- result[i][2] = (float) (v.z);
- i++;
- }
- return result;
- }
-
- public HashMap<Integer, Integer> vertexKeyToIndex() {
- final HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
- int i = 0;
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- map.put(vItr.next().key(), i);
- i++;
- }
- return map;
- }
-
- /**
- * Return all vertex positions.
- *
- * @return array of WB_Point, values are copied.
- */
- public WB_Point[] getVerticesAsNewPoint() {
- final WB_Point[] result = new WB_Point[numberOfVertices()];
- int i = 0;
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- v = vItr.next();
- result[i] = new WB_Point(v);
- i++;
- }
- return result;
- }
-
- /**
- * Return all vertex positions.
- *
- * @return array of WB_Point, no copies are made.
- */
- public WB_Point[] getVerticesAsPoint() {
- final WB_Point[] result = new WB_Point[numberOfVertices()];
- int i = 0;
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- v = vItr.next();
- result[i] = v;
- i++;
- }
- return result;
- }
-
- /**
- * Return all vertex normal.
- *
- * @return array of WB_Normal.
- */
- public WB_Normal[] getVertexNormals() {
- final WB_Normal[] result = new WB_Normal[numberOfVertices()];
- int i = 0;
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- v = vItr.next();
- result[i] = v.getVertexNormal();
- i++;
- }
- return result;
- }
-
- /**
- * Return all vertex normal.
- *
- * @return FastMap of WB_Normal.
- */
- public FastMap<Integer, WB_Normal> getKeyedVertexNormals() {
- final FastMap<Integer, WB_Normal> result = new FastMap<Integer, WB_Normal>(
- numberOfVertices());
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- v = vItr.next();
- result.put(v.key(), v.getVertexNormal());
- }
- return result;
- }
-
- /**
- * Return the faces as array of vertex indices.
- *
- * @return 2D array of int. First index gives face. Second index gives
- * vertices.
- */
- public int[][] getFacesAsInt() {
- final int[][] result = new int[numberOfFaces()][];
- final FastMap<Integer, Integer> vertexKeys = new FastMap<Integer, Integer>();
- final Iterator<HE_Vertex> vItr = vItr();
- int i = 0;
- while (vItr.hasNext()) {
- vertexKeys.put(vItr.next().key(), i);
- i++;
- }
-
- final Iterator<HE_Face> fItr = fItr();
- HE_Halfedge he;
- HE_Face f;
- i = 0;
- while (fItr.hasNext()) {
- f = fItr.next();
- result[i] = new int[f.getFaceOrder()];
- he = f.getHalfedge();
- int j = 0;
- do {
- result[i][j] = vertexKeys.get(he.getVertex().key());
- he = he.getNextInFace();
- j++;
- } while (he != f.getHalfedge());
- i++;
- }
- return result;
- }
-
- /**
- * Return all face normals.
- *
- * @return array of WB_Normal.
- */
- public WB_Normal[] getFaceNormals() {
- final WB_Normal[] result = new WB_Normal[numberOfFaces()];
- int i = 0;
- HE_Face f;
- final Iterator<HE_Face> fItr = fItr();
- while (fItr.hasNext()) {
- f = fItr.next();
- result[i] = f.getFaceNormal();
- i++;
- }
- return result;
- }
-
- /**
- * Return all face normals.
- *
- * @return FastMap of WB_Normal.
- */
- public FastMap<Integer, WB_Normal> getKeyedFaceNormals() {
- final FastMap<Integer, WB_Normal> result = new FastMap<Integer, WB_Normal>(
- numberOfFaces());
- HE_Face f;
- final Iterator<HE_Face> fItr = fItr();
- while (fItr.hasNext()) {
- f = fItr.next();
- result.put(f.key(), f.getFaceNormal());
- }
- return result;
- }
-
- /**
- * Return all face centers.
- *
- * @return array of WB_Point.
- */
- public WB_Point[] getFaceCenters() {
- final WB_Point[] result = new WB_Point[numberOfFaces()];
- int i = 0;
- HE_Face f;
- final Iterator<HE_Face> fItr = fItr();
- while (fItr.hasNext()) {
- f = fItr.next();
- result[i] = f.getFaceCenter();
- i++;
- }
- return result;
- }
-
- /**
- * Return all face centers.
- *
- * @return FastMap of WB_Point.
- */
- public FastMap<Integer, WB_Point> getKeyedFaceCenters() {
- final FastMap<Integer, WB_Point> result = new FastMap<Integer, WB_Point>(
- numberOfFaces());
- HE_Face f;
- final Iterator<HE_Face> fItr = fItr();
- while (fItr.hasNext()) {
- f = fItr.next();
- result.put(f.key(), f.getFaceCenter());
- }
- return result;
- }
-
- /**
- * Return all edge normals.
- *
- * @return array of WB_Normal.
- */
- public WB_Normal[] getEdgeNormals() {
- final WB_Normal[] result = new WB_Normal[numberOfEdges()];
- int i = 0;
- HE_Edge e;
- final Iterator<HE_Edge> eItr = eItr();
- while (eItr.hasNext()) {
- e = eItr.next();
- result[i] = e.getEdgeNormal();
- i++;
- }
- return result;
- }
-
- /**
- * Return all edge normals.
- *
- * @return FastMap of WB_Normal.
- */
- public FastMap<Integer, WB_Normal> getKeyedEdgeNormals() {
- final FastMap<Integer, WB_Normal> result = new FastMap<Integer, WB_Normal>(
- numberOfEdges());
- HE_Edge e;
- final Iterator<HE_Edge> eItr = eItr();
- while (eItr.hasNext()) {
- e = eItr.next();
- result.put(e.key(), e.getEdgeNormal());
- }
- return result;
- }
-
- /**
- * Return all edge centers.
- *
- * @return array of WB_Point.
- */
- public WB_Point[] getEdgeCenters() {
- final WB_Point[] result = new WB_Point[numberOfEdges()];
- int i = 0;
- HE_Edge e;
- final Iterator<HE_Edge> eItr = eItr();
- while (eItr.hasNext()) {
- e = eItr.next();
- result[i] = e.getEdgeCenter();
- i++;
- }
- return result;
- }
-
- /**
- * Return all edge centers.
- *
- * @return FastMap of WB_Point.
- */
- public FastMap<Integer, WB_Point> getKeyedEdgeCenters() {
- final FastMap<Integer, WB_Point> result = new FastMap<Integer, WB_Point>(
- numberOfEdges());
- HE_Edge e;
- final Iterator<HE_Edge> eItr = eItr();
- while (eItr.hasNext()) {
- e = eItr.next();
- result.put(e.key(), e.getEdgeCenter());
- }
- return result;
- }
-
- /**
- * Set vertex positions to values in array.
- *
- * @param values 2D array of float. First index is number of vertices, second
- * index is 3 (x-,y- and z-coordinate)
- */
- public void setVerticesFromFloat(final float[][] values) {
- int i = 0;
- _center.set(0, 0, 0);
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- v = vItr.next();
- v.set(values[i][0], values[i][1], values[i][2]);
- i++;
- }
-
- }
-
- /**
- * Set vertex positions to values in array.
- *
- * @param values array of WB_Point.
- */
- public void setVerticesFromPoint(final WB_Point[] values) {
- int i = 0;
- _center.set(0, 0, 0);
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- v = vItr.next();
- v.set(values[i]);
- i++;
- }
- ;
- }
-
- /**
- * Set vertex positions to values in array.
- *
- * @param values 2D array of double. First index is number of vertices, second
- * index is 3 (x-,y- and z-coordinate)
- */
- public void setVerticesFromDouble(final double[][] values) {
- int i = 0;
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- v = vItr.next();
- v.set(values[i][0], values[i][1], values[i][2]);
- i++;
-
- }
- ;
- }
-
- /**
- * Set vertex positions to values in array.
- *
- * @param values 2D array of int. First index is number of vertices, second
- * index is 3 (x-,y- and z-coordinate)
- */
- public void setVerticesFromInt(final int[][] values) {
- int i = 0;
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- v = vItr.next();
- v.set(values[i][0], values[i][1], values[i][2]);
- i++;
-
- }
- ;
- }
-
- /**
- * Return the mesh as polygon soup.
- *
- * @return array of WB_polygon
- *
- */
-
- public WB_ExplicitPolygon[] getPolygons() {
- final WB_ExplicitPolygon[] result = new WB_ExplicitPolygon[numberOfFaces()];
- final Iterator<HE_Face> fItr = fItr();
- HE_Face f;
- int i = 0;
- while (fItr.hasNext()) {
- f = fItr.next();
- result[i] = f.toPolygon();
- i++;
- }
- return result;
- }
-
- public ArrayList<WB_ExplicitPolygon> getPolygonArrayList() {
- final ArrayList<WB_ExplicitPolygon> result = new ArrayList<WB_ExplicitPolygon>();
- final Iterator<HE_Face> fItr = fItr();
- HE_Face f;
- while (fItr.hasNext()) {
- f = fItr.next();
- result.add(f.toPolygon());
- }
- return result;
- }
-
- public WB_ExplicitSegment[] getSegments() {
- final WB_ExplicitSegment[] result = new WB_ExplicitSegment[numberOfEdges()];
- final Iterator<HE_Edge> eItr = eItr();
- HE_Edge e;
- int i = 0;
- while (eItr.hasNext()) {
- e = eItr.next();
- result[i] = new WB_ExplicitSegment(e.getStartVertex(),
- e.getEndVertex(), false);
- i++;
- }
- return result;
- }
-
- public WB_IndexedSegment[] getIndexedSegments() {
- final WB_IndexedSegment[] result = new WB_IndexedSegment[numberOfEdges()];
- final WB_Point[] points = getVerticesAsPoint();
- final FastMap<Integer, Integer> map = new FastMap<Integer, Integer>();
- map.putAll(vertexKeyToIndex());
- final Iterator<HE_Edge> eItr = eItr();
- HE_Edge e;
- int i = 0;
- while (eItr.hasNext()) {
- e = eItr.next();
- result[i] = new WB_IndexedSegment(
- map.get(e.getStartVertex().key()), map.get(e.getEndVertex()
- .key()), points);
- i++;
- }
- return result;
- }
-
- public WB_Frame getFrame() {
- final WB_Frame frame = new WB_Frame(getVerticesAsPoint());
- final FastMap<Integer, Integer> map = new FastMap<Integer, Integer>();
- map.putAll(vertexKeyToIndex());
- final Iterator<HE_Edge> eItr = eItr();
- HE_Edge e;
- while (eItr.hasNext()) {
- e = eItr.next();
- frame.addStrut(map.get(e.getStartVertex().key()),
- map.get(e.getEndVertex().key()));
- }
-
- return frame;
-
- }
-
- // TRANSFORM
- /**
- * Apply transform to entire mesh.
- *
- * @param T WB_Transform to apply
-
- * @return self
- */
- public HE_Mesh transform(final WB_Transform T) {
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- T.apply(vItr.next());
- }
- return this;
- }
-
- /**
- * Translate entire mesh.
- *
- * @param x the x
- * @param y the y
- * @param z the z
- * @return self
- */
- public HE_Mesh move(final double x, final double y, final double z) {
- _center.add(x, y, z);
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- vItr.next().add(x, y, z);
- }
- return this;
- }
-
- /**
- * Translate entire mesh.
- *
- * @param v
- * @return self
- */
- public HE_Mesh move(final WB_XYZ v) {
- return move(v.x, v.y, v.z);
- }
-
- /**
- * Translate entire mesh to given position.
- *
- * @param x
- * @param y
- * @param z
- * @return self
- */
- public HE_Mesh moveTo(final double x, final double y, final double z) {
- if (!_centerUpdated) {
- getCenter();
- }
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- vItr.next().add(x - _center.x, y - _center.y, z - _center.z);
- }
- _center.set(x, y, z);
- return this;
- }
-
- /**
- * Translate entire mesh to given position.
- *
- * @param v the v
- * @return self
- */
- public HE_Mesh moveTo(final WB_Point v) {
- return moveTo(v.x, v.y, v.z);
- }
-
- /**
- * Rotate entire mesh around an arbitrary axis.
- *
- * @param angle angle
- * @param p1x x-coordinate of first point on axis
- * @param p1y y-coordinate of first point on axis
- * @param p1z z-coordinate of first point on axis
- * @param p2x x-coordinate of second point on axis
- * @param p2y y-coordinate of second point on axis
- * @param p2z z-coordinate of second point on axis
- * @return self
- */
- public HE_Mesh rotateAboutAxis(final double angle, final double p1x,
- final double p1y, final double p1z, final double p2x,
- final double p2y, final double p2z) {
- if (!_centerUpdated) {
- getCenter();
- }
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- final WB_Transform raa = new WB_Transform();
- raa.addRotateAboutAxis(angle, new WB_Point(p1x, p1y, p1z),
- new WB_Vector(p2x - p1x, p2y - p1y, p2z - p1z));
- while (vItr.hasNext()) {
- v = vItr.next();
- raa.applyInto(v, v);
- }
- raa.applyInto(_center, _center);
- ;
- return this;
- }
-
- /**
- * Rotate entire mesh around an arbitrary axis.
- *
- * @param angle angle
- * @param p1 first point on axis
- * @param p2 second point on axis
- * @return self
- */
- public HE_Mesh rotateAboutAxis(final double angle, final WB_Point p1,
- final WB_Point p2) {
- if (!_centerUpdated) {
- getCenter();
- }
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- final WB_Transform raa = new WB_Transform();
- raa.addRotateAboutAxis(angle, p1, p2.subToVector(p1));
- while (vItr.hasNext()) {
- v = vItr.next();
- raa.applyInto(v, v);
- }
- raa.applyInto(_center, _center);
- ;
- return this;
- }
-
- /**
- * Rotate entire mesh around an arbitrary axis.
- *
- * @param angle angle
- * @param p rotation point
- * @param a axis
- * @return self
- */
- public HE_Mesh rotateAboutAxis(final double angle, final WB_Point p,
- final WB_Vector a) {
- if (!_centerUpdated) {
- getCenter();
- }
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- final WB_Transform raa = new WB_Transform();
- raa.addRotateAboutAxis(angle, p, a);
- while (vItr.hasNext()) {
- v = vItr.next();
- raa.applyInto(v, v);
- }
- raa.applyInto(_center, _center);
- ;
- return this;
- }
-
- /**
- * Rotate entire mesh around an arbitrary axis.
- *
- * @param angle angle
- * @param p rotation point
- * @param a axis
- * @return self
- */
- public HE_Mesh rotateAboutAxis(final double angle, final WB_Point p,
- final WB_Normal a) {
- if (!_centerUpdated) {
- getCenter();
- }
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- final WB_Transform raa = new WB_Transform();
- raa.addRotateAboutAxis(angle, p, a);
- while (vItr.hasNext()) {
- v = vItr.next();
- raa.applyInto(v, v);
- }
- raa.applyInto(_center, _center);
- ;
- return this;
- }
-
- /**
- * Scale entire mesh around center point.
- *
- * @param scaleFactorx
- * x-coordinate of scale factor
- * @param scaleFactory
- * y-coordinate of scale factor
- * @param scaleFactorz
- * z-coordinate of scale factor
- * @param c
- * center
- * @return self
- */
- public HE_Mesh scale(final double scaleFactorx, final double scaleFactory,
- final double scaleFactorz, final WB_Point c) {
- if (!_centerUpdated) {
- getCenter();
- }
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- v = vItr.next();
- v.set(c.x + scaleFactorx * (v.x - c.x), c.y + scaleFactory
- * (v.y - c.y), c.z + scaleFactorz * (v.z - c.z));
- }
- _center.set(c.x + scaleFactorx * (-c.x + _center.x), c.y + scaleFactory
- * (-c.y + _center.y), c.z + scaleFactorz * (-c.z + _center.z));
- ;
- return this;
- }
-
- /**
- * Scale entire mesh around center point.
- *
- * @param scaleFactor
- * scale
- * @param c
- * center
- * @return self
- */
- public HE_Mesh scale(final double scaleFactor, final WB_Point c) {
- return scale(scaleFactor, scaleFactor, scaleFactor, c);
- }
-
- /**
- * Scale entire mesh around bodycenter.
- *
- * @param scaleFactorx
- * x-coordinate of scale factor
- * @param scaleFactory
- * y-coordinate of scale factor
- * @param scaleFactorz
- * z-coordinate of scale factor
- * @return self
- */
- public HE_Mesh scale(final double scaleFactorx, final double scaleFactory,
- final double scaleFactorz) {
- if (!_centerUpdated) {
- getCenter();
- }
- HE_Vertex v;
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- v = vItr.next();
- v.set(_center.x + scaleFactorx * (v.x - _center.x), _center.y
- + scaleFactory * (v.y - _center.y), _center.z
- + scaleFactorz * (v.z - _center.z));
- }
- ;
- return this;
- }
-
- /**
- * Scale entire mesh around bodycenter.
- *
- * @param scaleFactor
- * scale
- * @return self
- */
- public HE_Mesh scale(final double scaleFactor) {
- return scale(scaleFactor, scaleFactor, scaleFactor);
- }
-
- // DERIVED ELEMENTS
-
- /**
- * Get the center (average of all vertex positions).
- *
- * @return the center
- */
- public WB_Point getCenter() {
- if (_centerUpdated) {
- return _center;
- } else {
- resetCenter();
- return _center;
- }
- }
-
- /**
- * Reset the center to the average of all vertex positions).
- *
- */
- public void resetCenter() {
- _center.set(0, 0, 0);
- final Iterator<HE_Vertex> vItr = vItr();
- while (vItr.hasNext()) {
- _center.add(vItr.next());
- }
- _center.div(numberOfVertices());
- _centerUpdated = true;
-
- }
-
- // HELPERS
-
- /**
- * Assign face to halfedge loop.
- *
- * @param face face
- * @param halfedge halfedge loop
- */
- protected static void assignFaceToLoop(final HE_Face face,
- final HE_Halfedge halfedge) {
- HE_Halfedge he = halfedge;
- do {
- he.setFace(face);
- he = he.getNextInFace();
- } while (he != halfedge);
- }
-
- /**
- * Cycle halfedges.
- *
- * @param halfedges halfedges to cycle
- * @param cycle HE_CycleOption.NORMAL, HE_CycleOption.REVERSE
- */
- public static void cycleHalfedges(final List<HE_Halfedge> halfedges,
- final HE_CycleOption cycle) {
- HE_Halfedge he;
- final int n = halfedges.size();
- if (n > 0) {
- if (cycle == HE_CycleOption.NORMAL) {
- for (int j = 0; j < n - 1; j++) {
- he = halfedges.get(j);
- he.setNext(halfedges.get(j + 1));
- }
- he = halfedges.get(n - 1);
- he.setNext(halfedges.get(0));
- } else {
- he = halfedges.get(0);
- he.setNext(halfedges.get(n - 1));
- for (int j = 1; j < n; j++) {
- he = halfedges.get(j);
- he.setNext(halfedges.get(j - 1));
- }
- }
- }
- }
-
- /**
- * Collect all unpaired halfedges.
- *
- * @return the unpaired halfedges
- */
- public ArrayList<HE_Halfedge> getUnpairedHalfedges() {
- final ArrayList<HE_Halfedge> unpairedHalfedges = new ArrayList<HE_Halfedge>();
- HE_Halfedge he;
- final Iterator<HE_Halfedge> heItr = heItr();
- while (heItr.hasNext()) {
- he = heItr.next();
- if (he.getPair() == null) {
- unpairedHalfedges.add(he);
- }
- }
- return unpairedHalfedges;
- }
-
- /**
- * Collect all boundary halfedges.
- *
- * @return boundary halfedges
- */
- public ArrayList<HE_Halfedge> getBoundaryHalfedges() {
- final ArrayList<HE_Halfedge> boundaryHalfedges = new ArrayList<HE_Halfedge>();
- HE_Halfedge he;
- final Iterator<HE_Halfedge> heItr = heItr();
- while (heItr.hasNext()) {
- he = heItr.next();
- if (he.getFace() == null) {
- boundaryHalfedges.add(he);
- }
- }
- return boundaryHalfedges;
- }
-
- /**
- * Try to pair all unpaired halfedges.
- */
- public void pairHalfedges() {
- class VertexInfo {
- FastList<HE_Halfedge> out;
- FastList<HE_Halfedge> in;
-
- VertexInfo() {
- out = new FastList<HE_Halfedge>();
- in = new FastList<HE_Halfedge>();
- }
-
- }
-
- final FastMap<Integer, VertexInfo> vertexLists = new FastMap<Integer, VertexInfo>();
-
- final ArrayList<HE_Halfedge> unpairedHalfedges = getUnpairedHalfedges();
- HE_Vertex v;
- VertexInfo vi;
- System.out.println("HE_Mesh : collating " + unpairedHalfedges.size()
- + " unpaired halfedges per vertex.");
- for (final HE_Halfedge he : unpairedHalfedges) {
- v = he.getVertex();
- vi = vertexLists.get(v.key());
- if (vi == null) {
- vi = new VertexInfo();
-
- vertexLists.put(v.key(), vi);
- }
- vi.out.add(he);
- v = he.getNextInFace().getVertex();
- vi = vertexLists.get(v.key());
- if (vi == null) {
- vi = new VertexInfo();
- vertexLists.put(v.key(), vi);
-
- }
- vi.in.add(he);
- }
- HE_Halfedge he;
- HE_Halfedge he2;
- HE_Edge e;
- System.out.println("HE_Mesh : pairing unpaired halfedges per vertex.");
- for (final VertexInfo vInfo : vertexLists.values()) {
- for (int i = 0; i < vInfo.out.size(); i++) {
- he = vInfo.out.get(i);
- if (he.getPair() == null) {
- for (int j = 0; j < vInfo.in.size(); j++) {
- he2 = vInfo.in.get(j);
- if ((he2.getPair() == null)
- && (he.getVertex() == he2.getNextInFace()
- .getVertex())
- && (he2.getVertex() == he.getNextInFace()
- .getVertex())) {
- he.setPair(he2);
- e = new HE_Edge();
- e.setHalfedge(he);
- he.setEdge(e);
- he2.setEdge(e);
- add(e);
- break;
-
- }
- }
- }
- }
- }
-
- }
-
- public void pairHalfedgesSilent() {
- class VertexInfo {
- FastList<HE_Halfedge> out;
- FastList<HE_Halfedge> in;
-
- VertexInfo() {
- out = new FastList<HE_Halfedge>();
- in = new FastList<HE_Halfedge>();
- }
-
- }
-
- final FastMap<Integer, VertexInfo> vertexLists = new FastMap<Integer, VertexInfo>();
-
- final ArrayList<HE_Halfedge> unpairedHalfedges = getUnpairedHalfedges();
- HE_Vertex v;
- VertexInfo vi;
- for (final HE_Halfedge he : unpairedHalfedges) {
- v = he.getVertex();
- vi = vertexLists.get(v.key());
- if (vi == null) {
- vi = new VertexInfo();
-
- vertexLists.put(v.key(), vi);
- }
- vi.out.add(he);
- v = he.getNextInFace().getVertex();
- vi = vertexLists.get(v.key());
- if (vi == null) {
- vi = new VertexInfo();
- vertexLists.put(v.key(), vi);
-
- }
- vi.in.add(he);
- }
- HE_Halfedge he;
- HE_Halfedge he2;
- HE_Edge e;
- for (final VertexInfo vInfo : vertexLists.values()) {
- for (int i = 0; i < vInfo.out.size(); i++) {
- he = vInfo.out.get(i);
- if (he.getPair() == null) {
- for (int j = 0; j < vInfo.in.size(); j++) {
- he2 = vInfo.in.get(j);
- if ((he2.getPair() == null)
- && (he.getVertex() == he2.getNextInFace()
- .getVertex())
- && (he2.getVertex() == he.getNextInFace()
- .getVertex())) {
- he.setPair(he2);
- e = new HE_Edge();
- e.setHalfedge(he);
- he.setEdge(e);
- he2.setEdge(e);
- add(e);
- break;
-
- }
- }
- }
- }
- }
-
- }
-
- public void pairHalfedges(final List<HE_Halfedge> unpairedHalfedges) {
- class VertexInfo {
- FastList<HE_Halfedge> out;
- FastList<HE_Halfedge> in;
-
- VertexInfo() {
- out = new FastList<HE_Halfedge>();
- in = new FastList<HE_Halfedge>();
- }
-
- }
-
- final FastMap<Integer, VertexInfo> vertexLists = new FastMap<Integer, VertexInfo>();
- HE_Vertex v;
- VertexInfo vi;
- System.out.println("HE_Mesh : collating " + unpairedHalfedges.size()
- + " unpaired halfedges per vertex.");
- for (final HE_Halfedge he : unpairedHalfedges) {
- v = he.getVertex();
- vi = vertexLists.get(v.key());
- if (vi == null) {
- vi = new VertexInfo();
-
- vertexLists.put(v.key(), vi);
- }
- vi.out.add(he);
- v = he.getNextInFace().getVertex();
- vi = vertexLists.get(v.key());
- if (vi == null) {
- vi = new VertexInfo();
- vertexLists.put(v.key(), vi);
-
- }
- vi.in.add(he);
- }
- HE_Halfedge he;
- HE_Halfedge he2;
- HE_Edge e;
- System.out.println("HE_Mesh : pairing unpaired halfedges per vertex.");
- for (final VertexInfo vInfo : vertexLists.values()) {
- for (int i = 0; i < vInfo.out.size(); i++) {
- he = vInfo.out.get(i);
- if (he.getPair() == null) {
- for (int j = 0; j < vInfo.in.size(); j++) {
- he2 = vInfo.in.get(j);
- if ((he2.getPair() == null)
- && (he.getVertex() == he2.getNextInFace()
- .getVertex())
- && (he2.getVertex() == he.getNextInFace()
- .getVertex())) {
- he.setPair(he2);
- e = new HE_Edge();
- e.setHalfedge(he);
- he.setEdge(e);
- he2.setEdge(e);
- add(e);
- break;
-
- }
- }
- }
- }
- }
- }
-
- /**
- * Cap all remaining unpaired halfedges. Only use after pairHalfedges();
- */
- public void capHalfedges() {
- final ArrayList<HE_Halfedge> unpairedHalfedges = getUnpairedHalfedges();
- final int nuh = unpairedHalfedges.size();
- final HE_Halfedge[] newHalfedges = new HE_Halfedge[nuh];
- HE_Halfedge he1, he2;
- HE_Edge e;
- for (int i = 0; i < nuh; i++) {
- he1 = unpairedHalfedges.get(i);
- he2 = new HE_Halfedge();
- he2.setVertex(he1.getNextInFace().getVertex());
- he1.setPair(he2);
- newHalfedges[i] = he2;
- add(he2);
- e = new HE_Edge();
- add(e);
- e.setHalfedge(he1);
- he1.setEdge(e);
- he2.setEdge(e);
- }
-
- for (int i = 0; i < nuh; i++) {
- he1 = newHalfedges[i];
- if (he1.getNextInFace() == null) {
- for (int j = 0; j < nuh; j++) {
- he2 = newHalfedges[j];
- if (he2.getVertex() == he1.getPair().getVertex()) {
- he1.setNext(he2);
- break;
- }
- }
- }
- }
- }
-
- public void uncapHalfedges() {
- final Iterator<HE_Halfedge> heItr = heItr();
- HE_Halfedge he;
- while (heItr.hasNext()) {
- he = heItr.next();
- if (he.getFace() == null) {
- he.getVertex().setHalfedge(he.getPair());
- he.getEdge().setHalfedge(he.getPair());
- he.getPair().clearPair();
- heItr.remove();
- }
-
- }
-
- }
-
- /**
- * Cap holes.
- *
- * @return all new faces as ArrayList<HE_Face>
- */
- public ArrayList<HE_Face> capHoles() {
- final ArrayList<HE_Face> caps = new ArrayList<HE_Face>();
- final ArrayList<HE_Halfedge> unpairedEdges = getUnpairedHalfedges();
- ArrayList<HE_Halfedge> loopedHalfedges;
- HE_Halfedge start;
- HE_Halfedge he;
- HE_Halfedge hen;
- HE_Face nf;
- ArrayList<HE_Halfedge> newHalfedges;
- HE_Halfedge phe;
- HE_Halfedge nhe;
- HE_Edge ne;
- while (unpairedEdges.size() > 0) {
- loopedHalfedges = new ArrayList<HE_Halfedge>();
- start = unpairedEdges.get(0);
- loopedHalfedges.add(start);
- he = start;
- hen = start;
- boolean stuck = false;
- do {
- for (int i = 0; i < unpairedEdges.size(); i++) {
- hen = unpairedEdges.get(i);
- if (hen.getVertex() == he.getNextInFace().getVertex()) {
- if (!loopedHalfedges.contains(hen)) {
- loopedHalfedges.add(hen);
- } else {
- stuck = true;
- }
- break;
- }
- }
- if (hen.getVertex() != he.getNextInFace().getVertex()) {
- stuck = true;
- }
- he = hen;
- } while ((hen.getNextInFace().getVertex() != start.getVertex())
- && (!stuck));
- unpairedEdges.removeAll(loopedHalfedges);
- nf = new HE_Face();
- add(nf);
- caps.add(nf);
- newHalfedges = new ArrayList<HE_Halfedge>();
- for (int i = 0; i < loopedHalfedges.size(); i++) {
- phe = loopedHalfedges.get(i);
- nhe = new HE_Halfedge();
- add(nhe);
- newHalfedges.add(nhe);
- nhe.setVertex(phe.getNextInFace().getVertex());
- nhe.setPair(phe);
- nhe.setFace(nf);
- if (nf.getHalfedge() == null) {
- nf.setHalfedge(nhe);
- }
- ne = new HE_Edge();
- add(ne);
- ne.setHalfedge(nhe);
- nhe.setEdge(ne);
- phe.setEdge(ne);
-
- }
- cycleHalfedges(newHalfedges, HE_CycleOption.REVERSE);
-
- }
- return caps;
- }
-
- /**
- * Clean all mesh elements not used by any faces.
- *
- * @return self
- */
- public HE_Mesh cleanUnusedElementsByFace() {
- final ArrayList<HE_Vertex> cleanedVertices = new ArrayList<HE_Vertex>();
- final ArrayList<HE_Halfedge> cleanedHalfedges = new ArrayList<HE_Halfedge>();
- final ArrayList<HE_Edge> cleanedEdges = new ArrayList<HE_Edge>();
-
- HE_Halfedge he;
- HE_Edge e;
- HE_Face f;
- final Iterator<HE_Face> fItr = fItr();
- while (fItr.hasNext()) {
- f = fItr.next();
- he = f.getHalfedge();
- do {
- if (!cleanedVertices.contains(he.getVertex())) {
- cleanedVertices.add(he.getVertex());
- }
- if (!cleanedHalfedges.contains(he)) {
- cleanedHalfedges.add(he);
- }
-
- // if (!cleanedHalfedges.contains(he.pair())) {
- // cleanedHalfedges.add(he.pair());
- // }
-
- he.clearEdge();
- // he.pair().clearEdge();
- he = he.getNextInFace();
- } while (he != f.getHalfedge());
- }
- final int n = cleanedHalfedges.size();
- for (int i = 0; i < n; i++) {
- he = cleanedHalfedges.get(i);
- if (!cleanedHalfedges.contains(he.getPair())) {
- he.clearPair();
- he.getVertex().setHalfedge(he);
- } else {
- if (he.getEdge() == null) {
- e = new HE_Edge();
- e.setHalfedge(he);
- he.setEdge(e);
- he.getPair().setEdge(e);
- cleanedEdges.add(e);
- }
- }
- }
- replaceVertices(cleanedVertices);
- replaceHalfedges(cleanedHalfedges);
- replaceEdges(cleanedEdges);
- return this;
- }
-
- // MESH OPERATIONS
-
- /**
- * Reverse all faces. Flips normals.
- *
- */
- public HE_Mesh flipAllFaces() {
- HE_Edge edge;
- HE_Halfedge he1;
- HE_Halfedge he2;
- HE_Vertex tmp;
- HE_Halfedge[] prevHe;
- HE_Halfedge he;
- final Iterator<HE_Edge> eItr = eItr();
- while (eItr.hasNext()) {
- edge = eItr.next();
- he1 = edge.getHalfedge();
- he2 = he1.getPair();
- tmp = he1.getVertex();
- he1.setVertex(he2.getVertex());
- he2.setVertex(tmp);
- he1.getVertex().setHalfedge(he1);
- he2.getVertex().setHalfedge(he2);
- }
- prevHe = new HE_Halfedge[numberOfHalfedges()];
- int i = 0;
- Iterator<HE_Halfedge> heItr = heItr();
- while (heItr.hasNext()) {
- he = heItr.next();
- prevHe[i] = he.getPrevInFace();
- i++;
- }
- i = 0;
- heItr = heItr();
- while (heItr.hasNext()) {
- he = heItr.next();
- he.setNext(prevHe[i]);
- i++;
-
- }
- return this;
- }
-
- /**
- * Collapse edge. End vertices are averaged.
- *
- * @param e
- * edge to collapse
- */
- public void collapseEdge(final HE_Edge e) {
- if (contains(e)) {
- final HE_Halfedge he = e.getHalfedge();
- final HE_Vertex v = he.getVertex();
- final HE_Halfedge hePair = e.getHalfedge().getPair();
- final HE_Vertex vp = hePair.getVertex();
- vp.add(v).div(2);
- final ArrayList<HE_Halfedge> tmp = v.getHalfedgeStar();
- for (int i = 0; i < tmp.size(); i++) {
- tmp.get(i).setVertex(vp);
- }
-
- final HE_Halfedge hen = he.getNextInFace();
- final HE_Halfedge hep = he.getPrevInFace();
- final HE_Halfedge hePairn = hePair.getNextInFace();
- final HE_Halfedge hePairp = hePair.getPrevInFace();
- if (he.getFace() != null) {
- he.getFace().setHalfedge(hen);
- }
- if (hePair.getFace() != null) {
- hePair.getFace().setHalfedge(hePairn);
- }
-
- hep.setNext(hen);
- hePairp.setNext(hePairn);
- remove(he);
- remove(hePair);
- remove(e);
- remove(v);
- if (hen.getNextInFace() == hep) { // if face only contains 2 edges,
- // remove
- // face
- hePairp.setPair(hePairn);
- remove(hePairp.getEdge());
- hePairp.setEdge(hePairn.getEdge());
- remove(hep.getFace());
- remove(hep);
- remove(hen);
-
- }
- }
-
- }
-
- /**
- * Collapse all zero-length edges.
- *
- */
- public void collapseDegenerateEdges() {
- final ArrayList<HE_Edge> edgesToRemove = new ArrayList<HE_Edge>();
- final Iterator<HE_Edge> eItr = eItr();
- HE_Edge e;
- while (eItr.hasNext()) {
- e = eItr.next();
- if (WB_Epsilon.isZeroSq(WB_Distance.sqDistance(e.getStartVertex(),
- e.getEndVertex()))) {
- edgesToRemove.add(e);
- }
- }
- for (int i = 0; i < edgesToRemove.size(); i++) {
- collapseEdge(edgesToRemove.get(i));
- }
- }
-
- /**
- * Delete face and remove all references.
- *
- * @param f face to delete
- */
- public void deleteFace(final HE_Face f) {
- HE_Halfedge he = f.getHalfedge();
- do {
- he.clearFace();
- he = he.getNextInFace();
- } while (he != f.getHalfedge());
- remove(f);
- }
-
- /**
- * Delete edge. Adjacent faces are fused.
- *
- * @param e
- * edge to delete
- * @return fused face (or null)
- */
- public HE_Face deleteEdge(final HE_Edge e) {
- HE_Face f = null;
- final HE_Halfedge he1 = e.getHalfedge();
- final HE_Halfedge he2 = e.getHalfedge().getPair();
- final HE_Halfedge he1n = e.getHalfedge().getNextInFace();
- final HE_Halfedge he2n = e.getHalfedge().getPair().getNextInFace();
- final HE_Halfedge he1p = e.getHalfedge().getPrevInFace();
- final HE_Halfedge he2p = e.getHalfedge().getPair().getPrevInFace();
- he1p.setNext(he2n);
- he2p.setNext(he1n);
- HE_Vertex v = he1.getVertex();
- if (v.getHalfedge() == he1) {
- v.setHalfedge(he1.getNextInVertex());
- }
- v = he2.getVertex();
-
- if (v.getHalfedge() == he2) {
- v.setHalfedge(he2.getNextInVertex());
- }
- if ((e.getFirstFace() != null) && (e.getSecondFace() != null)) {
- f = new HE_Face();
- add(f);
- f.setHalfedge(he1p);
- HE_Halfedge he = he1p;
- do {
- he.setFace(f);
- he = he.getNextInFace();
- } while (he != he1p);
-
- }
- if (e.getFirstFace() != null) {
- remove(e.getFirstFace());
- }
- if (e.getSecondFace() != null) {
- remove(e.getSecondFace());
- }
- remove(he1);
- remove(he2);
- remove(e);
- return f;
- }
-
- /**
- * Insert vertex in edge.
- *
- * @param edge edge to split
- * @param v position of new vertex
- * @return selection of new vertex and new edge
- */
- public HE_Selection splitEdge(final HE_Edge edge, final WB_Point v) {
- final HE_Selection out = new HE_Selection(this);
- final HE_Halfedge he0 = edge.getHalfedge();
- final HE_Halfedge he1 = he0.getPair();
- final HE_Vertex vNew = new HE_Vertex(v);
- final HE_Halfedge he0new = new HE_Halfedge();
- final HE_Halfedge he1new = new HE_Halfedge();
- he0new.setVertex(vNew);
- he1new.setVertex(vNew);
- vNew.setHalfedge(he0new);
- he0new.setNext(he0.getNextInFace());
- he1new.setNext(he1.getNextInFace());
- he0.setNext(he0new);
- he1.setNext(he1new);
- he0.setPair(he1new);
- he0new.setPair(he1);
- final HE_Edge edgeNew = new HE_Edge();
- edgeNew.label = edge.label;
- edgeNew.setHalfedge(he0new);
- he1new.setEdge(edge);
- he1.setEdge(edgeNew);
- he0new.setEdge(edgeNew);
- if (he0.getFace() != null) {
- he0new.setFace(he0.getFace());
- }
- if (he1.getFace() != null) {
- he1new.setFace(he1.getFace());
- }
- vNew.setLabel(1);
- add(vNew);
- add(he0new);
- add(he1new);
- add(edgeNew);
- out.add(vNew);
- out.add(edgeNew);
- return out;
- }
-
- /**
- * Insert vertex in edge.
- *
- * @param key key of edge to split
- * @param v position of new vertex
- * @return selection of new vertex and new edge
- */
- public HE_Selection splitEdge(final Integer key, final WB_Point v) {
- final HE_Edge edge = getEdgeByKey(key);
- return splitEdge(edge, v);
- }
-
- /**
- * Insert vertex in edge.
- *
- * @param edge
- * edge to split
- * @param x
- * x-coordinate of new vertex
- * @param y
- * y-coordinate of new vertex
- * @param z
- * z-coordinate of new vertex
- */
- public void splitEdge(final HE_Edge edge, final double x, final double y,
- final double z) {
- splitEdge(edge, new WB_Point(x, y, z));
- }
-
- /**
- * Insert vertex in edge.
- *
- * @param key
- * key of edge to split
- * @param x
- * x-coordinate of new vertex
- * @param y
- * y-coordinate of new vertex
- * @param z
- * z-coordinate of new vertex
- */
- public void splitEdge(final Integer key, final double x, final double y,
- final double z) {
- splitEdge(key, new WB_Point(x, y, z));
- }
-
- /**
- * Split edge in half.
- *
- * @param edge edge to split.
- * @return selection of new vertex and new edge
- */
- public HE_Selection splitEdge(final HE_Edge edge) {
- final WB_Point v = edge.getStartVertex()
- .addAndCopy(edge.getEndVertex());
- v.mult(0.5);
- return splitEdge(edge, v);
- }
-
- /**
- * Split edge in half.
- *
- * @param key key of edge to split.
- * @return selection of new vertex and new edge
- */
- public HE_Selection splitEdge(final Integer key) {
- final HE_Edge edge = getEdgeByKey(key);
- final WB_Point v = edge.getStartVertex()
- .addAndCopy(edge.getEndVertex());
- v.mult(0.5);
- return splitEdge(edge, v);
- }
-
- /**
- * Split edge in two parts.
- *
- * @param edge edge to split
- * @param f fraction of first part (0..1)
- * @return selection of new vertex and new edge
- */
- public HE_Selection splitEdge(final HE_Edge edge, final double f) {
- final WB_Point v = WB_Point.interpolate(edge.getStartVertex(),
- edge.getEndVertex(), f);
- return splitEdge(edge, v);
- }
-
- /**
- * Split edge in two parts.
- *
- * @param key key of edge to split
- * @param f fraction of first part (0..1)
- * @return selection of new vertex and new edge
- */
- public HE_Selection splitEdge(final Integer key, final double f) {
- final HE_Edge edge = getEdgeByKey(key);
- return splitEdge(edge, f);
- }
-
- /**
- * Split all edges in half.
- *
- * @return selection of new vertices and new edges
- */
- public HE_Selection splitEdges() {
- final HE_Selection selectionOut = new HE_Selection(this);
-
- final HE_Edge[] edges = getEdgesAsArray();
- final int n = numberOfEdges();
- for (int i = 0; i < n; i++) {
- selectionOut.union(splitEdge(edges[i], 0.5));
- }
- return selectionOut;
- }
-
- /**
- * Split all edges in half, offset the center by a given distance along the edge normal.
- *
- * @param offset
- * @return selection of new vertices and new edges
- */
- public HE_Selection splitEdges(final double offset) {
- final HE_Selection selectionOut = new HE_Selection(this);
-
- final HE_Edge[] edges = getEdgesAsArray();
- final int n = numberOfEdges();
- for (int i = 0; i < n; i++) {
- final WB_Point p = new WB_Point(edges[i].getEdgeNormal());
- p.mult(offset).add(edges[i].getEdgeCenter());
- selectionOut.union(splitEdge(edges[i], p));
- }
- return selectionOut;
- }
-
- /**
- * Split edge in half.
- *
- * @param selection edges to split.
- * @return selection of new vertices and new edges
- */
- public HE_Selection splitEdges(final HE_Selection selection) {
- final HE_Selection selectionOut = new HE_Selection(this);
- selection.collectEdges();
- final Iterator<HE_Edge> eItr = selection.eItr();
- while (eItr.hasNext()) {
- selectionOut.union(splitEdge(eItr.next(), 0.5));
- }
- selection.addEdges(selectionOut.getEdgesAsArray());
- return selectionOut;
- }
-
- /**
- * Split edge in half, offset the center by a given distance along the edge normal.
- *
- * @param offset
- * @param selection edges to split.
- * @return selection of new vertices and new edges
- */
- public HE_Selection splitEdges(final HE_Selection selection,
- final double offset) {
- final HE_Selection selectionOut = new HE_Selection(this);
- selection.collectEdges();
- final Iterator<HE_Edge> eItr = selection.eItr();
- HE_Edge e;
- while (eItr.hasNext()) {
- e = eItr.next();
- final WB_Point p = new WB_Point(e.getEdgeNormal());
- p.mult(offset).add(e.getEdgeCenter());
- selectionOut.union(splitEdge(e, p));
- }
- selection.addEdges(selectionOut.getEdgesAsArray());
- return selectionOut;
- }
-
- /**
- * Split edge in multiple parts.
- *
- * @param edge
- * edge to split
- * @param f
- * array of fractions (0..1)
- */
- public void splitEdge(final HE_Edge edge, final double[] f) {
- final double[] fArray = Arrays.copyOf(f, f.length);
- Arrays.sort(fArray);
- HE_Edge e = edge;
- final HE_Halfedge he0 = edge.getHalfedge();
- final HE_Halfedge h…
Large files files are truncated, but you can click here to view the full file