OpenWalnut  1.5.0dev
WMMeshToPoints.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <algorithm>
26 #include <memory>
27 #include <string>
28 #include <vector>
29 
30 #include "WMMeshToPoints.h"
31 #include "core/common/WPropertyHelper.h"
32 #include "core/common/math/WMath.h"
33 #include "core/dataHandler/WDataHandler.h"
34 #include "core/kernel/WKernel.h"
35 
36 // This line is needed by the module loader to actually find your module. You need to add this to your module too. Do NOT add a ";" here.
37 W_LOADABLE_MODULE( WMMeshToPoints )
38 
40  WModule()
41 {
42 }
43 
45 {
46  // Cleanup!
47 }
48 
49 std::shared_ptr< WModule > WMMeshToPoints::factory() const
50 {
51  return std::shared_ptr< WModule >( new WMMeshToPoints() );
52 }
53 
54 const char** WMMeshToPoints::getXPMIcon() const
55 {
56  return NULL;
57 }
58 
59 const std::string WMMeshToPoints::getName() const
60 {
61  return "Mesh To Points";
62 }
63 
64 const std::string WMMeshToPoints::getDescription() const
65 {
66  return "This module converts mesh data to points by using the mesh vertex points and colors.";
67 }
68 
70 {
71  // The input triangle mesh
72  m_meshInput = std::shared_ptr< WModuleInputData < WTriangleMesh > >(
73  new WModuleInputData< WTriangleMesh >( shared_from_this(), "mesh", "The mesh dataset" )
74  );
75 
76  // As properties, every connector needs to be added to the list of connectors.
78 
79  // the points
80  m_pointsOutput = std::shared_ptr< WModuleOutputData < WDataSetPoints > >(
81  new WModuleOutputData< WDataSetPoints >( shared_from_this(), "out", "The point data." )
82  );
83 
84  // As above: make it known.
86 
87  // call WModule's initialization
89 }
90 
92 {
93  m_propCondition = std::shared_ptr< WCondition >( new WCondition() );
94 
95  m_doRefinement = m_properties->addProperty( "Resample", "If enabled, the mesh is sampled more dense.", false, m_propCondition );
96  m_minDistance = m_properties->addProperty( "Min Distance",
97  "Minimal distance between two samples. If reached, iteration will stop.", 1.0,
99  m_maxIterations = m_properties->addProperty( "Max Iterations", "Maximum number of iterations.", 2, m_propCondition );
100 
101  // call WModule's initialization
103 }
104 
105 void refine( const osg::Vec3& v1, const osg::Vec3& v2, const osg::Vec3& v3, WDataSetPoints::VertexArray points,
106  size_t c, const size_t& maxCount, const double& minDistance )
107 {
108  // add first verticies
109  if( c == 0 )
110  {
111  points->push_back( v1.x() );
112  points->push_back( v1.y() );
113  points->push_back( v1.z() );
114  points->push_back( v2.x() );
115  points->push_back( v2.y() );
116  points->push_back( v2.z() );
117  points->push_back( v3.x() );
118  points->push_back( v3.y() );
119  points->push_back( v3.z() );
120  }
121 
122  // abort
123  if( c == maxCount )
124  {
125  return;
126  }
127 
128  // get vertices in the middle of each edge
129  osg::Vec3 v12 = v1 + ( ( v2 - v1 ) * 0.5 );
130  osg::Vec3 v23 = v2 + ( ( v3 - v2 ) * 0.5 );
131  osg::Vec3 v31 = v3 + ( ( v1 - v3 ) * 0.5 );
132 
133  bool l12 = ( ( v2 - v1 ).length() < minDistance );
134  bool l23 = ( ( v3 - v2 ).length() < minDistance );
135  bool l31 = ( ( v1 - v3 ).length() < minDistance );
136  if( l12 + l23 + l31 >= 2 )
137  {
138  return;
139  }
140 
141  points->push_back( v12.x() );
142  points->push_back( v12.y() );
143  points->push_back( v12.z() );
144  points->push_back( v23.x() );
145  points->push_back( v23.y() );
146  points->push_back( v23.z() );
147  points->push_back( v31.x() );
148  points->push_back( v31.y() );
149  points->push_back( v31.z() );
150 
151  // build new triangle and refine this
152  refine( v1, v12, v31, points, c + 1, maxCount, minDistance );
153  refine( v2, v23, v12, points, c + 1, maxCount, minDistance );
154  refine( v3, v31, v23, points, c + 1, maxCount, minDistance );
155  refine( v12, v23, v31, points, c + 1, maxCount, minDistance );
156 }
157 
159 {
160  // get notified about data changes
161  m_moduleState.setResetable( true, true );
162  m_moduleState.add( m_meshInput->getDataChangedCondition() );
163  // Remember the condition provided to some properties in properties()? The condition can now be used with this condition set.
165 
166  ready();
167 
168  // main loop
169  while( !m_shutdownFlag() )
170  {
171  debugLog() << "Waiting ...";
173 
174  // woke up since the module is requested to finish?
175  if( m_shutdownFlag() )
176  {
177  break;
178  }
179 
180  // To query whether an input was updated, simply ask the input:
181  bool dataUpdated = m_meshInput->handledUpdate();
182  std::shared_ptr< WTriangleMesh > dataSet = m_meshInput->getData();
183  bool dataValid = ( dataSet != NULL );
184  bool propsChanged = m_doRefinement->changed() || m_maxIterations->changed() || m_minDistance->changed();
185 
186  // reset everything if input was disconnected/invalid
187  if( !dataValid )
188  {
189  debugLog() << "Resetting output.";
190  m_pointsOutput->reset();
191  continue;
192  }
193 
194  if( dataValid && !dataUpdated && !propsChanged )
195  {
196  continue;
197  }
198 
199  // progress indication
200  WProgress::SPtr progress = WProgress::SPtr( new WProgress( "Creating Points from mesh." ) );
201  m_progress->addSubProgress( progress );
202 
203  osg::ref_ptr< osg::Vec3Array > verts = dataSet->getVertexArray();
204  osg::ref_ptr< osg::Vec4Array > colors = dataSet->getVertexColorArray();
205  std::vector< size_t > faces = dataSet->getTriangles();
206 
207  debugLog() << "Creating point data. Num Points = " << verts->size() / 3 << ".";
208 
209  // convert to std array
210  WDataSetPoints::VertexArray vecConv( new WDataSetPoints::VertexArray::element_type() );
211  WDataSetPoints::ColorArray colConv( new WDataSetPoints::ColorArray::element_type() );
212 
213  WAssert( verts->size() == colors->size(), "Not enough colors for all vertices." );
214  for( size_t i = 0; i < faces.size(); i += 3 )
215  {
216  osg::Vec3 v1 = verts->operator[]( faces[ i + 0 ] );
217  osg::Vec3 v2 = verts->operator[]( faces[ i + 1 ] );
218  osg::Vec3 v3 = verts->operator[]( faces[ i + 2 ] );
219 
220  refine( v1, v2, v3, vecConv, 0, m_doRefinement->get() ? m_maxIterations->get() : 0, m_minDistance->get() );
221  }
222 
223  // TriangleMesh is implemented in a very ugly way, causing the color array to be (0,0,0,0) for each color -> invisible points.
225  m_pointsOutput->updateData( result );
226 
227  progress->finish();
228  m_progress->removeSubProgress( progress );
229  }
230 }
231 
virtual void wait() const
Wait for the condition.
void setResetable(bool resetable=true, bool autoReset=true)
Sets the resetable flag.
virtual void add(std::shared_ptr< WCondition > condition)
Adds another condition to the set of conditions to wait for.
Class to encapsulate boost::condition_variable_any.
Definition: WCondition.h:42
Dataset to store a bunch of points without order or topology.
std::shared_ptr< WDataSetPoints > SPtr
Pointer to dataset.
std::shared_ptr< std::vector< float > > ColorArray
Colors for each vertex in VertexArray.
std::shared_ptr< std::vector< float > > VertexArray
List of vertex coordinates in term of components of vertices.
This modules takes a mesh and extracts its vertices to build a point dataset.
virtual const std::string getDescription() const
Gives back a description of this module.
virtual const char ** getXPMIcon() const
Get the icon for this module in XPM format.
virtual const std::string getName() const
Gives back the name of this module.
virtual void connectors()
Initialize the connectors this module is using.
virtual ~WMMeshToPoints()
Destructor.
virtual std::shared_ptr< WModule > factory() const
Due to the prototype design pattern used to build modules, this method returns a new instance of this...
virtual void moduleMain()
Entry point after loading the module.
std::shared_ptr< WModuleInputData< WTriangleMesh > > m_meshInput
The fiber dataset which is going to be used.
WPropBool m_doRefinement
If true, refinement is applied.
WMMeshToPoints()
Default constructor.
virtual void properties()
Initialize the properties for this module.
WPropDouble m_minDistance
Maximum number of iterations for refinement.
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
WPropInt m_maxIterations
Maximum number of iterations for refinement.
std::shared_ptr< WModuleOutputData< WDataSetPoints > > m_pointsOutput
The output connector used to provide the calculated point data to other modules.
Class offering an instantiate-able data connection between modules.
Class offering an instantiate-able data connection between modules.
Class representing a single module of OpenWalnut.
Definition: WModule.h:72
virtual void properties()
Initialize properties in this function.
Definition: WModule.cpp:212
wlog::WStreamedLogger debugLog() const
Logger instance for comfortable debug logging.
Definition: WModule.cpp:575
void addConnector(std::shared_ptr< WModuleInputConnector > con)
Adds the specified connector to the list of inputs.
Definition: WModule.cpp:108
std::shared_ptr< WProperties > m_properties
The property object for the module.
Definition: WModule.h:640
void ready()
Call this whenever your module is ready and can react on property changes.
Definition: WModule.cpp:505
WConditionSet m_moduleState
The internal state of the module.
Definition: WModule.h:703
std::shared_ptr< WProgressCombiner > m_progress
Progress indicator used as parent for all progress' of this module.
Definition: WModule.h:652
virtual void connectors()
Initialize connectors in this function.
Definition: WModule.cpp:208
Class managing progress inside of modules.
Definition: WProgress.h:42
std::shared_ptr< WProgress > SPtr
Shared pointer on a WProgress.
Definition: WProgress.h:48
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.