Developer Documentation
EdgeSelection.cc
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 /*===========================================================================*\
43  * *
44  * $Revision$ *
45  * $Author$ *
46  * $Date$ *
47  * *
48 \*===========================================================================*/
49 
50 #include "MeshObjectSelectionPlugin.hh"
51 
53 
54 //=========================================================
55 //==== Edge selections
56 //=========================================================
57 
58 void MeshObjectSelectionPlugin::selectEdges( int objectId , IdList _edgeList ) {
59 
60  if(_edgeList.empty() ) return;
61 
62  BaseObjectData* object = 0;
63  if ( ! PluginFunctions::getObject(objectId,object) ) {
64  emit log(LOGERR,tr("selectEdges : unable to get object") );
65  return;
66  }
67 
68  if ( object->dataType() == DATA_TRIANGLE_MESH )
69  MeshSelection::selectEdges(PluginFunctions::triMesh(object), _edgeList);
70  else if ( object->dataType() == DATA_POLY_MESH )
71  MeshSelection::selectEdges(PluginFunctions::polyMesh(object), _edgeList);
72  else {
73  emit log(LOGERR,tr("selectEdges : Unsupported object Type") );
74  return;
75  }
76 
77  QString selection = "selectEdges( ObjectId(" + QString::number(objectId) + ") , [ " + QString::number(_edgeList[0]);
78 
79  for ( uint i = 1 ; i < _edgeList.size(); ++i) {
80  selection += " , " + QString::number(_edgeList[i]);
81  }
82 
83  selection += " ] )";
84 
85  emit updatedObject(object->id(), UPDATE_SELECTION_EDGES );
86  emit scriptInfo( selection );
87 }
88 
89 //=========================================================
90 
91 void MeshObjectSelectionPlugin::unselectEdges( int objectId , IdList _edgeList ) {
92 
93  if(_edgeList.empty()) return;
94 
95  BaseObjectData* object;
96  if ( ! PluginFunctions::getObject(objectId,object) ) {
97  emit log(LOGERR,tr("unselectEdges : unable to get object") );
98  return;
99  }
100 
101  if ( object->dataType() == DATA_TRIANGLE_MESH )
102  MeshSelection::unselectEdges(PluginFunctions::triMesh(object), _edgeList);
103  else if ( object->dataType() == DATA_POLY_MESH )
104  MeshSelection::unselectEdges(PluginFunctions::polyMesh(object), _edgeList);
105  else {
106  emit log(LOGERR,tr("unselectEdges : Unsupported object Type") );
107  return;
108  }
109 
110  QString selection = "unselectVertices( ObjectId(" + QString::number(objectId) +") , [ " + QString::number(_edgeList[0]);
111 
112  for ( uint i = 1 ; i < _edgeList.size(); ++i) {
113  selection += " , " + QString::number(_edgeList[i]);
114  }
115 
116  selection += " ] )";
117 
118  emit updatedObject(object->id(), UPDATE_SELECTION_EDGES);
119  emit scriptInfo( selection );
120 }
121 
122 //=========================================================
123 
125 
126  BaseObjectData* object;
127  if ( ! PluginFunctions::getObject(objectId,object) ) {
128  emit log(LOGERR,tr("selectAllVertices : unable to get object") );
129  return;
130  }
131 
132  if ( object->dataType() == DATA_TRIANGLE_MESH )
133  MeshSelection::selectAllEdges(PluginFunctions::triMesh(object));
134  else if ( object->dataType() == DATA_POLY_MESH )
135  MeshSelection::selectAllEdges(PluginFunctions::polyMesh(object));
136  else {
137  emit log(LOGERR,tr("selectAllEdges : Unsupported object Type") );
138  return;
139  }
140 
141  emit updatedObject(object->id(), UPDATE_SELECTION_EDGES);
142  emit scriptInfo( "selectAllEdges( ObjectId(" + QString::number(objectId) + ") )" );
143 }
144 
145 //=========================================================
146 
148 
149  BaseObjectData* object;
150  if ( ! PluginFunctions::getObject(objectId,object) ) {
151  emit log(LOGERR,tr("clearEdgeSelection : unable to get object") );
152  return;
153  }
154 
155  if ( object->dataType() == DATA_TRIANGLE_MESH )
156  MeshSelection::clearEdgeSelection(PluginFunctions::triMesh(object));
157  else if ( object->dataType() == DATA_POLY_MESH )
158  MeshSelection::clearEdgeSelection(PluginFunctions::polyMesh(object));
159  else {
160  emit log(LOGERR,tr("clearEdgeSelection : Unsupported object Type") );
161  return;
162  }
163 
164  emit updatedObject(object->id(), UPDATE_SELECTION_EDGES);
165  emit scriptInfo( "clearEdgeSelection( ObjectId(" + QString::number(objectId) + ") )" );
166 }
167 
168 //=========================================================
169 
171 
172  BaseObjectData* object;
173  if ( ! PluginFunctions::getObject(objectId,object) ) {
174  emit log(LOGERR,tr("invertEdgeSelection : unable to get object") );
175  return;
176  }
177 
178  if ( object->dataType() == DATA_TRIANGLE_MESH )
179  MeshSelection::invertEdgeSelection(PluginFunctions::triMesh(object));
180  else if ( object->dataType() == DATA_POLY_MESH )
181  MeshSelection::invertEdgeSelection(PluginFunctions::polyMesh(object));
182  else {
183  emit log(LOGERR,tr("invertEdgeSelection : Unsupported object Type") );
184  return;
185  }
186 
187  emit updatedObject(object->id(), UPDATE_SELECTION_EDGES);
188  emit scriptInfo( "invertEdgeSelection( ObjectId(" + QString::number(objectId) + ") )" );
189 }
190 
191 //=========================================================
192 
194 
195  BaseObjectData* object;
196  if ( ! PluginFunctions::getObject(objectId,object) ) {
197  emit log(LOGERR,tr("selectBoundaryEdges : unable to get object") );
198  return;
199  }
200 
201  if ( object->dataType() == DATA_TRIANGLE_MESH )
202  MeshSelection::selectBoundaryEdges(PluginFunctions::triMesh(object));
203  else if ( object->dataType() == DATA_POLY_MESH )
204  MeshSelection::selectBoundaryEdges(PluginFunctions::polyMesh(object));
205  else {
206  emit log(LOGERR,tr("selectBoundaryEdges : Unsupported object Type") );
207  return;
208  }
209 
210  emit updatedObject(object->id(), UPDATE_SELECTION_EDGES);
211  emit scriptInfo( "selectBoundaryEdges( ObjectId(" + QString::number(objectId) + ") )" );
212 }
213 
214 //=========================================================
215 
217 
218  BaseObjectData* object = 0;
219  if (!PluginFunctions::getObject(_objectId,object)) {
220  emit log(LOGERR,tr("deleteEdgeSelection: unable to get object"));
221  return;
222  }
223 
224  if (object->dataType() == DATA_TRIANGLE_MESH)
226  else if (object->dataType() == DATA_POLY_MESH)
228  else {
229  emit log(LOGERR,tr("deleteEdgeSelection: Unsupported object Type"));
230  return;
231  }
232 
233  emit updatedObject(object->id(), UPDATE_ALL);
234  emit scriptInfo("deleteEdgeSelection(ObjectId(" + QString::number(_objectId) + "))");
235 }
236 
237 //=========================================================
238 
240  return createMeshFromSelection(_objectId, edgeType_ );
241 }
242 
243 //=========================================================
244 
246 
247  BaseObjectData* object;
248  if ( ! PluginFunctions::getObject(objectId,object) ) {
249  emit log(LOGERR,tr("getEdgeSelection : unable to get object") );
250  return IdList(0);
251  }
252 
253  emit scriptInfo( "getEdgeSelection( ObjectId(" + QString::number(objectId) + ") )" );
254 
255  if ( object->dataType() == DATA_TRIANGLE_MESH )
256  return MeshSelection::getEdgeSelection(PluginFunctions::triMesh(object));
257  else if ( object->dataType() == DATA_POLY_MESH )
258  return MeshSelection::getEdgeSelection(PluginFunctions::polyMesh(object));
259  else {
260  emit log(LOGERR,tr("getEdgeSelection : Unsupported object Type") );
261  return IdList(0);
262  }
263 
264  return IdList(0);
265 
266 }
267 
268 //=========================================================
269 
271 
272  IdList vertex_pairs;
273 
274  BaseObjectData* object = 0;
275  if ( !PluginFunctions::getObject(_id,object) ) {
276  emit log(LOGERR,tr("Cannot find object for id ") + QString::number(_id));
277  return IdList(0);
278  }
279 
280  if(object->dataType() == DATA_TRIANGLE_MESH) {
281 
282  TriMeshObject* obj = 0;
283  if(!PluginFunctions::getObject(_id, obj)) {
284  emit log(LOGERR, "Could not get mesh object!");
285  return IdList(0);
286  }
287 
288  TriMesh* mesh = obj->mesh();
289 
290  for(IdList::const_iterator it = _edges.begin(); it != _edges.end(); ++it) {
291  vertex_pairs.push_back(mesh->from_vertex_handle(mesh->halfedge_handle(TriMesh::EdgeHandle(*it), 0)).idx());
292  vertex_pairs.push_back(mesh->to_vertex_handle(mesh->halfedge_handle(TriMesh::EdgeHandle(*it), 0)).idx());
293  }
294 
295  } else if(object->dataType() == DATA_POLY_MESH) {
296 
297  PolyMeshObject* obj = 0;
298  if(!PluginFunctions::getObject(_id, obj)) {
299  emit log(LOGERR, "Could not get mesh object!");
300  return IdList(0);
301  }
302 
303  PolyMesh* mesh = obj->mesh();
304 
305  for(IdList::const_iterator it = _edges.begin(); it != _edges.end(); ++it) {
306  vertex_pairs.push_back(mesh->from_vertex_handle(mesh->halfedge_handle(TriMesh::EdgeHandle(*it), 0)).idx());
307  vertex_pairs.push_back(mesh->to_vertex_handle(mesh->halfedge_handle(TriMesh::EdgeHandle(*it), 0)).idx());
308  }
309  }
310 
311  return vertex_pairs;
312 }
313 
314 //=========================================================
315 
317 
318  if(_vertices.size() % 2 != 0) {
319  emit log(LOGERR, "Number of vertices is not even!");
320  return IdList(0);
321  }
322 
323  IdList edges;
324 
325  BaseObjectData* object = 0;
326  if ( !PluginFunctions::getObject(_id,object) ) {
327  emit log(LOGERR,tr("Cannot find object for id ") + QString::number(_id));
328  return IdList(0);
329  }
330 
331  if(object->dataType() == DATA_TRIANGLE_MESH) {
332 
333  TriMeshObject* obj = 0;
334  if(!PluginFunctions::getObject(_id, obj)) {
335  emit log(LOGERR, "Could not get mesh object!");
336  return IdList(0);
337  }
338 
339  TriMesh* mesh = obj->mesh();
340 
341  for(IdList::const_iterator it = _vertices.begin(); it != _vertices.end(); it+=2) {
343  if(!vh.is_valid()) continue;
344  for(TriMesh::VertexOHalfedgeIter voh_it = mesh->voh_iter(vh);
345  voh_it.is_valid(); ++voh_it) {
346  if(mesh->to_vertex_handle(*voh_it).idx() == *(it+1)) {
347  edges.push_back(mesh->edge_handle(*voh_it).idx());
348  continue;
349  }
350  }
351  }
352 
353  } else if(object->dataType() == DATA_POLY_MESH) {
354 
355  PolyMeshObject* obj = 0;
356  if(!PluginFunctions::getObject(_id, obj)) {
357  emit log(LOGERR, "Could not get mesh object!");
358  return IdList(0);
359  }
360 
361  PolyMesh* mesh = obj->mesh();
362 
363  for(IdList::const_iterator it = _vertices.begin(); it != _vertices.end(); it+=2) {
365  if(!vh.is_valid()) continue;
366  for(PolyMesh::VertexOHalfedgeIter voh_it = mesh->voh_iter(vh);
367  voh_it.is_valid(); ++voh_it) {
368  if(mesh->to_vertex_handle(*voh_it).idx() == *(it+1)) {
369  edges.push_back(mesh->edge_handle(*voh_it).idx());
370  continue;
371  }
372  }
373  }
374  }
375 
376  return edges;
377 }
378 
379 //=========================================================
380 
381 void MeshObjectSelectionPlugin::colorizeEdgeSelection(int objectId, int r, int g, int b, int a ) {
382 
383  BaseObjectData* object;
384  if ( ! PluginFunctions::getObject(objectId,object) ) {
385  emit log(LOGERR,"colorizeEdgeSelection : unable to get object" );
386  return;
387  }
388 
389  if ( object->dataType() == DATA_TRIANGLE_MESH ) {
391  } else if ( object->dataType() == DATA_POLY_MESH ) {
393  } else {
394  emit log(LOGERR,"colorizeEdgeSelection : Unsupported object Type" );
395  return;
396  }
397 
398  emit scriptInfo( "colorizeEdgeSelection( ObjectId(" + QString::number(objectId) + "), "
399  + QString::number(r) + ", " + QString::number(g) + ", " + QString::number(b) + " )" );
400 
401  emit updatedObject(object->id(), UPDATE_COLOR);
402 }
403 
404 namespace {
405 
406 template<class MeshT>
407 inline bool edgeSelected(MeshT &mesh, typename MeshT::HalfedgeHandle he) {
408  return mesh.status(mesh.edge_handle(he)).selected();
409 }
410 template<class MeshT>
411 void traceEdgePath(MeshT &mesh, double threshold) {
412  typedef typename MeshT::HalfedgeIter HEIt;
413  typedef typename MeshT::VOHIter VOHIter;
414  typedef typename MeshT::HalfedgeHandle HEH;
415 
416  for (HEIt he_it = mesh.halfedges_begin(), he_end = mesh.halfedges_end();
417  he_it != he_end; ++he_it) {
418  if (edgeSelected(mesh, *he_it)) {
419 
420  HEH current_he = *he_it;
421 
422  for (bool tracing = true; tracing;) {
423  const typename MeshT::Normal cur_vec =
424  mesh.calc_edge_vector(current_he).normalized();
425  const HEH back_out_he = mesh.opposite_halfedge_handle(current_he);
426  HEH best_out_he;
427  double best_alignment = -std::numeric_limits<double>::infinity();
428  const typename MeshT::VertexHandle to_vtx =
429  mesh.to_vertex_handle(current_he);
430 
431  for (VOHIter voh_it = mesh.voh_begin(to_vtx),
432  voh_end = mesh.voh_end(to_vtx);
433  voh_it != voh_end; ++voh_it) {
434  if (*voh_it == back_out_he) continue;
435  if (edgeSelected(mesh, *voh_it)) {
436  tracing = false;
437  break;
438  }
439  const typename MeshT::Normal next_vec =
440  mesh.calc_edge_vector(*voh_it).normalized();
441  if (best_alignment < (cur_vec | next_vec)) {
442  best_alignment = (cur_vec | next_vec);
443  best_out_he = *voh_it;
444  }
445  }
446  if (tracing && best_alignment > threshold) {
447  current_he = best_out_he;
448  mesh.status(mesh.edge_handle(current_he)).set_selected(true);
449  } else {
450  tracing = false;
451  }
452  }
453  }
454  }
455 }
456 }
457 
458 void MeshObjectSelectionPlugin::traceEdgePath(int objectId, double threshold) {
459  BaseObjectData* object;
460  if ( ! PluginFunctions::getObject(objectId,object) ) {
461  emit log(LOGERR,"traceEdgePath: unable to get object" );
462  return;
463  }
464 
465  if ( object->dataType() == DATA_TRIANGLE_MESH ) {
466  ::traceEdgePath(*PluginFunctions::triMesh(object), threshold);
467  } else if ( object->dataType() == DATA_POLY_MESH ) {
468  ::traceEdgePath(*PluginFunctions::polyMesh(object), threshold);
469  } else {
470  emit log(LOGERR,"traceEdgePath: Unsupported object Type" );
471  return;
472  }
473 
474  emit scriptInfo(QString::fromUtf8("traceEdgePath(ObjectId(%1), %2)")
475  .arg(objectId).arg(threshold));
476 
477  emit updatedObject(object->id(), UPDATE_SELECTION_EDGES);
478 }
bool deleteSelection(MeshT *_mesh, PrimitiveType _primitiveType)
Delete all selected elements of a mesh.
Add normals to mesh item (vertices/faces)
Definition: Attributes.hh:87
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:73
bool getObject(int _identifier, BSplineCurveObject *&_object)
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
SelectionInterface::PrimitiveType edgeType_
Handle to selection environment.
void invertEdgeSelection(int objectId)
Unselect all Edges.
void selectAllEdges(int objectId)
Select all Edges.
int id() const
Definition: BaseObject.cc:201
void traceEdgePath(int objectId, double threshold)
Trace Edge Path.
void colorizeEdgeSelection(int objectId, int r, int g, int b, int a)
Colorize the edge selection.
MeshT * mesh()
return a pointer to the mesh
Definition: MeshObjectT.cc:351
int createMeshFromEdgeSelection(int _objectId)
Create a mesh containing the face selection of the given mesh.
void createMeshFromSelection(MeshT &_mesh, MeshT &_newMesh, PrimitiveType _primitiveType)
Create a new mesh from the selection.
void selectEdges(int objectId, IdList _vertexList)
Select given Edges.
const UpdateType UPDATE_COLOR(UpdateTypeSet(1)<< 10)
Colors have changed.
Functions for selection on a mesh.
void clearEdgeSelection(int objectId)
Invert the current edge selection.
IdList convertEdgesToVertexPairs(int _id, const IdList &_edges)
Convert edge ids to vertex pairs.
IdList convertVertexPairsToEdges(int _id, const IdList &_vertices)
Inverse of function above.
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:139
std::vector< int > IdList
Standard Type for id Lists used for scripting.
Definition: DataTypes.hh:192
void unselectEdges(int objectId, IdList _vertexList)
Unselect given Edges.
Type for a Meshobject containing a poly mesh.
Definition: PolyMesh.hh:70
Kernel::VertexOHalfedgeIter VertexOHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:166
void selectBoundaryEdges(int objectId)
select boundary edges
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
#define DATA_POLY_MESH
Definition: PolyMesh.hh:65
IdList getEdgeSelection(int objectId)
Return a list of all selected edges.
const UpdateType UPDATE_SELECTION_EDGES(UpdateTypeSet(1)<< 6)
Edge selection has changed.
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66
void colorizeSelection(MeshT *_mesh, PrimitiveType _primitiveTypes, int _red, int _green, int _blue, int _alpha)
Colorize the selection.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
void deleteEdgeSelection(int _objectId)
Delete edges that are currently selected.