Developer Documentation
PolyLinePluginT_impl.hh
1/*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40\*===========================================================================*/
41
42#define POLYLINEPLUGIN_CC
43
44#include "PolyLinePlugin.hh"
45#include <queue>
46
47//------------------------------------------------------------------------------
48
49
50template< class MeshT >
51bool cutted(MeshT& _mesh, typename MeshT::HalfedgeHandle _he, const ACG::Vec3d _planeNormal, const ACG::Vec3d _planePoint, ACG::Vec3d* _point = 0) {
52
53 //get intersection point with plane
54 typename MeshT::Point p0 = _mesh.point( _mesh.from_vertex_handle(_he) );
55 typename MeshT::Point p1 = _mesh.point( _mesh.to_vertex_handle(_he) );
56
57 typename MeshT::Point u = p1 - p0;
58 typename MeshT::Point w = p0 - _planePoint;
59
60 double D = (_planeNormal | u);
61 double N = - (_planeNormal | w);
62
63 // compute intersect parameter
64 double sI = N / D;
65
66 if ( _point ) {
67 *_point = p0 + sI * u;
68 }
69 return (sI >= 0.0 && sI <= 1.0 );
70}
71
72//------------------------------------------------------------------------------
73
83template< class MeshT >
84std::vector< ACG::Vec3d > getIntersectionLoop( MeshT* _mesh,
85 uint _fh,
86 ACG::Vec3d _planeNormal,
87 ACG::Vec3d _planePoint,
88 bool& _closed ) {
89
91 _mesh->get_property_handle(cut,"Plane Cut Property" );
92
93 typename MeshT::FaceHandle fh ( _fh );
94
95 typename OpenMesh::SmartFaceHandle current_face = make_smart(typename MeshT::FaceHandle(_fh), _mesh);
96
97 bool stop = false;
98 bool nothingFound = true;
99 int expansionLevel = 0;
100 bool flip_dir = false;
101 _closed = true;
102
103 std::vector< ACG::Vec3d > linePoints;
104
105 std::vector< typename MeshT::FaceHandle > startCandidates;
106 std::vector< typename MeshT::FaceHandle > expandable;
107 expandable.push_back( fh );
108
109 while (!stop) {
110 stop = true;
111
112 // First check the face we are in
113 for (auto fhe_it : current_face.halfedges()){
114 if ( _mesh->property(cut,fhe_it) )
115 continue;
116
117 typename MeshT::Point p0 = _mesh->point( fhe_it.from() );
118 typename MeshT::Point p1 = _mesh->point( fhe_it.to() );
119
120 typename MeshT::Point u = p1 - p0;
121 typename MeshT::Point w = p0 - _planePoint;
122
123 double D = (_planeNormal | u);
124 double N = - (_planeNormal | w);
125
126 // compute intersect param
127 double sI = N / D;
128 if (sI < 0.0 || sI > 1.0 ) // intersection on ray, but not within line segment
129 continue;
130
131 nothingFound = false;
132
133 stop = false;
134 _mesh->property(cut,fhe_it) = true;
135 _mesh->property(cut,fhe_it.opp()) = true;
136 current_face = fhe_it.opp().face();
137
138 if (!current_face.is_valid())
139 stop = true;
140
141 typename MeshT::Point cutPoint = p0 + sI * u;
142
143 // add new point
144 if ( !flip_dir )
145 linePoints.push_back(cutPoint);
146 else {
147 linePoints.insert( linePoints.begin() , cutPoint );
148 _closed = false;
149 }
150
151 break;
152 }
153
154 if ( stop ){
155 if ( nothingFound ){
156 if ( startCandidates.empty() ){
157
158 if (expansionLevel > 3 )
159 std::cerr << "Expanded" << expansionLevel << "rings but still nothing found!" << std::endl;
160 else{
161
162 //add the "expansionLevel"-ring of the start-face to the start candidates
163 for (uint i=0; i < expandable.size(); i++)
164 for( typename MeshT::FaceFaceIter ff_it(*_mesh, expandable[i]); ff_it.is_valid(); ++ff_it )
165 startCandidates.push_back( *ff_it );
166
167 expandable.clear();
168 expansionLevel++;
169 }
170 }
171
172 if ( !startCandidates.empty() ){
173 fh = startCandidates.back();
174 expandable.push_back( fh );
175 startCandidates.pop_back();
176 stop = false;
177 }
178
179 }else if (! flip_dir ){
180 flip_dir = true;
181 stop = false;
182 }
183
184 current_face = make_smart(fh, _mesh);
185 }
186 }
187
188 return linePoints;
189
190}
191
192//------------------------------------------------------------------------------
193
203template< class MeshT >
204std::vector< ACG::Vec3d > PolyLinePlugin::getIntersectionPoints( MeshT* _mesh,
205 uint _fh,
206 ACG::Vec3d _planeNormal,
207 ACG::Vec3d _planePoint,
208 bool& _closed ) {
210 _mesh->add_property(cut,"Plane Cut Property" );
211
212 for (auto he_it : _mesh->halfedges())
213 _mesh->property( cut, he_it ) = false;
214
215 std::vector< ACG::Vec3d > linePoints = getIntersectionLoop(_mesh,_fh,_planeNormal,_planePoint,_closed);
216
217 _mesh->remove_property( cut );
218
219 return linePoints;
220}
221
222//------------------------------------------------------------------------------
223
231template< class MeshT >
232typename MeshT::EdgeHandle
233PolyLinePlugin::getCuttedEdge(MeshT& _mesh, ACG::Vec3d& _planeNormal, ACG::Vec3d& _planePoint) {
234
235 typename MeshT::Scalar minDistance = FLT_MAX;
236 typename MeshT::EdgeHandle minEdge(-1);
237
238 for (auto e_it : _mesh.edges()){
239
240 typename OpenMesh::SmartHalfedgeHandle hh = e_it.h0();
241
242 //get intersection point with plane
243 typename MeshT::Point p0 = _mesh.point( hh.from() );
244 typename MeshT::Point p1 = _mesh.point( hh.to() );
245
246 typename MeshT::Point u = p1 - p0;
247 typename MeshT::Point w = p0 - _planePoint;
248
249 double D = (_planeNormal | u);
250 double N = - (_planeNormal | w);
251
252 // compute intersect param
253 double sI = N / D;
254
255 if (sI >= 0.0 && sI <= 1.0 ){
256
257 typename MeshT::Point cutPoint = p0 + sI * u;
258
259 typename MeshT::Scalar dist = (cutPoint - _planePoint).sqrnorm();
260
261 if ( dist < minDistance ){
262
263 minDistance = dist;
264 minEdge = e_it;
265 }
266 }
267 }
268
269 return minEdge;
270}
271
272
273
274
282template< class MeshT >
283std::vector< std::vector<ACG::Vec3d> > PolyLinePlugin::getMultipleIntersectionPoints( MeshT* _mesh,
284 ACG::Vec3d _planeNormal,
285 ACG::Vec3d _planePoint) {
286
287 std::vector< std::vector<ACG::Vec3d> > lines;
288
290 _mesh->add_property(cut,"Plane Cut Property" );
291
292 std::queue< typename OpenMesh::SmartEdgeHandle > queue;
293
294 // Mark all edges as not cut, and remember cutted edges as starting points if we get multiple unconnected cuts
295 for(auto e_it : _mesh->edges()) {
296
297 // Remember cutted edge
298 if ( cutted(*_mesh, e_it.h0(),_planeNormal, _planePoint, 0) ) {
299 queue.push(e_it);
300 }
301
302 //Initialize halfedge Property
303 _mesh->property( cut, e_it.h0() ) = false;
304 _mesh->property( cut, e_it.h1() ) = false;
305
306 }
307
308
309 // Used to catch all connected components
310 while( !queue.empty() ) {
311
312 // Get next element from queue
313 typename OpenMesh::SmartHalfedgeHandle hh = queue.front().h0();
314 queue.pop();
315
316 // Already visited so skip this one
317 if ( _mesh->property(cut,hh) )
318 continue;
319
320 // Get the adjacent face
321 typename MeshT::FaceHandle fh = hh.face();
322
323 // If we are at a boundary, get next
324 if ( !fh.is_valid() ) {
325 fh = hh.opp().face();
326 }
327
328 // No face anywhere at this edge? This should not happen, so we just skip the edge
329 if ( !fh.is_valid() )
330 continue;
331
332
333 bool closed = false;
334
335 // Compute the polyline from current face
336 lines.push_back(getIntersectionLoop(_mesh,fh.idx(),_planeNormal,_planePoint,closed) );
337
338 }
339
340 // Cleanup
341 _mesh->remove_property( cut );
342
343 return lines;
344
345}
346
347
348
bool is_valid() const
The handle is valid iff the index is not negative.
Definition: Handles.hh:72
VertexHandle from_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge starts from.
VertexHandle to_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge points to.
MeshT::EdgeHandle getCuttedEdge(MeshT &_mesh, ACG::Vec3d &_planeNormal, ACG::Vec3d &_planePoint)
get an edge of the mesh that is cut by the plane
std::vector< ACG::Vec3d > getIntersectionPoints(MeshT *_mesh, uint _fh, ACG::Vec3d _planeNormal, ACG::Vec3d _planePoint, bool &_closed)
get the points from the closest connected intersection between mesh and plane
std::vector< std::vector< ACG::Vec3d > > getMultipleIntersectionPoints(MeshT *_mesh, ACG::Vec3d _planeNormal, ACG::Vec3d _planePoint)
get all points from the intersection between mesh and plane
SmartVertexHandle make_smart(VertexHandle _vh, const PolyConnectivity *_mesh)
Creats a SmartVertexHandle from a VertexHandle and a Mesh.
PolyConnectivity::ConstFaceHalfedgeRange halfedges() const
Returns a range of halfedges of the face (PolyConnectivity::fh_range())
SmartFaceHandle face() const
Returns incident face of halfedge.
SmartVertexHandle from() const
Returns vertex at start of halfedge.
SmartHalfedgeHandle opp() const
Returns opposite halfedge handle.
SmartVertexHandle to() const
Returns vertex pointed to by halfedge.