PageRenderTime 68ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/deps/hemesh2010/src/wblut/hemesh/core/HE_Mesh.java

https://bitbucket.org/filtercake/bodyextensions
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

  1. /*
  2. * Copyright (c) 2010, Frederik Vanhoutte This library is free software; you can
  3. * redistribute it and/or modify it under the terms of the GNU Lesser General
  4. * Public License as published by the Free Software Foundation; either version
  5. * 2.1 of the License, or (at your option) any later version.
  6. * http://creativecommons.org/licenses/LGPL/2.1/ This library is distributed in
  7. * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
  8. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  9. * the GNU Lesser General Public License for more details. You should have
  10. * received a copy of the GNU Lesser General Public License along with this
  11. * library; if not, write to the Free Software Foundation, Inc., 51 Franklin St,
  12. * Fifth Floor, Boston, MA 02110-1301 USA
  13. */
  14. package wblut.hemesh.core;
  15. import java.util.ArrayList;
  16. import java.util.Arrays;
  17. import java.util.HashMap;
  18. import java.util.Iterator;
  19. import java.util.List;
  20. import javolution.util.FastList;
  21. import javolution.util.FastMap;
  22. import javolution.util.FastTable;
  23. import wblut.frame.WB_Frame;
  24. import wblut.geom.WB_AABB;
  25. import wblut.geom.WB_ClassifyPointToPlane;
  26. import wblut.geom.WB_ClosestPoint;
  27. import wblut.geom.WB_Distance;
  28. import wblut.geom.WB_ExplicitPolygon;
  29. import wblut.geom.WB_ExplicitSegment;
  30. import wblut.geom.WB_IndexedSegment;
  31. import wblut.geom.WB_IndexedTriangle;
  32. import wblut.geom.WB_Intersection;
  33. import wblut.geom.WB_IntersectionResult;
  34. import wblut.geom.WB_Normal;
  35. import wblut.geom.WB_Plane;
  36. import wblut.geom.WB_Point;
  37. import wblut.geom.WB_Ray;
  38. import wblut.geom.WB_Transform;
  39. import wblut.geom.WB_Vector;
  40. import wblut.geom.WB_XYZ;
  41. import wblut.geom2D.WB_IndexedTriangle2D;
  42. import wblut.geom2D.WB_PolygonType2D;
  43. import wblut.hemesh.creators.HEC_Creator;
  44. import wblut.hemesh.modifiers.HEM_Modifier;
  45. import wblut.hemesh.options.HE_CycleOption;
  46. import wblut.hemesh.subdividors.HES_Subdividor;
  47. import wblut.math.WB_Epsilon;
  48. import wblut.tree.WB_KDNeighbor;
  49. import wblut.tree.WB_KDTree;
  50. /**
  51. * Half-edge mesh data structure.
  52. *
  53. * @author Frederik Vanhoutte (W:Blut)
  54. *
  55. */
  56. public class HE_Mesh extends HE_MeshStructure {
  57. /** Stored mesh center. */
  58. private WB_Point _center;
  59. /** Status of mesh center. */
  60. private boolean _centerUpdated;
  61. /** General purpose label. */
  62. protected int label;
  63. /**
  64. * Instantiates a new HE_Mesh.
  65. *
  66. */
  67. public HE_Mesh() {
  68. super();
  69. _center = new WB_Point();
  70. _centerUpdated = false;
  71. label = -1;
  72. }
  73. public void setLabel(final int lab) {
  74. label = lab;
  75. }
  76. public int getLabel() {
  77. return label;
  78. }
  79. // CREATE
  80. /**
  81. * Constructor.
  82. *
  83. * @param creator
  84. * HE_Creator that generates this mesh
  85. */
  86. public HE_Mesh(final HEC_Creator creator) {
  87. super();
  88. setNoCopy(creator.create());
  89. _centerUpdated = false;
  90. label = -1;
  91. }
  92. // MODIFY
  93. /**
  94. * Modify the mesh.
  95. *
  96. * @param modifier
  97. * HE_Modifier to apply
  98. * @return self
  99. */
  100. public HE_Mesh modify(final HEM_Modifier modifier) {
  101. return modifier.apply(this);
  102. }
  103. /**
  104. * Modify selection. Elements should be part of this mesh.
  105. *
  106. * @param modifier
  107. * HE_Modifier to apply
  108. * @return self
  109. */
  110. public HE_Mesh modifySelected(final HEM_Modifier modifier,
  111. final HE_Selection selection) {
  112. return modifier.apply(selection.get());
  113. }
  114. // SUBDIVIDE
  115. /**
  116. * Subdivide the mesh.
  117. *
  118. * @param subdividor
  119. * HE_Subdividor to apply
  120. * @return self
  121. */
  122. public HE_Mesh subdivide(final HES_Subdividor subdividor) {
  123. return subdividor.apply(this);
  124. }
  125. /**
  126. * Subdivide selection of the mesh.
  127. *
  128. * @param subdividor
  129. * HE_Subdividor to apply
  130. * @param selection
  131. * HE_Selection
  132. * @return self
  133. */
  134. public HE_Mesh subdivideSelected(final HES_Subdividor subdividor,
  135. final HE_Selection selection) {
  136. return subdividor.apply(selection);
  137. }
  138. /**
  139. * Subdivide the mesh a number of times.
  140. *
  141. * @param subdividor HE_Subdividor to apply
  142. * @param rep subdivision iterations. WARNING: higher values will lead to
  143. * unmanageable number of faces.
  144. * @return self
  145. */
  146. public HE_Mesh subdivide(final HES_Subdividor subdividor, final int rep) {
  147. for (int i = 0; i < rep; i++) {
  148. subdivide(subdividor);
  149. }
  150. return this;
  151. }
  152. /**
  153. * Subdivide a selection of the mesh a number of times.
  154. *
  155. * @param subdividor
  156. * HE_Subdividor to apply
  157. * @param selection
  158. * HE_Selection initial selection
  159. * @param rep subdivision iterations
  160. * @return self
  161. */
  162. public HE_Mesh subdivideSelected(final HES_Subdividor subdividor,
  163. final HE_Selection selection, final int rep) {
  164. for (int i = 0; i < rep; i++) {
  165. subdivideSelected(subdividor, selection);
  166. }
  167. return this;
  168. }
  169. /**
  170. * Deep copy of mesh.
  171. *
  172. * @return copy as new HE_Mesh, includes selection
  173. */
  174. public HE_Mesh get() {
  175. final HE_Mesh result = new HE_Mesh();
  176. final HashMap<Integer, Integer> vertexCorrelation = new HashMap<Integer, Integer>();
  177. final HashMap<Integer, Integer> faceCorrelation = new HashMap<Integer, Integer>();
  178. final HashMap<Integer, Integer> halfedgeCorrelation = new HashMap<Integer, Integer>();
  179. final HashMap<Integer, Integer> edgeCorrelation = new HashMap<Integer, Integer>();
  180. HE_Vertex rv;
  181. HE_Vertex v;
  182. final Iterator<HE_Vertex> vItr = vItr();
  183. while (vItr.hasNext()) {
  184. v = vItr.next();
  185. rv = new HE_Vertex();
  186. result.add(rv);
  187. vertexCorrelation.put(v.key(), rv.key());
  188. }
  189. HE_Face rf;
  190. HE_Face f;
  191. final Iterator<HE_Face> fItr = fItr();
  192. while (fItr.hasNext()) {
  193. f = fItr.next();
  194. rf = new HE_Face();
  195. result.add(rf);
  196. rf.label = f.label;
  197. faceCorrelation.put(f.key(), rf.key());
  198. }
  199. HE_Halfedge rhe;
  200. HE_Halfedge he;
  201. final Iterator<HE_Halfedge> heItr = heItr();
  202. while (heItr.hasNext()) {
  203. he = heItr.next();
  204. rhe = new HE_Halfedge();
  205. result.add(rhe);
  206. halfedgeCorrelation.put(he.key(), rhe.key());
  207. }
  208. HE_Edge re;
  209. final Iterator<HE_Edge> eItr = eItr();
  210. HE_Edge e;
  211. while (eItr.hasNext()) {
  212. e = eItr.next();
  213. re = new HE_Edge();
  214. result.add(re);
  215. edgeCorrelation.put(e.key(), re.key());
  216. }
  217. HE_Vertex sv;
  218. HE_Vertex tv;
  219. final Iterator<HE_Vertex> svItr = vItr();
  220. final Iterator<HE_Vertex> tvItr = result.vItr();
  221. Integer key;
  222. while (svItr.hasNext()) {
  223. sv = svItr.next();
  224. tv = tvItr.next();
  225. tv.set(sv);
  226. if (sv.getHalfedge() != null) {
  227. key = halfedgeCorrelation.get(sv.getHalfedge().key());
  228. tv.setHalfedge(result.getHalfedgeByKey(key));
  229. }
  230. }
  231. HE_Face sf;
  232. HE_Face tf;
  233. final Iterator<HE_Face> sfItr = fItr();
  234. final Iterator<HE_Face> tfItr = result.fItr();
  235. while (sfItr.hasNext()) {
  236. sf = sfItr.next();
  237. tf = tfItr.next();
  238. if (sf.getHalfedge() != null) {
  239. key = halfedgeCorrelation.get(sf.getHalfedge().key());
  240. tf.setHalfedge(result.getHalfedgeByKey(key));
  241. }
  242. }
  243. final Iterator<HE_Edge> seItr = eItr();
  244. final Iterator<HE_Edge> teItr = result.eItr();
  245. HE_Edge se;
  246. HE_Edge te;
  247. while (seItr.hasNext()) {
  248. se = seItr.next();
  249. te = teItr.next();
  250. if (se.getHalfedge() != null) {
  251. key = halfedgeCorrelation.get(se.getHalfedge().key());
  252. te.setHalfedge(result.getHalfedgeByKey(key));
  253. }
  254. }
  255. HE_Halfedge she;
  256. HE_Halfedge the;
  257. final Iterator<HE_Halfedge> sheItr = heItr();
  258. final Iterator<HE_Halfedge> theItr = result.heItr();
  259. while (sheItr.hasNext()) {
  260. she = sheItr.next();
  261. the = theItr.next();
  262. if (she.getPair() != null) {
  263. key = halfedgeCorrelation.get(she.getPair().key());
  264. the.setPair(result.getHalfedgeByKey(key));
  265. }
  266. if (she.getNextInFace() != null) {
  267. key = halfedgeCorrelation.get(she.getNextInFace().key());
  268. the.setNext(result.getHalfedgeByKey(key));
  269. }
  270. if (she.getVertex() != null) {
  271. key = vertexCorrelation.get(she.getVertex().key());
  272. the.setVertex(result.getVertexByKey(key));
  273. }
  274. if (she.getFace() != null) {
  275. key = faceCorrelation.get(she.getFace().key());
  276. the.setFace(result.getFaceByKey(key));
  277. }
  278. if (she.getEdge() != null) {
  279. key = edgeCorrelation.get(she.getEdge().key());
  280. the.setEdge(result.getEdgeByKey(key));
  281. }
  282. }
  283. result._center.set(_center);
  284. result._centerUpdated = _centerUpdated;
  285. return result;
  286. }
  287. /**
  288. * Add all mesh elements to this mesh. No copies are made.
  289. *
  290. * @param mesh mesh to add
  291. */
  292. public void add(final HE_Mesh mesh) {
  293. addVertices(mesh.getVerticesAsArray());
  294. addFaces(mesh.getFacesAsArray());
  295. addEdges(mesh.getEdgesAsArray());
  296. addHalfedges(mesh.getHalfedgesAsArray());
  297. }
  298. /**
  299. * Replace mesh with deep copy of target.
  300. *
  301. * @param target
  302. * HE_Mesh to be duplicated
  303. */
  304. public void set(final HE_Mesh target) {
  305. final HE_Mesh result = target.get();
  306. replaceVertices(result.getVerticesAsArray());
  307. replaceFaces(result.getFacesAsArray());
  308. replaceHalfedges(result.getHalfedgesAsArray());
  309. replaceEdges(result.getEdgesAsArray());
  310. }
  311. /**
  312. * Replace mesh with shallow copy of target.
  313. *
  314. * @param target
  315. * HE_Mesh to be duplicated
  316. */
  317. private void setNoCopy(final HE_Mesh target) {
  318. _hashedVertices = target._hashedVertices;
  319. _hashedHalfedges = target._hashedHalfedges;
  320. _hashedEdges = target._hashedEdges;
  321. _hashedFaces = target._hashedFaces;
  322. _center = target._center;
  323. _centerUpdated = target._centerUpdated;
  324. }
  325. // CONVERT
  326. /**
  327. * Return all vertex positions as an array .
  328. *
  329. * @return 2D array of float. First index gives vertex. Second index gives
  330. * x-,y- or z-coordinate.
  331. */
  332. public float[][] getVerticesAsFloat() {
  333. final float[][] result = new float[numberOfVertices()][3];
  334. int i = 0;
  335. HE_Vertex v;
  336. final Iterator<HE_Vertex> vItr = vItr();
  337. while (vItr.hasNext()) {
  338. v = vItr.next();
  339. result[i][0] = (float) (v.x);
  340. result[i][1] = (float) (v.y);
  341. result[i][2] = (float) (v.z);
  342. i++;
  343. }
  344. return result;
  345. }
  346. /**
  347. * Return all vertex positions as an array .
  348. *
  349. * @return 2D array of double. First index gives vertex. Second index gives
  350. * x-,y- or z-coordinate.
  351. */
  352. public double[][] getVerticesAsDouble() {
  353. final double[][] result = new double[numberOfVertices()][3];
  354. int i = 0;
  355. HE_Vertex v;
  356. final Iterator<HE_Vertex> vItr = vItr();
  357. while (vItr.hasNext()) {
  358. v = vItr.next();
  359. result[i][0] = (float) (v.x);
  360. result[i][1] = (float) (v.y);
  361. result[i][2] = (float) (v.z);
  362. i++;
  363. }
  364. return result;
  365. }
  366. public HashMap<Integer, Integer> vertexKeyToIndex() {
  367. final HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
  368. int i = 0;
  369. final Iterator<HE_Vertex> vItr = vItr();
  370. while (vItr.hasNext()) {
  371. map.put(vItr.next().key(), i);
  372. i++;
  373. }
  374. return map;
  375. }
  376. /**
  377. * Return all vertex positions.
  378. *
  379. * @return array of WB_Point, values are copied.
  380. */
  381. public WB_Point[] getVerticesAsNewPoint() {
  382. final WB_Point[] result = new WB_Point[numberOfVertices()];
  383. int i = 0;
  384. HE_Vertex v;
  385. final Iterator<HE_Vertex> vItr = vItr();
  386. while (vItr.hasNext()) {
  387. v = vItr.next();
  388. result[i] = new WB_Point(v);
  389. i++;
  390. }
  391. return result;
  392. }
  393. /**
  394. * Return all vertex positions.
  395. *
  396. * @return array of WB_Point, no copies are made.
  397. */
  398. public WB_Point[] getVerticesAsPoint() {
  399. final WB_Point[] result = new WB_Point[numberOfVertices()];
  400. int i = 0;
  401. HE_Vertex v;
  402. final Iterator<HE_Vertex> vItr = vItr();
  403. while (vItr.hasNext()) {
  404. v = vItr.next();
  405. result[i] = v;
  406. i++;
  407. }
  408. return result;
  409. }
  410. /**
  411. * Return all vertex normal.
  412. *
  413. * @return array of WB_Normal.
  414. */
  415. public WB_Normal[] getVertexNormals() {
  416. final WB_Normal[] result = new WB_Normal[numberOfVertices()];
  417. int i = 0;
  418. HE_Vertex v;
  419. final Iterator<HE_Vertex> vItr = vItr();
  420. while (vItr.hasNext()) {
  421. v = vItr.next();
  422. result[i] = v.getVertexNormal();
  423. i++;
  424. }
  425. return result;
  426. }
  427. /**
  428. * Return all vertex normal.
  429. *
  430. * @return FastMap of WB_Normal.
  431. */
  432. public FastMap<Integer, WB_Normal> getKeyedVertexNormals() {
  433. final FastMap<Integer, WB_Normal> result = new FastMap<Integer, WB_Normal>(
  434. numberOfVertices());
  435. HE_Vertex v;
  436. final Iterator<HE_Vertex> vItr = vItr();
  437. while (vItr.hasNext()) {
  438. v = vItr.next();
  439. result.put(v.key(), v.getVertexNormal());
  440. }
  441. return result;
  442. }
  443. /**
  444. * Return the faces as array of vertex indices.
  445. *
  446. * @return 2D array of int. First index gives face. Second index gives
  447. * vertices.
  448. */
  449. public int[][] getFacesAsInt() {
  450. final int[][] result = new int[numberOfFaces()][];
  451. final FastMap<Integer, Integer> vertexKeys = new FastMap<Integer, Integer>();
  452. final Iterator<HE_Vertex> vItr = vItr();
  453. int i = 0;
  454. while (vItr.hasNext()) {
  455. vertexKeys.put(vItr.next().key(), i);
  456. i++;
  457. }
  458. final Iterator<HE_Face> fItr = fItr();
  459. HE_Halfedge he;
  460. HE_Face f;
  461. i = 0;
  462. while (fItr.hasNext()) {
  463. f = fItr.next();
  464. result[i] = new int[f.getFaceOrder()];
  465. he = f.getHalfedge();
  466. int j = 0;
  467. do {
  468. result[i][j] = vertexKeys.get(he.getVertex().key());
  469. he = he.getNextInFace();
  470. j++;
  471. } while (he != f.getHalfedge());
  472. i++;
  473. }
  474. return result;
  475. }
  476. /**
  477. * Return all face normals.
  478. *
  479. * @return array of WB_Normal.
  480. */
  481. public WB_Normal[] getFaceNormals() {
  482. final WB_Normal[] result = new WB_Normal[numberOfFaces()];
  483. int i = 0;
  484. HE_Face f;
  485. final Iterator<HE_Face> fItr = fItr();
  486. while (fItr.hasNext()) {
  487. f = fItr.next();
  488. result[i] = f.getFaceNormal();
  489. i++;
  490. }
  491. return result;
  492. }
  493. /**
  494. * Return all face normals.
  495. *
  496. * @return FastMap of WB_Normal.
  497. */
  498. public FastMap<Integer, WB_Normal> getKeyedFaceNormals() {
  499. final FastMap<Integer, WB_Normal> result = new FastMap<Integer, WB_Normal>(
  500. numberOfFaces());
  501. HE_Face f;
  502. final Iterator<HE_Face> fItr = fItr();
  503. while (fItr.hasNext()) {
  504. f = fItr.next();
  505. result.put(f.key(), f.getFaceNormal());
  506. }
  507. return result;
  508. }
  509. /**
  510. * Return all face centers.
  511. *
  512. * @return array of WB_Point.
  513. */
  514. public WB_Point[] getFaceCenters() {
  515. final WB_Point[] result = new WB_Point[numberOfFaces()];
  516. int i = 0;
  517. HE_Face f;
  518. final Iterator<HE_Face> fItr = fItr();
  519. while (fItr.hasNext()) {
  520. f = fItr.next();
  521. result[i] = f.getFaceCenter();
  522. i++;
  523. }
  524. return result;
  525. }
  526. /**
  527. * Return all face centers.
  528. *
  529. * @return FastMap of WB_Point.
  530. */
  531. public FastMap<Integer, WB_Point> getKeyedFaceCenters() {
  532. final FastMap<Integer, WB_Point> result = new FastMap<Integer, WB_Point>(
  533. numberOfFaces());
  534. HE_Face f;
  535. final Iterator<HE_Face> fItr = fItr();
  536. while (fItr.hasNext()) {
  537. f = fItr.next();
  538. result.put(f.key(), f.getFaceCenter());
  539. }
  540. return result;
  541. }
  542. /**
  543. * Return all edge normals.
  544. *
  545. * @return array of WB_Normal.
  546. */
  547. public WB_Normal[] getEdgeNormals() {
  548. final WB_Normal[] result = new WB_Normal[numberOfEdges()];
  549. int i = 0;
  550. HE_Edge e;
  551. final Iterator<HE_Edge> eItr = eItr();
  552. while (eItr.hasNext()) {
  553. e = eItr.next();
  554. result[i] = e.getEdgeNormal();
  555. i++;
  556. }
  557. return result;
  558. }
  559. /**
  560. * Return all edge normals.
  561. *
  562. * @return FastMap of WB_Normal.
  563. */
  564. public FastMap<Integer, WB_Normal> getKeyedEdgeNormals() {
  565. final FastMap<Integer, WB_Normal> result = new FastMap<Integer, WB_Normal>(
  566. numberOfEdges());
  567. HE_Edge e;
  568. final Iterator<HE_Edge> eItr = eItr();
  569. while (eItr.hasNext()) {
  570. e = eItr.next();
  571. result.put(e.key(), e.getEdgeNormal());
  572. }
  573. return result;
  574. }
  575. /**
  576. * Return all edge centers.
  577. *
  578. * @return array of WB_Point.
  579. */
  580. public WB_Point[] getEdgeCenters() {
  581. final WB_Point[] result = new WB_Point[numberOfEdges()];
  582. int i = 0;
  583. HE_Edge e;
  584. final Iterator<HE_Edge> eItr = eItr();
  585. while (eItr.hasNext()) {
  586. e = eItr.next();
  587. result[i] = e.getEdgeCenter();
  588. i++;
  589. }
  590. return result;
  591. }
  592. /**
  593. * Return all edge centers.
  594. *
  595. * @return FastMap of WB_Point.
  596. */
  597. public FastMap<Integer, WB_Point> getKeyedEdgeCenters() {
  598. final FastMap<Integer, WB_Point> result = new FastMap<Integer, WB_Point>(
  599. numberOfEdges());
  600. HE_Edge e;
  601. final Iterator<HE_Edge> eItr = eItr();
  602. while (eItr.hasNext()) {
  603. e = eItr.next();
  604. result.put(e.key(), e.getEdgeCenter());
  605. }
  606. return result;
  607. }
  608. /**
  609. * Set vertex positions to values in array.
  610. *
  611. * @param values 2D array of float. First index is number of vertices, second
  612. * index is 3 (x-,y- and z-coordinate)
  613. */
  614. public void setVerticesFromFloat(final float[][] values) {
  615. int i = 0;
  616. _center.set(0, 0, 0);
  617. HE_Vertex v;
  618. final Iterator<HE_Vertex> vItr = vItr();
  619. while (vItr.hasNext()) {
  620. v = vItr.next();
  621. v.set(values[i][0], values[i][1], values[i][2]);
  622. i++;
  623. }
  624. }
  625. /**
  626. * Set vertex positions to values in array.
  627. *
  628. * @param values array of WB_Point.
  629. */
  630. public void setVerticesFromPoint(final WB_Point[] values) {
  631. int i = 0;
  632. _center.set(0, 0, 0);
  633. HE_Vertex v;
  634. final Iterator<HE_Vertex> vItr = vItr();
  635. while (vItr.hasNext()) {
  636. v = vItr.next();
  637. v.set(values[i]);
  638. i++;
  639. }
  640. ;
  641. }
  642. /**
  643. * Set vertex positions to values in array.
  644. *
  645. * @param values 2D array of double. First index is number of vertices, second
  646. * index is 3 (x-,y- and z-coordinate)
  647. */
  648. public void setVerticesFromDouble(final double[][] values) {
  649. int i = 0;
  650. HE_Vertex v;
  651. final Iterator<HE_Vertex> vItr = vItr();
  652. while (vItr.hasNext()) {
  653. v = vItr.next();
  654. v.set(values[i][0], values[i][1], values[i][2]);
  655. i++;
  656. }
  657. ;
  658. }
  659. /**
  660. * Set vertex positions to values in array.
  661. *
  662. * @param values 2D array of int. First index is number of vertices, second
  663. * index is 3 (x-,y- and z-coordinate)
  664. */
  665. public void setVerticesFromInt(final int[][] values) {
  666. int i = 0;
  667. HE_Vertex v;
  668. final Iterator<HE_Vertex> vItr = vItr();
  669. while (vItr.hasNext()) {
  670. v = vItr.next();
  671. v.set(values[i][0], values[i][1], values[i][2]);
  672. i++;
  673. }
  674. ;
  675. }
  676. /**
  677. * Return the mesh as polygon soup.
  678. *
  679. * @return array of WB_polygon
  680. *
  681. */
  682. public WB_ExplicitPolygon[] getPolygons() {
  683. final WB_ExplicitPolygon[] result = new WB_ExplicitPolygon[numberOfFaces()];
  684. final Iterator<HE_Face> fItr = fItr();
  685. HE_Face f;
  686. int i = 0;
  687. while (fItr.hasNext()) {
  688. f = fItr.next();
  689. result[i] = f.toPolygon();
  690. i++;
  691. }
  692. return result;
  693. }
  694. public ArrayList<WB_ExplicitPolygon> getPolygonArrayList() {
  695. final ArrayList<WB_ExplicitPolygon> result = new ArrayList<WB_ExplicitPolygon>();
  696. final Iterator<HE_Face> fItr = fItr();
  697. HE_Face f;
  698. while (fItr.hasNext()) {
  699. f = fItr.next();
  700. result.add(f.toPolygon());
  701. }
  702. return result;
  703. }
  704. public WB_ExplicitSegment[] getSegments() {
  705. final WB_ExplicitSegment[] result = new WB_ExplicitSegment[numberOfEdges()];
  706. final Iterator<HE_Edge> eItr = eItr();
  707. HE_Edge e;
  708. int i = 0;
  709. while (eItr.hasNext()) {
  710. e = eItr.next();
  711. result[i] = new WB_ExplicitSegment(e.getStartVertex(),
  712. e.getEndVertex(), false);
  713. i++;
  714. }
  715. return result;
  716. }
  717. public WB_IndexedSegment[] getIndexedSegments() {
  718. final WB_IndexedSegment[] result = new WB_IndexedSegment[numberOfEdges()];
  719. final WB_Point[] points = getVerticesAsPoint();
  720. final FastMap<Integer, Integer> map = new FastMap<Integer, Integer>();
  721. map.putAll(vertexKeyToIndex());
  722. final Iterator<HE_Edge> eItr = eItr();
  723. HE_Edge e;
  724. int i = 0;
  725. while (eItr.hasNext()) {
  726. e = eItr.next();
  727. result[i] = new WB_IndexedSegment(
  728. map.get(e.getStartVertex().key()), map.get(e.getEndVertex()
  729. .key()), points);
  730. i++;
  731. }
  732. return result;
  733. }
  734. public WB_Frame getFrame() {
  735. final WB_Frame frame = new WB_Frame(getVerticesAsPoint());
  736. final FastMap<Integer, Integer> map = new FastMap<Integer, Integer>();
  737. map.putAll(vertexKeyToIndex());
  738. final Iterator<HE_Edge> eItr = eItr();
  739. HE_Edge e;
  740. while (eItr.hasNext()) {
  741. e = eItr.next();
  742. frame.addStrut(map.get(e.getStartVertex().key()),
  743. map.get(e.getEndVertex().key()));
  744. }
  745. return frame;
  746. }
  747. // TRANSFORM
  748. /**
  749. * Apply transform to entire mesh.
  750. *
  751. * @param T WB_Transform to apply
  752. * @return self
  753. */
  754. public HE_Mesh transform(final WB_Transform T) {
  755. final Iterator<HE_Vertex> vItr = vItr();
  756. while (vItr.hasNext()) {
  757. T.apply(vItr.next());
  758. }
  759. return this;
  760. }
  761. /**
  762. * Translate entire mesh.
  763. *
  764. * @param x the x
  765. * @param y the y
  766. * @param z the z
  767. * @return self
  768. */
  769. public HE_Mesh move(final double x, final double y, final double z) {
  770. _center.add(x, y, z);
  771. final Iterator<HE_Vertex> vItr = vItr();
  772. while (vItr.hasNext()) {
  773. vItr.next().add(x, y, z);
  774. }
  775. return this;
  776. }
  777. /**
  778. * Translate entire mesh.
  779. *
  780. * @param v
  781. * @return self
  782. */
  783. public HE_Mesh move(final WB_XYZ v) {
  784. return move(v.x, v.y, v.z);
  785. }
  786. /**
  787. * Translate entire mesh to given position.
  788. *
  789. * @param x
  790. * @param y
  791. * @param z
  792. * @return self
  793. */
  794. public HE_Mesh moveTo(final double x, final double y, final double z) {
  795. if (!_centerUpdated) {
  796. getCenter();
  797. }
  798. final Iterator<HE_Vertex> vItr = vItr();
  799. while (vItr.hasNext()) {
  800. vItr.next().add(x - _center.x, y - _center.y, z - _center.z);
  801. }
  802. _center.set(x, y, z);
  803. return this;
  804. }
  805. /**
  806. * Translate entire mesh to given position.
  807. *
  808. * @param v the v
  809. * @return self
  810. */
  811. public HE_Mesh moveTo(final WB_Point v) {
  812. return moveTo(v.x, v.y, v.z);
  813. }
  814. /**
  815. * Rotate entire mesh around an arbitrary axis.
  816. *
  817. * @param angle angle
  818. * @param p1x x-coordinate of first point on axis
  819. * @param p1y y-coordinate of first point on axis
  820. * @param p1z z-coordinate of first point on axis
  821. * @param p2x x-coordinate of second point on axis
  822. * @param p2y y-coordinate of second point on axis
  823. * @param p2z z-coordinate of second point on axis
  824. * @return self
  825. */
  826. public HE_Mesh rotateAboutAxis(final double angle, final double p1x,
  827. final double p1y, final double p1z, final double p2x,
  828. final double p2y, final double p2z) {
  829. if (!_centerUpdated) {
  830. getCenter();
  831. }
  832. HE_Vertex v;
  833. final Iterator<HE_Vertex> vItr = vItr();
  834. final WB_Transform raa = new WB_Transform();
  835. raa.addRotateAboutAxis(angle, new WB_Point(p1x, p1y, p1z),
  836. new WB_Vector(p2x - p1x, p2y - p1y, p2z - p1z));
  837. while (vItr.hasNext()) {
  838. v = vItr.next();
  839. raa.applyInto(v, v);
  840. }
  841. raa.applyInto(_center, _center);
  842. ;
  843. return this;
  844. }
  845. /**
  846. * Rotate entire mesh around an arbitrary axis.
  847. *
  848. * @param angle angle
  849. * @param p1 first point on axis
  850. * @param p2 second point on axis
  851. * @return self
  852. */
  853. public HE_Mesh rotateAboutAxis(final double angle, final WB_Point p1,
  854. final WB_Point p2) {
  855. if (!_centerUpdated) {
  856. getCenter();
  857. }
  858. HE_Vertex v;
  859. final Iterator<HE_Vertex> vItr = vItr();
  860. final WB_Transform raa = new WB_Transform();
  861. raa.addRotateAboutAxis(angle, p1, p2.subToVector(p1));
  862. while (vItr.hasNext()) {
  863. v = vItr.next();
  864. raa.applyInto(v, v);
  865. }
  866. raa.applyInto(_center, _center);
  867. ;
  868. return this;
  869. }
  870. /**
  871. * Rotate entire mesh around an arbitrary axis.
  872. *
  873. * @param angle angle
  874. * @param p rotation point
  875. * @param a axis
  876. * @return self
  877. */
  878. public HE_Mesh rotateAboutAxis(final double angle, final WB_Point p,
  879. final WB_Vector a) {
  880. if (!_centerUpdated) {
  881. getCenter();
  882. }
  883. HE_Vertex v;
  884. final Iterator<HE_Vertex> vItr = vItr();
  885. final WB_Transform raa = new WB_Transform();
  886. raa.addRotateAboutAxis(angle, p, a);
  887. while (vItr.hasNext()) {
  888. v = vItr.next();
  889. raa.applyInto(v, v);
  890. }
  891. raa.applyInto(_center, _center);
  892. ;
  893. return this;
  894. }
  895. /**
  896. * Rotate entire mesh around an arbitrary axis.
  897. *
  898. * @param angle angle
  899. * @param p rotation point
  900. * @param a axis
  901. * @return self
  902. */
  903. public HE_Mesh rotateAboutAxis(final double angle, final WB_Point p,
  904. final WB_Normal a) {
  905. if (!_centerUpdated) {
  906. getCenter();
  907. }
  908. HE_Vertex v;
  909. final Iterator<HE_Vertex> vItr = vItr();
  910. final WB_Transform raa = new WB_Transform();
  911. raa.addRotateAboutAxis(angle, p, a);
  912. while (vItr.hasNext()) {
  913. v = vItr.next();
  914. raa.applyInto(v, v);
  915. }
  916. raa.applyInto(_center, _center);
  917. ;
  918. return this;
  919. }
  920. /**
  921. * Scale entire mesh around center point.
  922. *
  923. * @param scaleFactorx
  924. * x-coordinate of scale factor
  925. * @param scaleFactory
  926. * y-coordinate of scale factor
  927. * @param scaleFactorz
  928. * z-coordinate of scale factor
  929. * @param c
  930. * center
  931. * @return self
  932. */
  933. public HE_Mesh scale(final double scaleFactorx, final double scaleFactory,
  934. final double scaleFactorz, final WB_Point c) {
  935. if (!_centerUpdated) {
  936. getCenter();
  937. }
  938. HE_Vertex v;
  939. final Iterator<HE_Vertex> vItr = vItr();
  940. while (vItr.hasNext()) {
  941. v = vItr.next();
  942. v.set(c.x + scaleFactorx * (v.x - c.x), c.y + scaleFactory
  943. * (v.y - c.y), c.z + scaleFactorz * (v.z - c.z));
  944. }
  945. _center.set(c.x + scaleFactorx * (-c.x + _center.x), c.y + scaleFactory
  946. * (-c.y + _center.y), c.z + scaleFactorz * (-c.z + _center.z));
  947. ;
  948. return this;
  949. }
  950. /**
  951. * Scale entire mesh around center point.
  952. *
  953. * @param scaleFactor
  954. * scale
  955. * @param c
  956. * center
  957. * @return self
  958. */
  959. public HE_Mesh scale(final double scaleFactor, final WB_Point c) {
  960. return scale(scaleFactor, scaleFactor, scaleFactor, c);
  961. }
  962. /**
  963. * Scale entire mesh around bodycenter.
  964. *
  965. * @param scaleFactorx
  966. * x-coordinate of scale factor
  967. * @param scaleFactory
  968. * y-coordinate of scale factor
  969. * @param scaleFactorz
  970. * z-coordinate of scale factor
  971. * @return self
  972. */
  973. public HE_Mesh scale(final double scaleFactorx, final double scaleFactory,
  974. final double scaleFactorz) {
  975. if (!_centerUpdated) {
  976. getCenter();
  977. }
  978. HE_Vertex v;
  979. final Iterator<HE_Vertex> vItr = vItr();
  980. while (vItr.hasNext()) {
  981. v = vItr.next();
  982. v.set(_center.x + scaleFactorx * (v.x - _center.x), _center.y
  983. + scaleFactory * (v.y - _center.y), _center.z
  984. + scaleFactorz * (v.z - _center.z));
  985. }
  986. ;
  987. return this;
  988. }
  989. /**
  990. * Scale entire mesh around bodycenter.
  991. *
  992. * @param scaleFactor
  993. * scale
  994. * @return self
  995. */
  996. public HE_Mesh scale(final double scaleFactor) {
  997. return scale(scaleFactor, scaleFactor, scaleFactor);
  998. }
  999. // DERIVED ELEMENTS
  1000. /**
  1001. * Get the center (average of all vertex positions).
  1002. *
  1003. * @return the center
  1004. */
  1005. public WB_Point getCenter() {
  1006. if (_centerUpdated) {
  1007. return _center;
  1008. } else {
  1009. resetCenter();
  1010. return _center;
  1011. }
  1012. }
  1013. /**
  1014. * Reset the center to the average of all vertex positions).
  1015. *
  1016. */
  1017. public void resetCenter() {
  1018. _center.set(0, 0, 0);
  1019. final Iterator<HE_Vertex> vItr = vItr();
  1020. while (vItr.hasNext()) {
  1021. _center.add(vItr.next());
  1022. }
  1023. _center.div(numberOfVertices());
  1024. _centerUpdated = true;
  1025. }
  1026. // HELPERS
  1027. /**
  1028. * Assign face to halfedge loop.
  1029. *
  1030. * @param face face
  1031. * @param halfedge halfedge loop
  1032. */
  1033. protected static void assignFaceToLoop(final HE_Face face,
  1034. final HE_Halfedge halfedge) {
  1035. HE_Halfedge he = halfedge;
  1036. do {
  1037. he.setFace(face);
  1038. he = he.getNextInFace();
  1039. } while (he != halfedge);
  1040. }
  1041. /**
  1042. * Cycle halfedges.
  1043. *
  1044. * @param halfedges halfedges to cycle
  1045. * @param cycle HE_CycleOption.NORMAL, HE_CycleOption.REVERSE
  1046. */
  1047. public static void cycleHalfedges(final List<HE_Halfedge> halfedges,
  1048. final HE_CycleOption cycle) {
  1049. HE_Halfedge he;
  1050. final int n = halfedges.size();
  1051. if (n > 0) {
  1052. if (cycle == HE_CycleOption.NORMAL) {
  1053. for (int j = 0; j < n - 1; j++) {
  1054. he = halfedges.get(j);
  1055. he.setNext(halfedges.get(j + 1));
  1056. }
  1057. he = halfedges.get(n - 1);
  1058. he.setNext(halfedges.get(0));
  1059. } else {
  1060. he = halfedges.get(0);
  1061. he.setNext(halfedges.get(n - 1));
  1062. for (int j = 1; j < n; j++) {
  1063. he = halfedges.get(j);
  1064. he.setNext(halfedges.get(j - 1));
  1065. }
  1066. }
  1067. }
  1068. }
  1069. /**
  1070. * Collect all unpaired halfedges.
  1071. *
  1072. * @return the unpaired halfedges
  1073. */
  1074. public ArrayList<HE_Halfedge> getUnpairedHalfedges() {
  1075. final ArrayList<HE_Halfedge> unpairedHalfedges = new ArrayList<HE_Halfedge>();
  1076. HE_Halfedge he;
  1077. final Iterator<HE_Halfedge> heItr = heItr();
  1078. while (heItr.hasNext()) {
  1079. he = heItr.next();
  1080. if (he.getPair() == null) {
  1081. unpairedHalfedges.add(he);
  1082. }
  1083. }
  1084. return unpairedHalfedges;
  1085. }
  1086. /**
  1087. * Collect all boundary halfedges.
  1088. *
  1089. * @return boundary halfedges
  1090. */
  1091. public ArrayList<HE_Halfedge> getBoundaryHalfedges() {
  1092. final ArrayList<HE_Halfedge> boundaryHalfedges = new ArrayList<HE_Halfedge>();
  1093. HE_Halfedge he;
  1094. final Iterator<HE_Halfedge> heItr = heItr();
  1095. while (heItr.hasNext()) {
  1096. he = heItr.next();
  1097. if (he.getFace() == null) {
  1098. boundaryHalfedges.add(he);
  1099. }
  1100. }
  1101. return boundaryHalfedges;
  1102. }
  1103. /**
  1104. * Try to pair all unpaired halfedges.
  1105. */
  1106. public void pairHalfedges() {
  1107. class VertexInfo {
  1108. FastList<HE_Halfedge> out;
  1109. FastList<HE_Halfedge> in;
  1110. VertexInfo() {
  1111. out = new FastList<HE_Halfedge>();
  1112. in = new FastList<HE_Halfedge>();
  1113. }
  1114. }
  1115. final FastMap<Integer, VertexInfo> vertexLists = new FastMap<Integer, VertexInfo>();
  1116. final ArrayList<HE_Halfedge> unpairedHalfedges = getUnpairedHalfedges();
  1117. HE_Vertex v;
  1118. VertexInfo vi;
  1119. System.out.println("HE_Mesh : collating " + unpairedHalfedges.size()
  1120. + " unpaired halfedges per vertex.");
  1121. for (final HE_Halfedge he : unpairedHalfedges) {
  1122. v = he.getVertex();
  1123. vi = vertexLists.get(v.key());
  1124. if (vi == null) {
  1125. vi = new VertexInfo();
  1126. vertexLists.put(v.key(), vi);
  1127. }
  1128. vi.out.add(he);
  1129. v = he.getNextInFace().getVertex();
  1130. vi = vertexLists.get(v.key());
  1131. if (vi == null) {
  1132. vi = new VertexInfo();
  1133. vertexLists.put(v.key(), vi);
  1134. }
  1135. vi.in.add(he);
  1136. }
  1137. HE_Halfedge he;
  1138. HE_Halfedge he2;
  1139. HE_Edge e;
  1140. System.out.println("HE_Mesh : pairing unpaired halfedges per vertex.");
  1141. for (final VertexInfo vInfo : vertexLists.values()) {
  1142. for (int i = 0; i < vInfo.out.size(); i++) {
  1143. he = vInfo.out.get(i);
  1144. if (he.getPair() == null) {
  1145. for (int j = 0; j < vInfo.in.size(); j++) {
  1146. he2 = vInfo.in.get(j);
  1147. if ((he2.getPair() == null)
  1148. && (he.getVertex() == he2.getNextInFace()
  1149. .getVertex())
  1150. && (he2.getVertex() == he.getNextInFace()
  1151. .getVertex())) {
  1152. he.setPair(he2);
  1153. e = new HE_Edge();
  1154. e.setHalfedge(he);
  1155. he.setEdge(e);
  1156. he2.setEdge(e);
  1157. add(e);
  1158. break;
  1159. }
  1160. }
  1161. }
  1162. }
  1163. }
  1164. }
  1165. public void pairHalfedgesSilent() {
  1166. class VertexInfo {
  1167. FastList<HE_Halfedge> out;
  1168. FastList<HE_Halfedge> in;
  1169. VertexInfo() {
  1170. out = new FastList<HE_Halfedge>();
  1171. in = new FastList<HE_Halfedge>();
  1172. }
  1173. }
  1174. final FastMap<Integer, VertexInfo> vertexLists = new FastMap<Integer, VertexInfo>();
  1175. final ArrayList<HE_Halfedge> unpairedHalfedges = getUnpairedHalfedges();
  1176. HE_Vertex v;
  1177. VertexInfo vi;
  1178. for (final HE_Halfedge he : unpairedHalfedges) {
  1179. v = he.getVertex();
  1180. vi = vertexLists.get(v.key());
  1181. if (vi == null) {
  1182. vi = new VertexInfo();
  1183. vertexLists.put(v.key(), vi);
  1184. }
  1185. vi.out.add(he);
  1186. v = he.getNextInFace().getVertex();
  1187. vi = vertexLists.get(v.key());
  1188. if (vi == null) {
  1189. vi = new VertexInfo();
  1190. vertexLists.put(v.key(), vi);
  1191. }
  1192. vi.in.add(he);
  1193. }
  1194. HE_Halfedge he;
  1195. HE_Halfedge he2;
  1196. HE_Edge e;
  1197. for (final VertexInfo vInfo : vertexLists.values()) {
  1198. for (int i = 0; i < vInfo.out.size(); i++) {
  1199. he = vInfo.out.get(i);
  1200. if (he.getPair() == null) {
  1201. for (int j = 0; j < vInfo.in.size(); j++) {
  1202. he2 = vInfo.in.get(j);
  1203. if ((he2.getPair() == null)
  1204. && (he.getVertex() == he2.getNextInFace()
  1205. .getVertex())
  1206. && (he2.getVertex() == he.getNextInFace()
  1207. .getVertex())) {
  1208. he.setPair(he2);
  1209. e = new HE_Edge();
  1210. e.setHalfedge(he);
  1211. he.setEdge(e);
  1212. he2.setEdge(e);
  1213. add(e);
  1214. break;
  1215. }
  1216. }
  1217. }
  1218. }
  1219. }
  1220. }
  1221. public void pairHalfedges(final List<HE_Halfedge> unpairedHalfedges) {
  1222. class VertexInfo {
  1223. FastList<HE_Halfedge> out;
  1224. FastList<HE_Halfedge> in;
  1225. VertexInfo() {
  1226. out = new FastList<HE_Halfedge>();
  1227. in = new FastList<HE_Halfedge>();
  1228. }
  1229. }
  1230. final FastMap<Integer, VertexInfo> vertexLists = new FastMap<Integer, VertexInfo>();
  1231. HE_Vertex v;
  1232. VertexInfo vi;
  1233. System.out.println("HE_Mesh : collating " + unpairedHalfedges.size()
  1234. + " unpaired halfedges per vertex.");
  1235. for (final HE_Halfedge he : unpairedHalfedges) {
  1236. v = he.getVertex();
  1237. vi = vertexLists.get(v.key());
  1238. if (vi == null) {
  1239. vi = new VertexInfo();
  1240. vertexLists.put(v.key(), vi);
  1241. }
  1242. vi.out.add(he);
  1243. v = he.getNextInFace().getVertex();
  1244. vi = vertexLists.get(v.key());
  1245. if (vi == null) {
  1246. vi = new VertexInfo();
  1247. vertexLists.put(v.key(), vi);
  1248. }
  1249. vi.in.add(he);
  1250. }
  1251. HE_Halfedge he;
  1252. HE_Halfedge he2;
  1253. HE_Edge e;
  1254. System.out.println("HE_Mesh : pairing unpaired halfedges per vertex.");
  1255. for (final VertexInfo vInfo : vertexLists.values()) {
  1256. for (int i = 0; i < vInfo.out.size(); i++) {
  1257. he = vInfo.out.get(i);
  1258. if (he.getPair() == null) {
  1259. for (int j = 0; j < vInfo.in.size(); j++) {
  1260. he2 = vInfo.in.get(j);
  1261. if ((he2.getPair() == null)
  1262. && (he.getVertex() == he2.getNextInFace()
  1263. .getVertex())
  1264. && (he2.getVertex() == he.getNextInFace()
  1265. .getVertex())) {
  1266. he.setPair(he2);
  1267. e = new HE_Edge();
  1268. e.setHalfedge(he);
  1269. he.setEdge(e);
  1270. he2.setEdge(e);
  1271. add(e);
  1272. break;
  1273. }
  1274. }
  1275. }
  1276. }
  1277. }
  1278. }
  1279. /**
  1280. * Cap all remaining unpaired halfedges. Only use after pairHalfedges();
  1281. */
  1282. public void capHalfedges() {
  1283. final ArrayList<HE_Halfedge> unpairedHalfedges = getUnpairedHalfedges();
  1284. final int nuh = unpairedHalfedges.size();
  1285. final HE_Halfedge[] newHalfedges = new HE_Halfedge[nuh];
  1286. HE_Halfedge he1, he2;
  1287. HE_Edge e;
  1288. for (int i = 0; i < nuh; i++) {
  1289. he1 = unpairedHalfedges.get(i);
  1290. he2 = new HE_Halfedge();
  1291. he2.setVertex(he1.getNextInFace().getVertex());
  1292. he1.setPair(he2);
  1293. newHalfedges[i] = he2;
  1294. add(he2);
  1295. e = new HE_Edge();
  1296. add(e);
  1297. e.setHalfedge(he1);
  1298. he1.setEdge(e);
  1299. he2.setEdge(e);
  1300. }
  1301. for (int i = 0; i < nuh; i++) {
  1302. he1 = newHalfedges[i];
  1303. if (he1.getNextInFace() == null) {
  1304. for (int j = 0; j < nuh; j++) {
  1305. he2 = newHalfedges[j];
  1306. if (he2.getVertex() == he1.getPair().getVertex()) {
  1307. he1.setNext(he2);
  1308. break;
  1309. }
  1310. }
  1311. }
  1312. }
  1313. }
  1314. public void uncapHalfedges() {
  1315. final Iterator<HE_Halfedge> heItr = heItr();
  1316. HE_Halfedge he;
  1317. while (heItr.hasNext()) {
  1318. he = heItr.next();
  1319. if (he.getFace() == null) {
  1320. he.getVertex().setHalfedge(he.getPair());
  1321. he.getEdge().setHalfedge(he.getPair());
  1322. he.getPair().clearPair();
  1323. heItr.remove();
  1324. }
  1325. }
  1326. }
  1327. /**
  1328. * Cap holes.
  1329. *
  1330. * @return all new faces as ArrayList<HE_Face>
  1331. */
  1332. public ArrayList<HE_Face> capHoles() {
  1333. final ArrayList<HE_Face> caps = new ArrayList<HE_Face>();
  1334. final ArrayList<HE_Halfedge> unpairedEdges = getUnpairedHalfedges();
  1335. ArrayList<HE_Halfedge> loopedHalfedges;
  1336. HE_Halfedge start;
  1337. HE_Halfedge he;
  1338. HE_Halfedge hen;
  1339. HE_Face nf;
  1340. ArrayList<HE_Halfedge> newHalfedges;
  1341. HE_Halfedge phe;
  1342. HE_Halfedge nhe;
  1343. HE_Edge ne;
  1344. while (unpairedEdges.size() > 0) {
  1345. loopedHalfedges = new ArrayList<HE_Halfedge>();
  1346. start = unpairedEdges.get(0);
  1347. loopedHalfedges.add(start);
  1348. he = start;
  1349. hen = start;
  1350. boolean stuck = false;
  1351. do {
  1352. for (int i = 0; i < unpairedEdges.size(); i++) {
  1353. hen = unpairedEdges.get(i);
  1354. if (hen.getVertex() == he.getNextInFace().getVertex()) {
  1355. if (!loopedHalfedges.contains(hen)) {
  1356. loopedHalfedges.add(hen);
  1357. } else {
  1358. stuck = true;
  1359. }
  1360. break;
  1361. }
  1362. }
  1363. if (hen.getVertex() != he.getNextInFace().getVertex()) {
  1364. stuck = true;
  1365. }
  1366. he = hen;
  1367. } while ((hen.getNextInFace().getVertex() != start.getVertex())
  1368. && (!stuck));
  1369. unpairedEdges.removeAll(loopedHalfedges);
  1370. nf = new HE_Face();
  1371. add(nf);
  1372. caps.add(nf);
  1373. newHalfedges = new ArrayList<HE_Halfedge>();
  1374. for (int i = 0; i < loopedHalfedges.size(); i++) {
  1375. phe = loopedHalfedges.get(i);
  1376. nhe = new HE_Halfedge();
  1377. add(nhe);
  1378. newHalfedges.add(nhe);
  1379. nhe.setVertex(phe.getNextInFace().getVertex());
  1380. nhe.setPair(phe);
  1381. nhe.setFace(nf);
  1382. if (nf.getHalfedge() == null) {
  1383. nf.setHalfedge(nhe);
  1384. }
  1385. ne = new HE_Edge();
  1386. add(ne);
  1387. ne.setHalfedge(nhe);
  1388. nhe.setEdge(ne);
  1389. phe.setEdge(ne);
  1390. }
  1391. cycleHalfedges(newHalfedges, HE_CycleOption.REVERSE);
  1392. }
  1393. return caps;
  1394. }
  1395. /**
  1396. * Clean all mesh elements not used by any faces.
  1397. *
  1398. * @return self
  1399. */
  1400. public HE_Mesh cleanUnusedElementsByFace() {
  1401. final ArrayList<HE_Vertex> cleanedVertices = new ArrayList<HE_Vertex>();
  1402. final ArrayList<HE_Halfedge> cleanedHalfedges = new ArrayList<HE_Halfedge>();
  1403. final ArrayList<HE_Edge> cleanedEdges = new ArrayList<HE_Edge>();
  1404. HE_Halfedge he;
  1405. HE_Edge e;
  1406. HE_Face f;
  1407. final Iterator<HE_Face> fItr = fItr();
  1408. while (fItr.hasNext()) {
  1409. f = fItr.next();
  1410. he = f.getHalfedge();
  1411. do {
  1412. if (!cleanedVertices.contains(he.getVertex())) {
  1413. cleanedVertices.add(he.getVertex());
  1414. }
  1415. if (!cleanedHalfedges.contains(he)) {
  1416. cleanedHalfedges.add(he);
  1417. }
  1418. // if (!cleanedHalfedges.contains(he.pair())) {
  1419. // cleanedHalfedges.add(he.pair());
  1420. // }
  1421. he.clearEdge();
  1422. // he.pair().clearEdge();
  1423. he = he.getNextInFace();
  1424. } while (he != f.getHalfedge());
  1425. }
  1426. final int n = cleanedHalfedges.size();
  1427. for (int i = 0; i < n; i++) {
  1428. he = cleanedHalfedges.get(i);
  1429. if (!cleanedHalfedges.contains(he.getPair())) {
  1430. he.clearPair();
  1431. he.getVertex().setHalfedge(he);
  1432. } else {
  1433. if (he.getEdge() == null) {
  1434. e = new HE_Edge();
  1435. e.setHalfedge(he);
  1436. he.setEdge(e);
  1437. he.getPair().setEdge(e);
  1438. cleanedEdges.add(e);
  1439. }
  1440. }
  1441. }
  1442. replaceVertices(cleanedVertices);
  1443. replaceHalfedges(cleanedHalfedges);
  1444. replaceEdges(cleanedEdges);
  1445. return this;
  1446. }
  1447. // MESH OPERATIONS
  1448. /**
  1449. * Reverse all faces. Flips normals.
  1450. *
  1451. */
  1452. public HE_Mesh flipAllFaces() {
  1453. HE_Edge edge;
  1454. HE_Halfedge he1;
  1455. HE_Halfedge he2;
  1456. HE_Vertex tmp;
  1457. HE_Halfedge[] prevHe;
  1458. HE_Halfedge he;
  1459. final Iterator<HE_Edge> eItr = eItr();
  1460. while (eItr.hasNext()) {
  1461. edge = eItr.next();
  1462. he1 = edge.getHalfedge();
  1463. he2 = he1.getPair();
  1464. tmp = he1.getVertex();
  1465. he1.setVertex(he2.getVertex());
  1466. he2.setVertex(tmp);
  1467. he1.getVertex().setHalfedge(he1);
  1468. he2.getVertex().setHalfedge(he2);
  1469. }
  1470. prevHe = new HE_Halfedge[numberOfHalfedges()];
  1471. int i = 0;
  1472. Iterator<HE_Halfedge> heItr = heItr();
  1473. while (heItr.hasNext()) {
  1474. he = heItr.next();
  1475. prevHe[i] = he.getPrevInFace();
  1476. i++;
  1477. }
  1478. i = 0;
  1479. heItr = heItr();
  1480. while (heItr.hasNext()) {
  1481. he = heItr.next();
  1482. he.setNext(prevHe[i]);
  1483. i++;
  1484. }
  1485. return this;
  1486. }
  1487. /**
  1488. * Collapse edge. End vertices are averaged.
  1489. *
  1490. * @param e
  1491. * edge to collapse
  1492. */
  1493. public void collapseEdge(final HE_Edge e) {
  1494. if (contains(e)) {
  1495. final HE_Halfedge he = e.getHalfedge();
  1496. final HE_Vertex v = he.getVertex();
  1497. final HE_Halfedge hePair = e.getHalfedge().getPair();
  1498. final HE_Vertex vp = hePair.getVertex();
  1499. vp.add(v).div(2);
  1500. final ArrayList<HE_Halfedge> tmp = v.getHalfedgeStar();
  1501. for (int i = 0; i < tmp.size(); i++) {
  1502. tmp.get(i).setVertex(vp);
  1503. }
  1504. final HE_Halfedge hen = he.getNextInFace();
  1505. final HE_Halfedge hep = he.getPrevInFace();
  1506. final HE_Halfedge hePairn = hePair.getNextInFace();
  1507. final HE_Halfedge hePairp = hePair.getPrevInFace();
  1508. if (he.getFace() != null) {
  1509. he.getFace().setHalfedge(hen);
  1510. }
  1511. if (hePair.getFace() != null) {
  1512. hePair.getFace().setHalfedge(hePairn);
  1513. }
  1514. hep.setNext(hen);
  1515. hePairp.setNext(hePairn);
  1516. remove(he);
  1517. remove(hePair);
  1518. remove(e);
  1519. remove(v);
  1520. if (hen.getNextInFace() == hep) { // if face only contains 2 edges,
  1521. // remove
  1522. // face
  1523. hePairp.setPair(hePairn);
  1524. remove(hePairp.getEdge());
  1525. hePairp.setEdge(hePairn.getEdge());
  1526. remove(hep.getFace());
  1527. remove(hep);
  1528. remove(hen);
  1529. }
  1530. }
  1531. }
  1532. /**
  1533. * Collapse all zero-length edges.
  1534. *
  1535. */
  1536. public void collapseDegenerateEdges() {
  1537. final ArrayList<HE_Edge> edgesToRemove = new ArrayList<HE_Edge>();
  1538. final Iterator<HE_Edge> eItr = eItr();
  1539. HE_Edge e;
  1540. while (eItr.hasNext()) {
  1541. e = eItr.next();
  1542. if (WB_Epsilon.isZeroSq(WB_Distance.sqDistance(e.getStartVertex(),
  1543. e.getEndVertex()))) {
  1544. edgesToRemove.add(e);
  1545. }
  1546. }
  1547. for (int i = 0; i < edgesToRemove.size(); i++) {
  1548. collapseEdge(edgesToRemove.get(i));
  1549. }
  1550. }
  1551. /**
  1552. * Delete face and remove all references.
  1553. *
  1554. * @param f face to delete
  1555. */
  1556. public void deleteFace(final HE_Face f) {
  1557. HE_Halfedge he = f.getHalfedge();
  1558. do {
  1559. he.clearFace();
  1560. he = he.getNextInFace();
  1561. } while (he != f.getHalfedge());
  1562. remove(f);
  1563. }
  1564. /**
  1565. * Delete edge. Adjacent faces are fused.
  1566. *
  1567. * @param e
  1568. * edge to delete
  1569. * @return fused face (or null)
  1570. */
  1571. public HE_Face deleteEdge(final HE_Edge e) {
  1572. HE_Face f = null;
  1573. final HE_Halfedge he1 = e.getHalfedge();
  1574. final HE_Halfedge he2 = e.getHalfedge().getPair();
  1575. final HE_Halfedge he1n = e.getHalfedge().getNextInFace();
  1576. final HE_Halfedge he2n = e.getHalfedge().getPair().getNextInFace();
  1577. final HE_Halfedge he1p = e.getHalfedge().getPrevInFace();
  1578. final HE_Halfedge he2p = e.getHalfedge().getPair().getPrevInFace();
  1579. he1p.setNext(he2n);
  1580. he2p.setNext(he1n);
  1581. HE_Vertex v = he1.getVertex();
  1582. if (v.getHalfedge() == he1) {
  1583. v.setHalfedge(he1.getNextInVertex());
  1584. }
  1585. v = he2.getVertex();
  1586. if (v.getHalfedge() == he2) {
  1587. v.setHalfedge(he2.getNextInVertex());
  1588. }
  1589. if ((e.getFirstFace() != null) && (e.getSecondFace() != null)) {
  1590. f = new HE_Face();
  1591. add(f);
  1592. f.setHalfedge(he1p);
  1593. HE_Halfedge he = he1p;
  1594. do {
  1595. he.setFace(f);
  1596. he = he.getNextInFace();
  1597. } while (he != he1p);
  1598. }
  1599. if (e.getFirstFace() != null) {
  1600. remove(e.getFirstFace());
  1601. }
  1602. if (e.getSecondFace() != null) {
  1603. remove(e.getSecondFace());
  1604. }
  1605. remove(he1);
  1606. remove(he2);
  1607. remove(e);
  1608. return f;
  1609. }
  1610. /**
  1611. * Insert vertex in edge.
  1612. *
  1613. * @param edge edge to split
  1614. * @param v position of new vertex
  1615. * @return selection of new vertex and new edge
  1616. */
  1617. public HE_Selection splitEdge(final HE_Edge edge, final WB_Point v) {
  1618. final HE_Selection out = new HE_Selection(this);
  1619. final HE_Halfedge he0 = edge.getHalfedge();
  1620. final HE_Halfedge he1 = he0.getPair();
  1621. final HE_Vertex vNew = new HE_Vertex(v);
  1622. final HE_Halfedge he0new = new HE_Halfedge();
  1623. final HE_Halfedge he1new = new HE_Halfedge();
  1624. he0new.setVertex(vNew);
  1625. he1new.setVertex(vNew);
  1626. vNew.setHalfedge(he0new);
  1627. he0new.setNext(he0.getNextInFace());
  1628. he1new.setNext(he1.getNextInFace());
  1629. he0.setNext(he0new);
  1630. he1.setNext(he1new);
  1631. he0.setPair(he1new);
  1632. he0new.setPair(he1);
  1633. final HE_Edge edgeNew = new HE_Edge();
  1634. edgeNew.label = edge.label;
  1635. edgeNew.setHalfedge(he0new);
  1636. he1new.setEdge(edge);
  1637. he1.setEdge(edgeNew);
  1638. he0new.setEdge(edgeNew);
  1639. if (he0.getFace() != null) {
  1640. he0new.setFace(he0.getFace());
  1641. }
  1642. if (he1.getFace() != null) {
  1643. he1new.setFace(he1.getFace());
  1644. }
  1645. vNew.setLabel(1);
  1646. add(vNew);
  1647. add(he0new);
  1648. add(he1new);
  1649. add(edgeNew);
  1650. out.add(vNew);
  1651. out.add(edgeNew);
  1652. return out;
  1653. }
  1654. /**
  1655. * Insert vertex in edge.
  1656. *
  1657. * @param key key of edge to split
  1658. * @param v position of new vertex
  1659. * @return selection of new vertex and new edge
  1660. */
  1661. public HE_Selection splitEdge(final Integer key, final WB_Point v) {
  1662. final HE_Edge edge = getEdgeByKey(key);
  1663. return splitEdge(edge, v);
  1664. }
  1665. /**
  1666. * Insert vertex in edge.
  1667. *
  1668. * @param edge
  1669. * edge to split
  1670. * @param x
  1671. * x-coordinate of new vertex
  1672. * @param y
  1673. * y-coordinate of new vertex
  1674. * @param z
  1675. * z-coordinate of new vertex
  1676. */
  1677. public void splitEdge(final HE_Edge edge, final double x, final double y,
  1678. final double z) {
  1679. splitEdge(edge, new WB_Point(x, y, z));
  1680. }
  1681. /**
  1682. * Insert vertex in edge.
  1683. *
  1684. * @param key
  1685. * key of edge to split
  1686. * @param x
  1687. * x-coordinate of new vertex
  1688. * @param y
  1689. * y-coordinate of new vertex
  1690. * @param z
  1691. * z-coordinate of new vertex
  1692. */
  1693. public void splitEdge(final Integer key, final double x, final double y,
  1694. final double z) {
  1695. splitEdge(key, new WB_Point(x, y, z));
  1696. }
  1697. /**
  1698. * Split edge in half.
  1699. *
  1700. * @param edge edge to split.
  1701. * @return selection of new vertex and new edge
  1702. */
  1703. public HE_Selection splitEdge(final HE_Edge edge) {
  1704. final WB_Point v = edge.getStartVertex()
  1705. .addAndCopy(edge.getEndVertex());
  1706. v.mult(0.5);
  1707. return splitEdge(edge, v);
  1708. }
  1709. /**
  1710. * Split edge in half.
  1711. *
  1712. * @param key key of edge to split.
  1713. * @return selection of new vertex and new edge
  1714. */
  1715. public HE_Selection splitEdge(final Integer key) {
  1716. final HE_Edge edge = getEdgeByKey(key);
  1717. final WB_Point v = edge.getStartVertex()
  1718. .addAndCopy(edge.getEndVertex());
  1719. v.mult(0.5);
  1720. return splitEdge(edge, v);
  1721. }
  1722. /**
  1723. * Split edge in two parts.
  1724. *
  1725. * @param edge edge to split
  1726. * @param f fraction of first part (0..1)
  1727. * @return selection of new vertex and new edge
  1728. */
  1729. public HE_Selection splitEdge(final HE_Edge edge, final double f) {
  1730. final WB_Point v = WB_Point.interpolate(edge.getStartVertex(),
  1731. edge.getEndVertex(), f);
  1732. return splitEdge(edge, v);
  1733. }
  1734. /**
  1735. * Split edge in two parts.
  1736. *
  1737. * @param key key of edge to split
  1738. * @param f fraction of first part (0..1)
  1739. * @return selection of new vertex and new edge
  1740. */
  1741. public HE_Selection splitEdge(final Integer key, final double f) {
  1742. final HE_Edge edge = getEdgeByKey(key);
  1743. return splitEdge(edge, f);
  1744. }
  1745. /**
  1746. * Split all edges in half.
  1747. *
  1748. * @return selection of new vertices and new edges
  1749. */
  1750. public HE_Selection splitEdges() {
  1751. final HE_Selection selectionOut = new HE_Selection(this);
  1752. final HE_Edge[] edges = getEdgesAsArray();
  1753. final int n = numberOfEdges();
  1754. for (int i = 0; i < n; i++) {
  1755. selectionOut.union(splitEdge(edges[i], 0.5));
  1756. }
  1757. return selectionOut;
  1758. }
  1759. /**
  1760. * Split all edges in half, offset the center by a given distance along the edge normal.
  1761. *
  1762. * @param offset
  1763. * @return selection of new vertices and new edges
  1764. */
  1765. public HE_Selection splitEdges(final double offset) {
  1766. final HE_Selection selectionOut = new HE_Selection(this);
  1767. final HE_Edge[] edges = getEdgesAsArray();
  1768. final int n = numberOfEdges();
  1769. for (int i = 0; i < n; i++) {
  1770. final WB_Point p = new WB_Point(edges[i].getEdgeNormal());
  1771. p.mult(offset).add(edges[i].getEdgeCenter());
  1772. selectionOut.union(splitEdge(edges[i], p));
  1773. }
  1774. return selectionOut;
  1775. }
  1776. /**
  1777. * Split edge in half.
  1778. *
  1779. * @param selection edges to split.
  1780. * @return selection of new vertices and new edges
  1781. */
  1782. public HE_Selection splitEdges(final HE_Selection selection) {
  1783. final HE_Selection selectionOut = new HE_Selection(this);
  1784. selection.collectEdges();
  1785. final Iterator<HE_Edge> eItr = selection.eItr();
  1786. while (eItr.hasNext()) {
  1787. selectionOut.union(splitEdge(eItr.next(), 0.5));
  1788. }
  1789. selection.addEdges(selectionOut.getEdgesAsArray());
  1790. return selectionOut;
  1791. }
  1792. /**
  1793. * Split edge in half, offset the center by a given distance along the edge normal.
  1794. *
  1795. * @param offset
  1796. * @param selection edges to split.
  1797. * @return selection of new vertices and new edges
  1798. */
  1799. public HE_Selection splitEdges(final HE_Selection selection,
  1800. final double offset) {
  1801. final HE_Selection selectionOut = new HE_Selection(this);
  1802. selection.collectEdges();
  1803. final Iterator<HE_Edge> eItr = selection.eItr();
  1804. HE_Edge e;
  1805. while (eItr.hasNext()) {
  1806. e = eItr.next();
  1807. final WB_Point p = new WB_Point(e.getEdgeNormal());
  1808. p.mult(offset).add(e.getEdgeCenter());
  1809. selectionOut.union(splitEdge(e, p));
  1810. }
  1811. selection.addEdges(selectionOut.getEdgesAsArray());
  1812. return selectionOut;
  1813. }
  1814. /**
  1815. * Split edge in multiple parts.
  1816. *
  1817. * @param edge
  1818. * edge to split
  1819. * @param f
  1820. * array of fractions (0..1)
  1821. */
  1822. public void splitEdge(final HE_Edge edge, final double[] f) {
  1823. final double[] fArray = Arrays.copyOf(f, f.length);
  1824. Arrays.sort(fArray);
  1825. HE_Edge e = edge;
  1826. final HE_Halfedge he0 = edge.getHalfedge();
  1827. final HE_Halfedge h

Large files files are truncated, but you can click here to view the full file