Face.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import { HalfEdge } from './HalfEdge';
  2. import { Vector3 } from '../Vector3';
  3. import { Triangle } from '../Triangle';
  4. import { Visible, NonConvex, Deleted } from '../../constants';
  5. /**
  6. * @author Mugen87 / https://github.com/Mugen87
  7. *
  8. */
  9. function Face() {
  10. this.normal = new Vector3();
  11. this.midpoint = new Vector3();
  12. this.area = 0;
  13. this.constant = 0; // signed distance from face to the origin
  14. this.outside = null; // reference to the a vertex in a vertex list this face can see
  15. this.mark = Visible;
  16. this.edge = null;
  17. }
  18. Object.assign( Face, {
  19. create: function( a, b, c ) {
  20. var face = new Face();
  21. var e0 = new HalfEdge( a, face );
  22. var e1 = new HalfEdge( b, face );
  23. var e2 = new HalfEdge( c, face );
  24. // join edges
  25. e0.next = e2.prev = e1;
  26. e1.next = e0.prev = e2;
  27. e2.next = e1.prev = e0;
  28. // main half edge reference
  29. face.edge = e0;
  30. return face.compute();
  31. }
  32. } );
  33. Object.assign( Face.prototype, {
  34. getEdge: function ( i ) {
  35. var edge = this.edge;
  36. while ( i > 0 ) {
  37. edge = edge.next;
  38. i --;
  39. }
  40. while ( i < 0 ) {
  41. edge = edge.prev;
  42. i ++;
  43. }
  44. return edge;
  45. },
  46. compute: function () {
  47. var triangle;
  48. return function compute () {
  49. if ( triangle === undefined ) triangle = new Triangle();
  50. var a = this.edge.tail();
  51. var b = this.edge.head();
  52. var c = this.edge.next.head();
  53. triangle.set( a.point, b.point, c.point );
  54. triangle.normal( this.normal );
  55. triangle.midpoint( this.midpoint );
  56. this.area = triangle.area();
  57. this.constant = this.normal.dot( this.midpoint );
  58. return this;
  59. };
  60. }(),
  61. distanceToPoint: function ( point ) {
  62. return this.normal.dot( point ) - this.constant;
  63. },
  64. // Connects two edges assuming that prev.head().point === next.tail().point
  65. connectHalfEdges: function ( prev, next ) {
  66. var discardedFace;
  67. if ( prev.twin.face === next.twin.face ) {
  68. var oppositeFace = next.twin.face;
  69. var twinEdge;
  70. if ( prev === this.edge ) {
  71. this.edge = next;
  72. }
  73. twinEdge = next.twin.prev.twin;
  74. oppositeFace.mark = Deleted;
  75. discardedFace = oppositeFace;
  76. next.prev = prev.prev;
  77. next.prev.next = next;
  78. next.setTwin( twinEdge );
  79. oppositeFace.compute();
  80. } else {
  81. prev.next = next;
  82. next.prev = prev;
  83. }
  84. return discardedFace;
  85. },
  86. mergeAdjacentFaces: function( adjacentEdge, discardedFaces ) {
  87. var twinEdge = adjacentEdge.twin;
  88. var oppositeFace = twinEdge.face;
  89. discardedFaces.push( oppositeFace );
  90. oppositeFace.mark = Deleted;
  91. // find the chain of edges whose opposite face is 'oppositeFace'
  92. var adjacentEdgePrev = adjacentEdge.prev;
  93. var adjacentEdgeNext = adjacentEdge.next;
  94. var twinEdgePrev = twinEdge.prev;
  95. var twinEdgeNext = twinEdge.next;
  96. // left edge
  97. while ( adjacentEdgePrev.twin.face === oppositeFace ) {
  98. adjacentEdgePrev = adjacentEdgePrev.prev;
  99. twinEdgeNext = twinEdgeNext.next;
  100. }
  101. // right edge
  102. while ( adjacentEdgeNext.twin.face === oppositeFace ) {
  103. adjacentEdgeNext = adjacentEdgeNext.next;
  104. twinEdgePrev = twinEdgePrev.prev;
  105. }
  106. // fix the face reference of all the twin edges that are not part of
  107. // the edges whose opposite face is not 'face' i.e. all the edges that
  108. // 'face' and 'oppositeFace' do not have in common
  109. var edge = twinEdgeNext;
  110. do {
  111. edge.face = this;
  112. edge = edge.next;
  113. } while ( edge !== twinEdgePrev.next );
  114. // make sure that 'face.edge' is not one of the edges to be destroyed
  115. // Note: it's important for it to be a 'next' edge since 'prev' edges
  116. // might be destroyed on 'connectHalfEdges'
  117. this.edge = adjacentEdgeNext;
  118. // connect the extremes
  119. // Note: it might be possible that after connecting the edges a triangular face might be redundant
  120. var discardedFace;
  121. discardedFace = this.connectHalfEdges( twinEdgePrev, adjacentEdgeNext );
  122. if ( discardedFace !== undefined ) {
  123. discardedFaces.push( discardedFace );
  124. }
  125. discardedFace = this.connectHalfEdges( adjacentEdgePrev, twinEdgeNext );
  126. if ( discardedFace !== undefined ) {
  127. discardedFaces.push( discardedFace );
  128. }
  129. this.compute();
  130. return discardedFaces;
  131. }
  132. } );
  133. export { Face };