Loading [MathJax]/extensions/TeX/AMSsymbols.js
DGtal 2.0.0
standardDigitalPolyhedronBuilder3D.cpp
Go to the documentation of this file.
1
16
29
30namespace DGtal {
61} // namespace DGtal {
62
64#include <iostream>
65#include <queue>
66#include "DGtal/base/Common.h"
67#include "DGtal/helpers/StdDefs.h"
68#include "DGtal/io/viewers/PolyscopeViewer.h"
69#include "DGtal/shapes/Shapes.h"
70#include "DGtal/shapes/SurfaceMesh.h"
71#include "DGtal/io/readers/SurfaceMeshReader.h"
72#include "DGtal/geometry/volumes/DigitalConvexity.h"
73#include "ConfigExamples.h"
74
76
77using namespace std;
78using namespace DGtal;
79typedef Z3i::Space Space;
80typedef Z3i::Integer Integer;
81typedef Z3i::KSpace KSpace;
82typedef Z3i::Domain Domain;
83typedef Z3i::SCell SCell;
84typedef Space::Point Point;
86typedef Space::RealVector RealVector;
87typedef Space::Vector Vector;
88typedef std::vector<Point> PointRange;
89
90// Convenient class to represent different types of arithmetic planes as a predicate.
91template < bool Naive, bool Symmetric >
96 MedianPlane() = default;
97 MedianPlane( const MedianPlane& other ) = default;
98 MedianPlane( MedianPlane&& other ) = default;
99 MedianPlane& operator=( const MedianPlane& other ) = default;
100 MedianPlane& operator=( MedianPlane&& other ) = default;
102 : N ( ( q - p ).crossProduct( r - p ) )
103 {
104 mu = N.dot( p );
105 omega = Naive ? N.norm( N.L_infty ) : N.norm( N.L_1 );
106 if ( Symmetric && ( ( omega & 1 ) == 0 ) ) omega += 1;
107 mu -= omega / 2;
108 }
109 bool operator()( const Point& p ) const
110 {
111 auto r = N.dot( p );
112 return ( mu <= r ) && ( r < mu+omega );
113 }
114};
115
116// Choose your plane !
117// typedef MedianPlane< true, false > Plane; //< Naive, thinnest possible
118// typedef MedianPlane< true, true > Plane; //< Naive, Symmetric
119// typedef MedianPlane< false, false > Plane; //< Standard
120typedef MedianPlane< false, true > Plane; //< Standard, Symmetric, thickest here
121
122int main( int argc, char** argv )
123{
124 trace.info() << "Usage: " << argv[ 0 ] << " <input.obj> <h> <view>" << std::endl;
125 trace.info() << "\tComputes a digital polyhedron from an OBJ file" << std::endl;
126 trace.info() << "\t- input.obj: choose your favorite mesh" << std::endl;
127 trace.info() << "\t- h [==1]: the digitization gridstep" << std::endl;
128 trace.info() << "\t- view [==31]: display vertices(1), common edges(2), positive side f edges(4), negative side f edges (8), faces(16)" << std::endl;
129 string filename = examplesPath + "samples/lion.obj";
130 std::string fn = argc > 1 ? argv[ 1 ] : filename; //< vol filename
131 double h = argc > 2 ? atof( argv[ 2 ] ) : 1.0;
132 int view = argc > 3 ? atoi( argv[ 3 ] ) : 31;
133 // Read OBJ file
134 std::ifstream input( fn.c_str() );
137 if ( ! ok )
138 {
139 trace.error() << "Unable to read obj file : " << fn << std::endl;
140 return 1;
141 }
142
143 typedef PolyscopeViewer<Space,KSpace> MViewer;
144 MViewer viewer;
145
146 Point lo(-500,-500,-500);
147 Point up(500,500,500);
148 DigitalConvexity< KSpace > dconv( lo, up );
150
151 auto vertices = std::vector<Point>( surfmesh.nbVertices() );
152 for ( auto v : surfmesh )
153 {
154 RealPoint p = (1.0 / h) * surfmesh.position( v );
155 Point q ( (Integer) round( p[ 0 ] ),
156 (Integer) round( p[ 1 ] ),
157 (Integer) round( p[ 2 ] ) );
158 vertices[ v ] = q;
159 }
160 std::set< Point > faces_set, pos_edges_set, neg_edges_set;
161 auto faceVertices = surfmesh.allIncidentVertices();
162
163 trace.beginBlock( "Checking face planarity" );
164 std::vector< Plane > face_planes;
165 face_planes.resize( surfmesh.nbFaces() );
166 bool planarity = true;
167 for ( int f = 0; f < surfmesh.nbFaces() && planarity; ++f )
168 {
169 PointRange X;
170 for ( auto v : faceVertices[ f ] )
171 X.push_back( vertices[ v ] );
172 face_planes[ f ] = Plane( X[ 0 ], X[ 1 ], X[ 2 ] );
173 for ( int v = 3; v < X.size(); v++ )
174 if ( ! face_planes[ f ]( X[ v ] ) )
175 {
176 trace.error() << "Face " << f << " is not planar." << std::endl;
177 planarity = false; break;
178 }
179 }
180 trace.endBlock();
181 if ( ! planarity ) return 1;
182 trace.beginBlock( "Computing polyhedron" );
183 for ( int f = 0; f < surfmesh.nbFaces(); ++f )
184 {
185 PointRange X;
186 for ( auto v : faceVertices[ f ] )
187 X.push_back( vertices[ v ] );
188 auto F = dconv.relativeEnvelope( X, face_planes[ f ], Algorithm::DIRECT );
189 faces_set.insert( F.cbegin(), F.cend() );
190 for ( int i = 0; i < X.size(); i++ )
191 {
192 PointRange Y { X[ i ], X[ (i+1)%X.size() ] };
193 if ( Y[ 1 ] < Y[ 0 ] ) std::swap( Y[ 0 ], Y[ 1 ] );
194 int idx1 = faceVertices[ f ][ i ];
195 int idx2 = faceVertices[ f ][ (i+1)%X.size() ];
196 // Variant (1): edges of both sides have many points in common
197 // auto A = dconv.relativeEnvelope( Y, face_planes[ f ], Algorithm::DIRECT );
198 // Variant (2): edges of both sides have much less points in common
199 auto A = dconv.relativeEnvelope( Y, F, Algorithm::DIRECT );
200 bool pos = idx1 < idx2;
201 (pos ? pos_edges_set : neg_edges_set).insert( A.cbegin(), A.cend() );
202 }
203 }
204 trace.endBlock();
205 std::vector< Point > face_points, common_edge_points, arc_points, final_arc_points ;
206 std::vector< Point > pos_edge_points, neg_edge_points, both_edge_points;
207 std::vector< Point > vertex_points = vertices;
208 std::sort( vertex_points.begin(), vertex_points.end() );
209 std::set_symmetric_difference( pos_edges_set.cbegin(), pos_edges_set.cend(),
210 neg_edges_set.cbegin(), neg_edges_set.cend(),
211 std::back_inserter( arc_points ) );
212 std::set_intersection( pos_edges_set.cbegin(), pos_edges_set.cend(),
213 neg_edges_set.cbegin(), neg_edges_set.cend(),
214 std::back_inserter( common_edge_points ) );
215 std::set_union( pos_edges_set.cbegin(), pos_edges_set.cend(),
216 neg_edges_set.cbegin(), neg_edges_set.cend(),
217 std::back_inserter( both_edge_points ) );
218 std::set_difference( faces_set.cbegin(), faces_set.cend(),
219 both_edge_points.cbegin(), both_edge_points.cend(),
220 std::back_inserter( face_points ) );
221 std::set_difference( pos_edges_set.cbegin(), pos_edges_set.cend(),
222 common_edge_points.cbegin(), common_edge_points.cend(),
223 std::back_inserter( pos_edge_points ) );
224 std::set_difference( neg_edges_set.cbegin(), neg_edges_set.cend(),
225 common_edge_points.cbegin(), common_edge_points.cend(),
226 std::back_inserter( neg_edge_points ) );
227 std::set_difference( common_edge_points.cbegin(), common_edge_points.cend(),
228 vertex_points.cbegin(), vertex_points.cend(),
229 std::back_inserter( final_arc_points ) );
230 auto total = vertex_points.size() + pos_edge_points.size()
231 + neg_edge_points.size()
232 + final_arc_points.size() + face_points.size();
233 trace.info() << "#vertex points=" << vertex_points.size() << std::endl;
234 trace.info() << "#pos edge points=" << pos_edge_points.size() << std::endl;
235 trace.info() << "#neg edge points=" << neg_edge_points.size() << std::endl;
236 trace.info() << "#arc points=" << final_arc_points.size() << std::endl;
237 trace.info() << "#face points=" << face_points.size() << std::endl;
238 trace.info() << "#total points=" << total << std::endl;
239
240 // display everything
241 Color colors[] =
243 Color::Magenta, Color( 200, 200, 200 ) };
244 if ( view & 0x1 )
245 {
246 viewer.drawColor( colors[ 0 ] );
247 viewer.drawColor( colors[ 0 ] );
248 for ( auto p : vertices ) viewer << p;
249 }
250 if ( view & 0x2 )
251 {
252 viewer.drawColor( colors[ 3 ] );
253 viewer.drawColor( colors[ 3 ] );
254 for ( auto p : final_arc_points ) viewer << p;
255 }
256 if ( view & 0x4 )
257 {
258 viewer.drawColor( colors[ 1 ] );
259 viewer.drawColor( colors[ 1 ] );
260 for ( auto p : pos_edge_points ) viewer << p;
261 }
262 if ( view & 0x8 )
263 {
264 viewer.drawColor( colors[ 2 ] );
265 viewer.drawColor( colors[ 2 ] );
266 for ( auto p : neg_edge_points ) viewer << p;
267 }
268 if ( view & 0x10 )
269 {
270 viewer.drawColor( colors[ 4 ] );
271 viewer.drawColor( colors[ 4 ] );
272 for ( auto p : face_points ) viewer << p;
273 }
274
275 viewer.show();
276 return 0;
277
278}
279// //
281
Structure representing an RGB triple with alpha component.
Definition Color.h:77
static const Color Red
Definition Color.h:425
static const Color Black
Definition Color.h:422
static const Color Blue
Definition Color.h:428
static const Color Magenta
Definition Color.h:430
PointVector< dim, Integer > Point
Definition SpaceND.h:110
PointVector< dim, double > RealPoint
Definition SpaceND.h:117
PointVector< dim, double > RealVector
Definition SpaceND.h:121
PointVector< dim, Integer > Vector
Definition SpaceND.h:113
SurfMesh surfmesh
Z3i::SCell SCell
std::vector< Point > PointRange
HyperRectDomain< Space > Domain
Definition StdDefs.h:172
SpaceND< 3, Integer > Space
Definition StdDefs.h:144
KhalimskySpaceND< 3, Integer > KSpace
Definition StdDefs.h:146
KSpace::SCell SCell
Definition StdDefs.h:149
DGtal::int32_t Integer
Definition StdDefs.h:143
DGtal is the top-level namespace which contains all DGtal functions and types.
auto crossProduct(PointVector< 3, LeftEuclideanRing, LeftContainer > const &lhs, PointVector< 3, RightEuclideanRing, RightContainer > const &rhs) -> decltype(DGtal::constructFromArithmeticConversion(lhs, rhs))
Cross product of two 3D Points/Vectors.
Trace trace
STL namespace.
MedianPlane< false, true > Plane
static bool readOBJ(std::istream &input, SurfaceMesh &smesh)
MedianPlane(const MedianPlane &other)=default
MedianPlane(Point p, Point q, Point r)
MedianPlane(MedianPlane &&other)=default
MedianPlane & operator=(MedianPlane &&other)=default
MedianPlane()=default
bool operator()(const Point &p) const
MedianPlane & operator=(const MedianPlane &other)=default
int main()
Definition testBits.cpp:56
void insert(VContainer1 &c1, LContainer2 &c2, unsigned int idx, double v)
PointVector< 3, double > RealPoint