face.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. // Begin License:
  2. // Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
  3. // All rights reserved.
  4. //
  5. // This file is part of the Carve CSG Library (http://carve-csg.com/)
  6. //
  7. // This file may be used under the terms of either the GNU General
  8. // Public License version 2 or 3 (at your option) as published by the
  9. // Free Software Foundation and appearing in the files LICENSE.GPL2
  10. // and LICENSE.GPL3 included in the packaging of this file.
  11. //
  12. // This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
  13. // INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
  14. // A PARTICULAR PURPOSE.
  15. // End:
  16. #if defined(HAVE_CONFIG_H)
  17. # include <carve_config.h>
  18. #endif
  19. #include <carve/poly.hpp>
  20. namespace {
  21. double CALC_X(const carve::geom::plane<3> &p, double y, double z) { return -(p.d + p.N.y * y + p.N.z * z) / p.N.x; }
  22. double CALC_Y(const carve::geom::plane<3> &p, double x, double z) { return -(p.d + p.N.x * x + p.N.z * z) / p.N.y; }
  23. double CALC_Z(const carve::geom::plane<3> &p, double x, double y) { return -(p.d + p.N.x * x + p.N.y * y) / p.N.z; }
  24. } // namespace
  25. namespace carve {
  26. namespace poly {
  27. namespace {
  28. carve::geom2d::P2 _project_1(const carve::geom3d::Vector &v) {
  29. return carve::geom::VECTOR(v.z, v.y);
  30. }
  31. carve::geom2d::P2 _project_2(const carve::geom3d::Vector &v) {
  32. return carve::geom::VECTOR(v.x, v.z);
  33. }
  34. carve::geom2d::P2 _project_3(const carve::geom3d::Vector &v) {
  35. return carve::geom::VECTOR(v.y, v.x);
  36. }
  37. carve::geom2d::P2 _project_4(const carve::geom3d::Vector &v) {
  38. return carve::geom::VECTOR(v.y, v.z);
  39. }
  40. carve::geom2d::P2 _project_5(const carve::geom3d::Vector &v) {
  41. return carve::geom::VECTOR(v.z, v.x);
  42. }
  43. carve::geom2d::P2 _project_6(const carve::geom3d::Vector &v) {
  44. return carve::geom::VECTOR(v.x, v.y);
  45. }
  46. carve::geom3d::Vector _unproject_1(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
  47. return carve::geom::VECTOR(CALC_X(plane_eqn, p.y, p.x), p.y, p.x);
  48. }
  49. carve::geom3d::Vector _unproject_2(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
  50. return carve::geom::VECTOR(p.x, CALC_Y(plane_eqn, p.x, p.y), p.y);
  51. }
  52. carve::geom3d::Vector _unproject_3(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
  53. return carve::geom::VECTOR(p.y, p.x, CALC_Z(plane_eqn, p.y, p.x));
  54. }
  55. carve::geom3d::Vector _unproject_4(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
  56. return carve::geom::VECTOR(CALC_X(plane_eqn, p.x, p.y), p.x, p.y);
  57. }
  58. carve::geom3d::Vector _unproject_5(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
  59. return carve::geom::VECTOR(p.y, CALC_Y(plane_eqn, p.y, p.x), p.x);
  60. }
  61. carve::geom3d::Vector _unproject_6(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
  62. return carve::geom::VECTOR(p.x, p.y, CALC_Z(plane_eqn, p.x, p.y));
  63. }
  64. } // namespace
  65. static carve::geom2d::P2 (*project_tab[2][3])(const carve::geom3d::Vector &) = {
  66. { &_project_1, &_project_2, &_project_3 },
  67. { &_project_4, &_project_5, &_project_6 }
  68. };
  69. static carve::geom3d::Vector (*unproject_tab[2][3])(const carve::geom2d::P2 &, const carve::geom3d::Plane &) = {
  70. { &_unproject_1, &_unproject_2, &_unproject_3 },
  71. { &_unproject_4, &_unproject_5, &_unproject_6 }
  72. };
  73. // only implemented for 3d.
  74. template<unsigned ndim>
  75. typename Face<ndim>::project_t Face<ndim>::getProjector(bool positive_facing, int axis) {
  76. return NULL;
  77. }
  78. template<>
  79. Face<3>::project_t Face<3>::getProjector(bool positive_facing, int axis) {
  80. return project_tab[positive_facing ? 1 : 0][axis];
  81. }
  82. template<unsigned ndim>
  83. typename Face<ndim>::unproject_t Face<ndim>::getUnprojector(bool positive_facing, int axis) {
  84. return NULL;
  85. }
  86. template<>
  87. Face<3>::unproject_t Face<3>::getUnprojector(bool positive_facing, int axis) {
  88. return unproject_tab[positive_facing ? 1 : 0][axis];
  89. }
  90. template<unsigned ndim>
  91. Face<ndim>::Face(const std::vector<const vertex_t *> &_vertices,
  92. bool delay_recalc) : tagable() {
  93. vertices = _vertices;
  94. edges.resize(nVertices(), NULL);
  95. if (!delay_recalc && !recalc()) { }
  96. }
  97. template<unsigned ndim>
  98. Face<ndim>::Face(const vertex_t *a,
  99. const vertex_t *b,
  100. const vertex_t *c,
  101. bool delay_recalc) : tagable() {
  102. vertices.reserve(3);
  103. vertices.push_back(a);
  104. vertices.push_back(b);
  105. vertices.push_back(c);
  106. edges.resize(3, NULL);
  107. if (!delay_recalc && !recalc()) { }
  108. }
  109. template<unsigned ndim>
  110. Face<ndim>::Face(const vertex_t *a,
  111. const vertex_t *b,
  112. const vertex_t *c,
  113. const vertex_t *d,
  114. bool delay_recalc) : tagable() {
  115. vertices.reserve(4);
  116. vertices.push_back(a);
  117. vertices.push_back(b);
  118. vertices.push_back(c);
  119. vertices.push_back(d);
  120. edges.resize(4, NULL);
  121. if (!delay_recalc && !recalc()) { }
  122. }
  123. template<unsigned ndim>
  124. void Face<ndim>::invert() {
  125. size_t n_verts = vertices.size();
  126. std::reverse(vertices.begin(), vertices.end());
  127. if (project != NULL) {
  128. plane_eqn.negate();
  129. int da = carve::geom::largestAxis(plane_eqn.N);
  130. project = getProjector(plane_eqn.N.v[da] > 0, da);
  131. unproject = getUnprojector(plane_eqn.N.v[da] > 0, da);
  132. }
  133. std::reverse(edges.begin(), edges.end() - 1);
  134. for (size_t i = 0; i < n_verts; i++) {
  135. const vertex_t *v1 = vertices[i];
  136. const vertex_t *v2 = vertices[(i+1) % n_verts];
  137. CARVE_ASSERT((edges[i]->v1 == v1 && edges[i]->v2 == v2) || (edges[i]->v1 == v2 && edges[i]->v2 == v1));
  138. }
  139. }
  140. template<unsigned ndim>
  141. bool Face<ndim>::recalc() {
  142. aabb.fit(vertices.begin(), vertices.end(), vec_adapt_vertex_ptr());
  143. if (!carve::geom3d::fitPlane(vertices.begin(), vertices.end(), vec_adapt_vertex_ptr(), plane_eqn)) {
  144. return false;
  145. }
  146. int da = carve::geom::largestAxis(plane_eqn.N);
  147. project = getProjector(false, da);
  148. double A = carve::geom2d::signedArea(vertices, projector());
  149. if ((A < 0.0) ^ (plane_eqn.N.v[da] < 0.0)) {
  150. plane_eqn.negate();
  151. }
  152. project = getProjector(plane_eqn.N.v[da] > 0, da);
  153. unproject = getUnprojector(plane_eqn.N.v[da] > 0, da);
  154. return true;
  155. }
  156. template<unsigned ndim>
  157. Face<ndim> *Face<ndim>::init(const Face *base, const std::vector<const vertex_t *> &_vertices, bool flipped) {
  158. return init(base, _vertices.begin(), _vertices.end(), flipped);
  159. }
  160. template<unsigned ndim>
  161. bool Face<ndim>::containsPoint(const vector_t &p) const {
  162. if (!carve::math::ZERO(carve::geom::distance(plane_eqn, p))) return false;
  163. // return pointInPolySimple(vertices, projector(), (this->*project)(p));
  164. return carve::geom2d::pointInPoly(vertices, projector(), face::project(this, p)).iclass != POINT_OUT;
  165. }
  166. template<unsigned ndim>
  167. bool Face<ndim>::containsPointInProjection(const vector_t &p) const {
  168. return carve::geom2d::pointInPoly(vertices, projector(), face::project(this, p)).iclass != POINT_OUT;
  169. }
  170. template<unsigned ndim>
  171. bool Face<ndim>::simpleLineSegmentIntersection(const carve::geom::linesegment<ndim> &line,
  172. vector_t &intersection) const {
  173. if (!line.OK()) return false;
  174. carve::geom3d::Vector p;
  175. IntersectionClass intersects = carve::geom3d::lineSegmentPlaneIntersection(plane_eqn,
  176. line,
  177. p);
  178. if (intersects == INTERSECT_NONE || intersects == INTERSECT_BAD) {
  179. return false;
  180. }
  181. carve::geom2d::P2 proj_p(face::project(this, p));
  182. if (carve::geom2d::pointInPolySimple(vertices, projector(), proj_p)) {
  183. intersection = p;
  184. return true;
  185. }
  186. return false;
  187. }
  188. // XXX: should try to return a pre-existing vertex in the case of a
  189. // line-vertex intersection. as it stands, this code isn't used,
  190. // so... meh.
  191. template<unsigned ndim>
  192. IntersectionClass Face<ndim>::lineSegmentIntersection(const carve::geom::linesegment<ndim> &line,
  193. vector_t &intersection) const {
  194. if (!line.OK()) return INTERSECT_NONE;
  195. carve::geom3d::Vector p;
  196. IntersectionClass intersects = carve::geom3d::lineSegmentPlaneIntersection(plane_eqn,
  197. line,
  198. p);
  199. if (intersects == INTERSECT_NONE || intersects == INTERSECT_BAD) {
  200. return intersects;
  201. }
  202. carve::geom2d::P2 proj_p(face::project(this, p));
  203. carve::geom2d::PolyInclusionInfo pi = carve::geom2d::pointInPoly(vertices, projector(), proj_p);
  204. switch (pi.iclass) {
  205. case POINT_VERTEX:
  206. intersection = p;
  207. return INTERSECT_VERTEX;
  208. case POINT_EDGE:
  209. intersection = p;
  210. return INTERSECT_EDGE;
  211. case POINT_IN:
  212. intersection = p;
  213. return INTERSECT_FACE;
  214. case POINT_OUT:
  215. return INTERSECT_NONE;
  216. default:
  217. break;
  218. }
  219. return INTERSECT_NONE;
  220. }
  221. }
  222. }
  223. // explicit instantiations.
  224. template class carve::poly::Face<3>;