DGtal 1.3.0
Loading...
Searching...
No Matches
Display2DFactory.ih
1/**
2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *
15 **/
16
17/**
18 * @file Display2DFactory.ih
19 * @author Martial Tola <http://liris.cnrs.fr/martial.tola/>
20 * @date mercredi 28 septembre 2011
21 *
22 * @brief
23 *
24 * Implementation of inline methods defined in Display2DFactory.h
25 *
26 * This file is part of the DGtal library.
27 */
28
29#include <DGtal/io/Style2DFactory.h>
30#include <DGtal/io/colormaps/GradientColorMap.h>
31#include <DGtal/topology/CanonicSCellEmbedder.h>
32
33///////////////////////////////////////////////////////////////////////////////
34// Implementation of inline methods //
35
36
37///////////////////////////////////////////////////////////////////////////////
38// Implementation of inline functions and external operators //
39template <DGtal::Dimension dim, typename TInteger>
40inline
41void
42DGtal::Display2DFactory::drawDECSignedKhalimskyCell(DGtal::Board2D& board, const DGtal::SignedKhalimskyCell<dim, TInteger>& sk)
43{
44 drawDECSignedKhalimskyCell( board, sk.preCell() );
45}
46
47template <DGtal::Dimension dim, typename TInteger>
48inline
49void
50DGtal::Display2DFactory::drawDECSignedKhalimskyCell(DGtal::Board2D& board, const DGtal::SignedKhalimskyPreCell<dim, TInteger>& sk)
51{
52 FATAL_ERROR( dim == 2 );
53
54 using KPS = DGtal::Z2i::KPreSpace;
55 const KPS K{};
56
57 //FIXME: as for Display3D models, embedder should be factorized
58 //and not instantiated at each call.
59 using Embedder = DGtal::CanonicSCellEmbedder<KPS>;
60 const Embedder embedder( K );
61
62 const Embedder::RealPoint coords = embedder( sk );
63 const double x = coords[0];
64 const double y = coords[1];
65 const double retract = 0.1f;
66 const bool xodd = ( KPS::sKCoord(sk, 0) & 1 );
67 const bool yodd = ( KPS::sKCoord(sk, 1) & 1 );
68 board.setLineWidth( .5 );
69 board.setPenColor( DGtal::Color::Black );
70 board.setLineStyle( Board2D::Shape::SolidStyle );
71 if (!xodd && !yodd)
72 {
73 if ( KPS::sSign(sk) == KPS::NEG ) DGtal::trace.warning() << "negative khalimsky 0-cell" << std::endl;
74 board.drawCircle(x, y, retract);
75 return;
76 }
77 if (xodd && !yodd)
78 {
79 if ( KPS::sSign(sk) == KPS::NEG ) board.drawTriangle(x-.5f, y-retract, x-.5f, y+retract, x+.5f, y);
80 else board.drawTriangle(x+.5f, y+retract, x+.5f, y-retract, x-.5f, y);
81 return;
82 }
83 if (!xodd && yodd)
84 {
85 if ( KPS::sSign(sk) == KPS::NEG ) board.drawTriangle(x-retract, y-.5f, x+retract, y-.5f, x, y+.5);
86 else board.drawTriangle(x+retract, y+.5f, x-retract, y+.5f, x, y-.5);
87 return;
88 }
89 if ( KPS::sSign(sk) == KPS::NEG ) DGtal::trace.warning() << "negative khalimsky 2-cell" << std::endl;
90 board.drawRectangle(x-.5, y+.5, 1, 1);
91}
92
93// DiscreteExteriorCalculus
94template <DGtal::Dimension dimEmbedded, DGtal::Dimension dimAmbient, typename TLinearAlgebraBackend, typename TInteger>
95inline
96void
97DGtal::Display2DFactory::draw(DGtal::Board2D& board, const DGtal::DiscreteExteriorCalculus<dimEmbedded, dimAmbient, TLinearAlgebraBackend, TInteger>& calculus)
98{
99 BOOST_STATIC_ASSERT(( dimAmbient == 2 ));
100
101 typedef DiscreteExteriorCalculus<dimEmbedded, dimAmbient, TLinearAlgebraBackend, TInteger> Calculus;
102 typedef typename Calculus::ConstIterator ConstIterator;
103 typedef typename Calculus::Cell Cell;
104 typedef typename Calculus::SCell SCell;
105 typedef typename Calculus::KSpace KSpace;
106
107 board.setFillColor( DGtal::Color(128,128,128) );
108 for (int kk=2; kk>=0; kk--)
109 for (ConstIterator ci=calculus.begin(), cie=calculus.end(); ci!=cie; ci++)
110 {
111 const Cell& cell = ci->first;
112 if (calculus.myKSpace.uDim(cell) != static_cast<DGtal::Dimension>(kk)) continue;
113
114 const bool& flipped = ci->second.flipped;
115 const SCell displayed_cell = calculus.myKSpace.signs(cell, flipped ? KSpace::NEG : KSpace::POS);
116
117 drawDECSignedKhalimskyCell(board, displayed_cell);
118 }
119}
120// DiscreteExteriorCalculus
121
122// KForm
123template <typename TCalculus, DGtal::Order order, DGtal::Duality duality>
124inline
125void
126DGtal::Display2DFactory::draw(DGtal::Board2D& board, const DGtal::KForm<TCalculus, order, duality>& kform)
127{
128 BOOST_STATIC_ASSERT(( TCalculus::dimensionAmbient == 2 ));
129 ASSERT( kform.myCalculus );
130
131 typedef typename TCalculus::Scalar Scalar;
132 typedef typename TCalculus::Index Index;
133
134 Scalar cmap_min = 0;
135 Scalar cmap_max = 0;
136 DGtal::ColorGradientPreset cmap_preset = CMAP_JET;
137 int cmap_repeat = 0;
138
139 {
140 const DGtal::KFormStyle2D* style = dynamic_cast<const DGtal::KFormStyle2D*>(board.myStyles["KForm"].get());
141 if (style)
142 {
143 cmap_min = style->cmap_min;
144 cmap_max = style->cmap_max;
145 cmap_preset = style->cmap_preset;
146 cmap_repeat = style->cmap_repeat;
147 }
148 }
149
150 if (cmap_min == 0 && cmap_max == 0)
151 {
152 bool first = true;
153 for (Index index=0; index<kform.myContainer.rows(); index++)
154 {
155 const Scalar value = kform.myContainer(index);
156 if (!std::isfinite(value)) continue;
157 if (first || cmap_min > value) cmap_min = value;
158 if (first || cmap_max < value) cmap_max = value;
159 first = false;
160 }
161 }
162
163 if (cmap_min == cmap_max) cmap_max += 1;
164
165 board.setLineWidth( .5 );
166
167 if (cmap_repeat < 1 && cmap_preset == DGtal::CMAP_JET)
168 {
169 typedef typename DGtal::GradientColorMap<Scalar, DGtal::CMAP_JET> ColorMap;
170 const ColorMap colormap(cmap_min, cmap_max);
171 drawWithColorMap(board, kform, colormap);
172 return;
173 }
174
175 if (cmap_repeat < 1 && cmap_preset == DGtal::CMAP_GRAYSCALE)
176 {
177 typedef typename DGtal::GradientColorMap<Scalar, DGtal::CMAP_GRAYSCALE> ColorMap;
178 const ColorMap colormap(cmap_min, cmap_max);
179 drawWithColorMap(board, kform, colormap);
180 return;
181 }
182
183 // @todo FIXME add other colomaps
184 if (cmap_repeat < 1)
185 {
186 typedef typename DGtal::GradientColorMap<Scalar, DGtal::CMAP_HOT> ColorMap;
187 const ColorMap colormap(cmap_min, cmap_max);
188 drawWithColorMap(board, kform, colormap);
189 return;
190 }
191
192 ASSERT(cmap_repeat >= 1);
193 typedef typename DGtal::HueShadeColorMap<Scalar, DGtal::CMAP_HOT> ColorMap;
194 const ColorMap colormap(cmap_min, cmap_max, cmap_repeat);
195 drawWithColorMap(board, kform, colormap);
196}
197
198template <typename TCalculus, DGtal::Order order, DGtal::Duality duality, typename TColorMap>
199inline
200void
201DGtal::Display2DFactory::drawWithColorMap(DGtal::Board2D& board, const DGtal::KForm<TCalculus, order, duality>& kform, const TColorMap& colormap)
202{
203 typedef typename TCalculus::Scalar Scalar;
204 typedef typename TCalculus::SCell SCell;
205
206 for (typename TCalculus::Index index=0; index<kform.length(); index++)
207 {
208 const SCell displayed_cell = kform.getSCell(index);
209 const Scalar displayed_value = kform.myContainer(index);
210
211 if (std::isfinite(displayed_value)) board.setFillColor( colormap(displayed_value) );
212 else continue;
213
214 drawDECSignedKhalimskyCell(board, displayed_cell);
215 }
216}
217// KForm
218
219// VectorField
220template <typename TCalculus, DGtal::Duality duality>
221void
222DGtal::Display2DFactory::draw(DGtal::Board2D& board, const DGtal::VectorField<TCalculus, duality>& vector_field)
223{
224 BOOST_STATIC_ASSERT(( TCalculus::dimensionAmbient == 2 ));
225 ASSERT( vector_field.myCalculus );
226
227 typedef typename DGtal::VectorField<TCalculus, duality>::Vector Vector;
228
229 typename TCalculus::Scalar scale = .25;
230 typename TCalculus::Scalar epsilon = 1e-8;
231
232 {
233 const DGtal::VectorFieldStyle2D* style = dynamic_cast<const DGtal::VectorFieldStyle2D*>(board.myStyles["VectorField"].get());
234 if (style)
235 {
236 scale = style->scale;
237 epsilon = style->epsilon;
238 }
239 }
240
241 for (typename TCalculus::Index index=0; index<vector_field.length(); index++)
242 {
243 const typename TCalculus::SCell& cell = vector_field.getSCell(index);
244 const DGtal::Z2i::RealPoint origin = DGtal::Z2i::RealPoint(cell.preCell().coordinates[0]-1, cell.preCell().coordinates[1]-1)/2.;
245
246 Vector vector = vector_field.getVector(index);
247
248 vector *= scale;
249 if (!std::isfinite(vector[0]) || !std::isfinite(vector[1])) continue;
250 const typename TCalculus::Scalar& norm = vector.norm();
251 if (norm <= epsilon) continue;
252 if (norm <= .5) vector *= .5/norm;
253
254 board.drawArrow(origin[0],origin[1],origin[0]+vector[0],origin[1]+vector[1]);
255 }
256
257}
258// VectorField
259
260// AngleLinearMinimizer
261inline
262void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
263 const DGtal::AngleLinearMinimizer & a )
264{
265 double distance=5.0;
266 board.setLineWidth(3.0);
267 board.setPenColor(Color(20,20,200));
268 // now with accessor
269 for(int i=0; i< (int)a.size(); i++){
270 board.drawArc(0.0, 0.0, distance, a.ro(i).min, a.ro(i).max, false, 1);
271 board.drawDot(cos(a.ro(i).value)*distance, sin(a.ro(i).value)*distance );
272 distance+=a.ro(i).distToNext;
273 }
274 distance=5.0;
275 double distanceNext;
276 // now with accessor
277 for(int i=0; i< (int) (a.size()-1); i++){
278 distanceNext= distance+ a.ro(i).distToNext;
279 board.setPenColor(Color(200,20,20));
280 board.drawLine(cos(a.ro(i).value)*distance, sin(a.ro(i).value)*distance,
281 cos(a.ro(i+1).value)*distanceNext, sin(a.ro(i+1).value)*distanceNext);
282 distance=distanceNext;
283 }
284}
285// AngleLinearMinimizer
286
287// ArithmeticalDSS
288template <typename TCoordinate, typename TInteger, unsigned short adjacency>
289inline
290void DGtal::Display2DFactory::drawAsBoundingBox( DGtal::Board2D & aBoard,
291 const DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency> & a )
292{
293 typedef typename DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency>::PointD PointD;
294
295 //draw bounding box
296 PointD topLeft = a.project(a.back(), a.Uf());
297 PointD bottomLeft = a.project(a.back(), a.Lf());
298 PointD bottomRight = a.project(a.front(), a.Lf());
299 PointD topRight = a.project(a.front(), a.Uf());
300
301 LibBoard::Point topLeftBoard(topLeft[0],topLeft[1]);
302 LibBoard::Point bottomLeftBoard(bottomLeft[0],bottomLeft[1]);
303 LibBoard::Point bottomRightBoard(bottomRight[0],bottomRight[1]);
304 LibBoard::Point topRightBoard(topRight[0],topRight[1]);
305
306 std::vector<LibBoard::Point> bb;
307 bb.push_back(topLeftBoard);
308 bb.push_back(bottomLeftBoard);
309 bb.push_back(bottomRightBoard);
310 bb.push_back(topRightBoard);
311
312 aBoard.drawClosedPolyline(bb);
313}
314
315template <typename TCoordinate, typename TInteger, unsigned short adjacency>
316inline
317void DGtal::Display2DFactory::drawAsDigitalPoints( DGtal::Board2D & aBoard,
318 const DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency> & a )
319{
320 typedef typename DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency>::ConstIterator ConstIterator;
321 typedef typename IteratorCirculatorTraits<ConstIterator>::Value Point;
322
323 // Draw a linking polygonal line if the pixels are drawn as points.
324 if(aBoard.getMode("PointVector")=="Grid" || aBoard.getMode("PointVector")=="")
325 {
326 std::vector<LibBoard::Point> contour;
327 for (ConstIterator it = a.begin(), itEnd = a.end();
328 it != itEnd; ++it)
329 {
330 Point p = *it;
331 double xp = NumberTraits<TInteger>::castToDouble(p[0]);
332 double yp = NumberTraits<TInteger>::castToDouble(p[1]);
333 contour.push_back(LibBoard::Point(xp,yp));
334 }
335 aBoard.drawPolyline(contour);
336 }
337
338 // Draw points
339 for (ConstIterator it = a.begin(), itEnd = a.end();
340 it != itEnd; ++it)
341 {
342 Point p = *it;
343 aBoard << p;
344 }
345}
346
347template <typename TCoordinate, typename TInteger, unsigned short adjacency>
348inline
349void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
350 const DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency> & a )
351{
352 std::string mode = board.getMode( a.className() );
353 if ( mode == "BoundingBox" )
354 drawAsBoundingBox( board, a );
355 else if ( mode == "Points" )
356 drawAsDigitalPoints( board, a );
357 else if ( ( mode == "" ) )
358 {
359 auto style = new DefaultDrawStyleBB_ArithmeticalDSS();
360 drawAsDigitalPoints( board, a );
361 Style2DFactory::draw( board, style);
362 drawAsBoundingBox( board, a );
363 delete style;
364 }
365 else
366 ASSERT(false && ("draw( DGtal::Board2D & board, const DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency> & a ): Unknown mode "+mode)=="" );
367}
368// ArithmeticalDSS
369
370// ArithmeticalDSSComputer
371template <typename TIterator, typename TInteger, int connectivity>
372inline
373void DGtal::Display2DFactory::drawAsBoundingBox( DGtal::Board2D & aBoard,
374 const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a )
375{
376 typedef DGtal::PointVector<2,double> PointD;
377
378 //draw bounding box
379 PointD topLeft = a.project(*a.myF, a.myUf);
380 PointD bottomLeft = a.project(*a.myF, a.myLf);
381 PointD bottomRight = a.project(*a.myL, a.myLf);
382 PointD topRight = a.project(*a.myL, a.myUf);
383
384
385 LibBoard::Point topLeftBoard(topLeft[0],topLeft[1]);
386 LibBoard::Point bottomLeftBoard(bottomLeft[0],bottomLeft[1]);
387 LibBoard::Point bottomRightBoard(bottomRight[0],bottomRight[1]);
388 LibBoard::Point topRightBoard(topRight[0],topRight[1]);
389
390 std::vector<LibBoard::Point> bb;
391 bb.push_back(topLeftBoard);
392 bb.push_back(bottomLeftBoard);
393 bb.push_back(bottomRightBoard);
394 bb.push_back(topRightBoard);
395
396 aBoard.drawClosedPolyline(bb);
397}
398
399template <typename TIterator, typename TInteger, int connectivity>
400inline
401void DGtal::Display2DFactory::drawAsDigitalPoints( DGtal::Board2D & aBoard,
402 const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a )
403{
404 typedef TIterator ConstIterator;
405 typedef typename IteratorCirculatorTraits<ConstIterator>::Value Point;
406
407 ConstIterator itend = a.myL; ++itend;
408
409 // Draw a linking polygonal line if the pixels are drawn as points.
410 if(aBoard.getMode("PointVector")=="Grid" || aBoard.getMode("PointVector")=="")
411 {
412 std::vector<LibBoard::Point> contour;
413 for (ConstIterator i = a.myF; i != itend; ++i) {
414 Point p = *i;
415 double xp = NumberTraits<TInteger>::castToDouble(p[0]);
416 double yp = NumberTraits<TInteger>::castToDouble(p[1]);
417 contour.push_back(LibBoard::Point(xp,yp));
418 }
419 aBoard.drawPolyline(contour);
420 }
421
422 // Draw points
423 for (ConstIterator i = a.myF; i != itend; ++i) {
424 Point p = *i;
425 aBoard << p;
426 }
427}
428
429template <typename TIterator, typename TInteger, int connectivity>
430inline
431void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
432 const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a )
433{
434 std::string mode = board.getMode( a.className() );
435 if ( mode == "BoundingBox" )
436 drawAsBoundingBox( board, a );
437 else if ( mode == "Points" )
438 drawAsDigitalPoints( board, a );
439 else if ( ( mode == "" ) )
440 {
441 drawAsDigitalPoints( board, a );
442 drawAsBoundingBox( board, a );
443 }
444 else
445 FATAL_ERROR_MSG(false, "draw( DGtal::Board2D & board, const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a ): Unknown mode "+mode);
446
447}
448// ArithmeticalDSSComputer
449
450
451// AlphaThickSegmentComputer
452template <typename TInputPoint, typename TConstIterator>
453void DGtal::Display2DFactory::drawAsBoundingBox( DGtal::Board2D & aBoard,
454 const DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator> & anAlphaThickSegment){
455 typedef DGtal::PointVector<2,double> PointD;
456
457 PointD topLeft, topRight, bottomRight, bottomLeft;
458 anAlphaThickSegment.getBoundingBox(topLeft, topRight, bottomRight, bottomLeft);
459 //draw bounding box
460 aBoard.drawLine(topLeft[0],topLeft[1],topRight[0],topRight[1]);
461 aBoard.drawLine(topRight[0],topRight[1],bottomRight[0], bottomRight[1] );
462 aBoard.drawLine(bottomRight[0], bottomRight[1], bottomLeft[0], bottomLeft[1]);
463 aBoard.drawLine(bottomLeft[0], bottomLeft[1],topLeft[0],topLeft[1]);
464}
465
466
467template < typename TInputPoint, typename TConstIterator>
468void DGtal::Display2DFactory::drawAsDigitalPoints( DGtal::Board2D & aBoard,
469 const DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator> & anAlphaThickSegment){
470 typedef typename DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator>::ContainerConstIterator ContConstIterator;
471 typedef TConstIterator ConstIterator;
472 typedef TInputPoint Point;
473 // Draw a linking polygonal line if the pixels are drawn as points.
474 if(aBoard.getMode("PointVector")=="Grid" || aBoard.getMode("PointVector")=="")
475 {
476 std::vector<LibBoard::Point> contour;
477 if (anAlphaThickSegment.isStoringSegmentPoints()){
478 for (ContConstIterator it = anAlphaThickSegment.containerBegin();
479 it != anAlphaThickSegment.containerEnd(); it++) {
480 Point p = *it;
481 double xp = NumberTraits<typename TInputPoint::Component>::castToDouble(p[0]);
482 double yp = NumberTraits<typename TInputPoint::Component>::castToDouble(p[1]);
483 contour.push_back(LibBoard::Point(xp,yp));
484 }
485
486 }else{
487 for (ConstIterator it = anAlphaThickSegment.begin(); it != anAlphaThickSegment.end(); it++) {
488 Point p = *it;
489 double xp = NumberTraits<typename TInputPoint::Component>::castToDouble(p[0]);
490 double yp = NumberTraits<typename TInputPoint::Component>::castToDouble(p[1]);
491 contour.push_back(LibBoard::Point(xp,yp));
492 }
493 }
494 if(contour.size()>0){
495 aBoard.drawPolyline(contour);
496 }
497 }
498 // Draw points
499 if (anAlphaThickSegment.isStoringSegmentPoints()){
500 for (ContConstIterator it = anAlphaThickSegment.containerBegin();
501 it != anAlphaThickSegment.containerEnd(); it++) {
502 Point p = *it;
503 draw(aBoard,p );
504 }
505 }else {
506 for (ConstIterator it = anAlphaThickSegment.begin(); it != anAlphaThickSegment.end(); it++) {
507 Point p = *it;
508 draw(aBoard,p );
509 }
510 }
511}
512
513template < typename TInputPoint, typename TConstIterator>
514void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
515 const DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator> & anAlphaThickSegment ){
516 std::string mode = aBoard.getMode( anAlphaThickSegment.className() );
517 if ( mode == "BoundingBox" )
518 drawAsBoundingBox( aBoard, anAlphaThickSegment );
519 else if ( mode == "Points" )
520 drawAsDigitalPoints( aBoard, anAlphaThickSegment );
521 else if ( ( mode == "" ) )
522 {
523 drawAsDigitalPoints( aBoard, anAlphaThickSegment );
524 drawAsBoundingBox( aBoard, anAlphaThickSegment );
525 }
526 else
527 FATAL_ERROR_MSG(false, "draw( DGtal::Board2D & board, const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a ): Unknown mode "+mode);
528 }
529// AlphaThickSegmentComputer
530
531
532// CircleFrom2Points
533template <typename TPoint>
534inline
535void DGtal::Display2DFactory::draw(Board2D & aBoard, const DGtal::CircleFrom2Points<TPoint> & cf2p)
536{
537 // now with accessor
538 CircleFrom3Points<TPoint> c(cf2p.pole(),cf2p.p(),cf2p.q());
539 drawArc(aBoard,c,cf2p.p(),cf2p.q(),true);
540}
541// CircleFrom2Points
542
543
544// CircleFrom3Points
545template <typename Point>
546inline
547void DGtal::Display2DFactory::drawArc(Board2D & aBoard, const DGtal::CircleFrom3Points<Point> & cf3p, const Point& aPoint1, const Point& aPoint2, bool anOrientation)
548{
549 typedef typename Point::Coordinate Coordinate;
550 typedef Point Vector;
551
552 double cx = 0, cy = 0, radius = 1;
553 try
554 {
555 //circle parameters
556 cf3p.getParameters(cx, cy, radius);
557 //angle parameters
558 double alpha1 = std::atan2( NumberTraits<Coordinate>::castToDouble(aPoint1[1])-cy,
559 NumberTraits<Coordinate>::castToDouble(aPoint1[0])-cx );
560 alpha1 = (alpha1<0)?(alpha1+2.0*M_PI):alpha1;
561 double alpha2 = std::atan2( NumberTraits<Coordinate>::castToDouble(aPoint2[1])-cy,
562 NumberTraits<Coordinate>::castToDouble(aPoint2[0])-cx );
563 alpha2 = (alpha2<0)?(alpha2+2.0*M_PI):alpha2;
564 // now with accessor
565 Vector u(cf3p.p() - cf3p.q());
566 Vector v(cf3p.r() - cf3p.p());
567 bool orientation = ( ( (u[0] * v[1]) - (u[1] * v[0]) ) < 0 )?(!anOrientation):anOrientation;
568 //drawing
569 aBoard.drawArc (cx, cy, radius, alpha1, alpha2, orientation);
570 }
571 catch ( InfiniteNumberException& e )
572 {
573 aBoard.drawLine( NumberTraits<Coordinate>::castToDouble(aPoint1[0]),
574 NumberTraits<Coordinate>::castToDouble(aPoint1[1]),
575 NumberTraits<Coordinate>::castToDouble(aPoint2[0]),
576 NumberTraits<Coordinate>::castToDouble(aPoint2[1]) );
577 }
578}
579
580template <typename Point>
581inline
582void DGtal::Display2DFactory::drawSector(Board2D & aBoard, const DGtal::CircleFrom3Points<Point> & cf3p, const Point& aPoint1, const Point& aPoint2, bool anOrientation)
583{
584 typedef typename Point::Coordinate Coordinate;
585 typedef Point Vector;
586
587 double cx = 0, cy = 0, radius = 1;
588 try
589 {
590 //circle parameters
591 cf3p.getParameters(cx, cy, radius);
592 //angle parameters
593 double alpha1 = std::atan2( NumberTraits<Coordinate>::castToDouble(aPoint1[1])-cy,
594 NumberTraits<Coordinate>::castToDouble(aPoint1[0])-cx );
595 alpha1 = (alpha1<0)?(alpha1+2.0*M_PI):alpha1;
596 double alpha2 = std::atan2( NumberTraits<Coordinate>::castToDouble(aPoint2[1])-cy,
597 NumberTraits<Coordinate>::castToDouble(aPoint2[0])-cx );
598 alpha2 = (alpha2<0)?(alpha2+2.0*M_PI):alpha2;
599 // now with accessor
600 Vector u(cf3p.p() - cf3p.q());
601 Vector v(cf3p.r() - cf3p.p());
602 bool orientation = ( ( (u[0] * v[1]) - (u[1] * v[0]) ) < 0 )?(!anOrientation):anOrientation;
603 //arc drawing
604 aBoard.drawArc (cx, cy, radius, alpha1, alpha2, orientation);
605 //draw the segments tied to the center
606 double fx = cx + radius*std::cos(alpha1);
607 double fy = cy + radius*std::sin(alpha1);
608 double lx = cx + radius*std::cos(alpha2);
609 double ly = cy + radius*std::sin(alpha2);
610 aBoard.drawLine(fx, fy, cx, cy );
611 aBoard.drawLine(lx, ly, cx, cy );
612
613 }
614 catch ( InfiniteNumberException& e )
615 {
616 aBoard.drawLine( NumberTraits<Coordinate>::castToDouble(aPoint1[0]),
617 NumberTraits<Coordinate>::castToDouble(aPoint1[1]),
618 NumberTraits<Coordinate>::castToDouble(aPoint2[0]),
619 NumberTraits<Coordinate>::castToDouble(aPoint2[1]) );
620 }
621}
622
623template <typename Point>
624inline
625void DGtal::Display2DFactory::drawAnnulus(Board2D & aBoard, const DGtal::CircleFrom3Points<Point> & cf3p,
626 const Point& aPoint1, const Point& aPoint2, bool anOrientation, const double& w)
627{
628 typedef typename Point::Coordinate Coordinate;
629 typedef Point Vector;
630
631 double cx = 0, cy = 0, radius = 1;
632 try
633 {
634 //circle parameters
635 cf3p.getParameters(cx, cy, radius);
636 //angle parameters
637 double alpha1 = std::atan2( NumberTraits<Coordinate>::castToDouble(aPoint1[1])-cy,
638 NumberTraits<Coordinate>::castToDouble(aPoint1[0])-cx );
639 alpha1 = (alpha1<0)?(alpha1+2.0*M_PI):alpha1;
640 double alpha2 = std::atan2( NumberTraits<Coordinate>::castToDouble(aPoint2[1])-cy,
641 NumberTraits<Coordinate>::castToDouble(aPoint2[0])-cx );
642 alpha2 = (alpha2<0)?(alpha2+2.0*M_PI):alpha2;
643 // now with accessor
644 Vector u(cf3p.p() - cf3p.q());
645 Vector v(cf3p.r() - cf3p.p());
646 bool orientation = ( ( (u[0] * v[1]) - (u[1] * v[0]) ) < 0 )?(!anOrientation):anOrientation;
647 //inner arc
648 aBoard.drawArc (cx, cy, radius-w, alpha1, alpha2, orientation);
649 //outer arc
650 aBoard.drawArc (cx, cy, radius+w, alpha1, alpha2, orientation);
651 //first segment
652 double ifx = cx + (radius-w)*std::cos(alpha1);
653 double ify = cy + (radius-w)*std::sin(alpha1);
654 double ofx = cx + (radius+w)*std::cos(alpha1);
655 double ofy = cy + (radius+w)*std::sin(alpha1);
656 aBoard.drawLine(ifx, ify, ofx, ofy);
657 //second segment
658 double ilx = cx + (radius-w)*std::cos(alpha2);
659 double ily = cy + (radius-w)*std::sin(alpha2);
660 double olx = cx + (radius+w)*std::cos(alpha2);
661 double oly = cy + (radius+w)*std::sin(alpha2);
662 aBoard.drawLine(ilx, ily, olx, oly);
663 }
664 catch ( InfiniteNumberException& e )
665 {
666 aBoard.drawLine( NumberTraits<Coordinate>::castToDouble(aPoint1[0]),
667 NumberTraits<Coordinate>::castToDouble(aPoint1[1]),
668 NumberTraits<Coordinate>::castToDouble(aPoint2[0]),
669 NumberTraits<Coordinate>::castToDouble(aPoint2[1]) );
670 }
671}
672
673template <typename Point>
674inline
675void DGtal::Display2DFactory::draw(Board2D & aBoard, const DGtal::CircleFrom3Points<Point> & cf3p, const Point& aPoint1, const Point& aPoint2, bool anOrientation)
676{
677 std::string mode = aBoard.getMode( cf3p.className() );
678 FATAL_ERROR( (mode=="Arc" || mode=="" || mode=="Sector"|| mode=="Annulus") ||
679 ("draw(Board2D & aBoard, const DGtal::CircleFrom3Points<Point> & cf3p, const Point& aPoint1, const Point& aPoint2): Unknown mode "+mode)=="" );
680
681 if ( mode == "Arc" || ( mode == "" ) )
682 drawArc( aBoard, cf3p, aPoint1, aPoint2, anOrientation);
683 else if ( mode == "Sector" )
684 drawSector( aBoard, cf3p, aPoint1, aPoint2, anOrientation);
685 else if ( mode == "Annulus" )
686 drawAnnulus( aBoard, cf3p, aPoint1, aPoint2, anOrientation);
687}
688
689template <typename TPoint>
690inline
691void DGtal::Display2DFactory::draw(Board2D & aBoard, const DGtal::CircleFrom3Points<TPoint> & cf3p)
692{
693 typedef typename TPoint::Coordinate Coordinate;
694
695 double cx = 0, cy = 0, radius = 1;
696 try
697 {
698 cf3p.getParameters(cx,cy,radius);
699 aBoard.drawCircle (cx,cy,radius);
700 }
701 catch ( InfiniteNumberException& e )
702 {
703 aBoard.drawLine( NumberTraits<Coordinate>::castToDouble(cf3p.myP[0]),
704 NumberTraits<Coordinate>::castToDouble(cf3p.myP[1]),
705 NumberTraits<Coordinate>::castToDouble(cf3p.myR[0]),
706 NumberTraits<Coordinate>::castToDouble(cf3p.myR[1]) );
707 }
708}
709// CircleFrom3Points
710
711
712// DigitalSetBySTLSet
713template<typename Domain, typename Compare>
714inline
715void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
716 const DGtal::DigitalSetBySTLSet<Domain, Compare> & s )
717{
718 typedef typename Domain::Point Point;
719 typedef typename std::set<Point>::const_iterator ConstIterator;
720
721 BOOST_STATIC_ASSERT(Domain::Space::dimension == 2);
722 for(ConstIterator it = s.begin(); it != s.end(); ++it)
723 draw(board, *it);
724}
725// DigitalSetBySTLSet
726
727
728// DigitalSetByAssociativeContainer
729template<typename Domain, typename Container>
730inline
731void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
732 const DGtal::DigitalSetByAssociativeContainer<Domain,Container> & s )
733{
734 typedef typename DigitalSetByAssociativeContainer<Domain,Container>::ConstIterator ConstIterator;
735
736 BOOST_STATIC_ASSERT(Domain::Space::dimension == 2);
737 for(ConstIterator it = s.begin(); it != s.end(); ++it)
738 draw(board, *it);
739}
740// DigitalSetByAssociativeContainer
741
742
743// DigitalSetBySTLVector
744template<typename Domain>
745inline
746void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
747 const DGtal::DigitalSetBySTLVector<Domain> & v )
748{
749 typedef typename Domain::Point Point;
750 typedef typename std::vector<Point>::const_iterator ConstIterator;
751
752 if (Domain::dimension == 2)
753 {
754 for(ConstIterator it = v.begin(); it != v.end(); ++it)
755 draw(board, *it);
756 }
757 else
758 FATAL_ERROR_MSG(false, "draw-NOT-YET-IMPLEMENTED-in-ND");
759}
760// DigitalSetBySTLVector
761
762
763// FP
764template <typename TIterator, typename TInteger, int connectivity>
765inline
766void DGtal::Display2DFactory::drawAsPolygon( DGtal::Board2D & aBoard,
767 const DGtal::FP<TIterator,TInteger,connectivity> & fp )
768{
769 typedef DGtal::PointVector<2,TInteger> Point;
770 typedef std::list<Point> Polygon;
771
772 typedef typename Polygon::const_iterator ConstIterator;
773
774 //polyline to draw
775 std::vector<LibBoard::Point> polyline;
776
777 // now with accessor
778 ConstIterator i = fp.polygon().begin();
779 for ( ;i != fp.polygon().end();++i) {
780 Point p = (*i);
781 double xp = (double)NumberTraits<TInteger>::castToInt64_t(p[0]);
782 double yp = (double)NumberTraits<TInteger>::castToInt64_t(p[1]);
783 polyline.push_back(LibBoard::Point(xp,yp));
784 }
785
786 // now with accessor
787 if (fp.isClosed()) {
788 Point p = (*fp.polygon().begin());
789 double xp = (double)NumberTraits<TInteger>::castToInt64_t(p[0]);
790 double yp = (double)NumberTraits<TInteger>::castToInt64_t(p[1]);
791 polyline.push_back(LibBoard::Point(xp,yp));
792 }
793 aBoard.drawPolyline(polyline);
794}
795
796template <typename TIterator, typename TInteger, int connectivity>
797inline
798void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
799 const DGtal::FP<TIterator,TInteger,connectivity> & fp )
800{
801 std::string mode = board.getMode( fp.className() );
802 if ( mode == "Polygon" )
803 drawAsPolygon( board, fp );
804 else if ( ( mode == "Both" ) || ( mode == "" ) )
805 {
806 drawAsPolygon( board, fp );
807 }
808 else
809 {
810 FATAL_ERROR_MSG(false, "draw( DGtal::Board2D & board, const DGtal::FP<TIterator,TInteger,connectivity> & fp ): Unknown mode "+mode);
811 }
812}
813// FP
814
815
816// FreemanChain
817template <typename TInteger>
818inline
819void DGtal::Display2DFactory::drawAsGrid( DGtal::Board2D & aBoard,
820 const DGtal::FreemanChain<TInteger> & f )
821{
822 typedef TInteger Integer;
823 typedef PointVector<2, Integer> Point;
824
825 std::vector<Point> aVContour;
826 FreemanChain<TInteger>::getContourPoints(f, aVContour);
827 TInteger minX, minY, maxX, maxY;
828 f.computeBoundingBox(minX, minY, maxX, maxY);
829
830 std::vector<LibBoard::Point> contour;
831 for(unsigned int i=0; i< aVContour.size(); i++){
832 contour.push_back(LibBoard::Point(NumberTraits<TInteger>::castToDouble(aVContour[i][0]),
833 NumberTraits<TInteger>::castToDouble(aVContour[i][1])));
834 }
835 aBoard.drawPolyline(contour);
836}
837
838template <typename TInteger>
839inline
840void DGtal::Display2DFactory::drawAsInterGrid( DGtal::Board2D & aBoard,
841 const DGtal::FreemanChain<TInteger> & f )
842{
843 typedef TInteger Integer;
844 typedef PointVector<2, Integer> Point;
845
846 std::vector<Point> aVContour;
847 FreemanChain<TInteger>::getContourPoints(f, aVContour);
848 TInteger minX, minY, maxX, maxY;
849 f.computeBoundingBox(minX, minY, maxX, maxY);
850
851 std::vector<LibBoard::Point> contour;
852 for(unsigned int i=0; i< aVContour.size(); i++){
853 contour.push_back(LibBoard::Point(NumberTraits<TInteger>::castToInt64_t(aVContour[i][0])-0.5,
854 NumberTraits<TInteger>::castToInt64_t(aVContour[i][1])+0.5));
855 }
856 aBoard.drawPolyline(contour);
857}
858
859template <typename TInteger>
860inline
861void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
862 const DGtal::FreemanChain<TInteger> & f )
863{
864 std::string mode = aBoard.getMode( f.className() );
865 FATAL_ERROR_MSG( (mode=="Grid" || mode=="" || mode=="InterGrid"),
866 "draw( DGtal::Board2D & board, const DGtal::FreemanChain<TInteger> & f ): Unknown mode "+mode);
867
868 if ( mode == "Grid" || ( mode == "" ) )
869 drawAsGrid( aBoard, f );
870 else if ( mode == "InterGrid" )
871 drawAsInterGrid( aBoard, f );
872}
873// FreemanChain
874
875
876// StabbingLineComputer
877template <typename TConstIterator>
878inline
879void DGtal::Display2DFactory::draw(DGtal::Board2D & aBoard,
880 const DGtal::StabbingLineComputer<TConstIterator> & g)
881{
882 typedef TConstIterator ConstIterator;
883 typedef typename IteratorCirculatorTraits<ConstIterator>::Value Pair;
884 typedef typename Pair::first_type Point;
885
886 double alpha, beta, gamma;
887 g.getParameters(alpha, beta, gamma);
888
889 typedef typename Point::Coordinate Coordinate;
890
891 // now with accessor
892 Pair firstPair( *g.begin() );
893 double fx1 = NumberTraits<Coordinate>::castToDouble(firstPair.first[0]);
894 double fx2 = NumberTraits<Coordinate>::castToDouble(firstPair.second[0]);
895 double fy1 = NumberTraits<Coordinate>::castToDouble(firstPair.first[1]);
896 double fy2 = NumberTraits<Coordinate>::castToDouble(firstPair.second[1]);
897 double fx = (fx1+fx2)/2.0;
898 double fy = (fy1+fy2)/2.0;
899 g.projects(fx, fy, alpha, beta, gamma);
900
901 // now with accessor
902 ConstIterator it (g.end());
903 --it;
904 Pair lastPair( *it );
905 double lx1 = NumberTraits<Coordinate>::castToDouble(lastPair.first[0]);
906 double lx2 = NumberTraits<Coordinate>::castToDouble(lastPair.second[0]);
907 double ly1 = NumberTraits<Coordinate>::castToDouble(lastPair.first[1]);
908 double ly2 = NumberTraits<Coordinate>::castToDouble(lastPair.second[1]);
909 double lx = (lx1+lx2)/2.0;
910 double ly = (ly1+ly2)/2.0;
911 g.projects(lx, ly, alpha, beta, gamma);
912
913 aBoard.drawLine(fx,fy,lx,ly);
914}
915// StabbingLineComputer
916
917// StabbingCircleComputer
918template <typename TConstIterator>
919inline
920void DGtal::Display2DFactory::draw(DGtal::Board2D & aBoard,
921 const DGtal::StabbingCircleComputer<TConstIterator> & g)
922{
923
924 typedef TConstIterator ConstIterator;
925 typedef typename IteratorCirculatorTraits<ConstIterator>::Value Pair;
926 typedef typename Pair::first_type Point;
927
928 if (g.isValid())
929 {
930 if (!g.isStraight())
931 {
932 typedef typename Point::Coordinate Coordinate;
933
934 //points
935 Pair firstPair( *g.begin() );
936 double fx1 = NumberTraits<Coordinate>::castToDouble(firstPair.first[0]);
937 double fx2 = NumberTraits<Coordinate>::castToDouble(firstPair.second[0]);
938 double fy1 = NumberTraits<Coordinate>::castToDouble(firstPair.first[1]);
939 double fy2 = NumberTraits<Coordinate>::castToDouble(firstPair.second[1]);
940 PointVector<2,double> p1( (fx1+fx2)/2.0, (fy1+fy2)/2.0 );
941
942 ConstIterator it (g.end());
943 --it;
944 Pair lastPair( *it );
945 double lx1 = NumberTraits<Coordinate>::castToDouble(lastPair.first[0]);
946 double lx2 = NumberTraits<Coordinate>::castToDouble(lastPair.second[0]);
947 double ly1 = NumberTraits<Coordinate>::castToDouble(lastPair.first[1]);
948 double ly2 = NumberTraits<Coordinate>::castToDouble(lastPair.second[1]);
949 PointVector<2,double> p2( (lx1+lx2)/2.0, (ly1+ly2)/2.0 );
950
951 //circle
952 CircleFrom3Points<Point> separatingCircle = g.getSeparatingCircle();
953 double px = NumberTraits<Coordinate>::castToDouble(separatingCircle.p()[0]);
954 double py = NumberTraits<Coordinate>::castToDouble(separatingCircle.p()[1]);
955 double qx = NumberTraits<Coordinate>::castToDouble(separatingCircle.q()[0]);
956 double qy = NumberTraits<Coordinate>::castToDouble(separatingCircle.q()[1]);
957 double rx = NumberTraits<Coordinate>::castToDouble(separatingCircle.r()[0]);
958 double ry = NumberTraits<Coordinate>::castToDouble(separatingCircle.r()[1]);
959 CircleFrom3Points<PointVector<2,double> > circleToDraw;
960 circleToDraw.init( PointVector<2,double>(px,py),
961 PointVector<2,double>(qx,qy),
962 PointVector<2,double>(rx,ry) );
963
964 //orientation
965 FATAL_ERROR( g.getStabbingLineComputerPtr().get() != 0 );
966 bool orientation = g.getStabbingLineComputerPtr()->isClockwiseOriented();
967
968 //mode
969 std::string mode = aBoard.getMode( g.className() );
970 if ( mode == "Sector" )
971 drawSector( aBoard, circleToDraw, p1, p2, orientation );
972 else if ( mode == "Annulus" )
973 drawAnnulus( aBoard, circleToDraw, p1, p2, orientation );
974 else
975 drawArc( aBoard, circleToDraw, p1, p2, orientation );
976 }
977 else
978 {
979 FATAL_ERROR( g.getStabbingLineComputerPtr().get() != 0 );
980 aBoard << ( *(g.getStabbingLineComputerPtr()) );
981 }
982 }
983
984}
985// StabbingCircleComputer
986
987
988
989// FrechetShortcut
990template <typename TIterator,typename TInteger>
991inline
992 void DGtal::Display2DFactory::draw(DGtal::Board2D & aBoard, const DGtal::FrechetShortcut<TIterator,TInteger> & f)
993{
994 typedef TIterator Iterator;
995 typedef PointVector<2,TInteger> Point;
996 typedef typename Point::Coordinate Coordinate;
997
998 // get first point of the shortcut
999 Point p1 = *(f.begin());
1000 double px1 = NumberTraits<Coordinate>::castToDouble(p1[0]);
1001 double py1 = NumberTraits<Coordinate>::castToDouble(p1[1]);
1002
1003 // get last point of the shortcut
1004 Iterator it (f.end());
1005 --it;
1006 Point p2(*it);
1007 double px2 = NumberTraits<Coordinate>::castToDouble(p2[0]);
1008 double py2 = NumberTraits<Coordinate>::castToDouble(p2[1]);
1009
1010 aBoard.drawLine(px1,py1,px2,py2);
1011}
1012// FrechetShortcut
1013
1014
1015
1016// GridCurve
1017template <typename TKSpace>
1018void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1019 const GridCurve<TKSpace> & object )
1020{
1021
1022 std::string mode = aBoard.getMode( object.className() );
1023 if(mode=="Fill"){
1024 DGtal::Display2DFactory::drawFill(aBoard, object);
1025 }else{
1026 typedef typename GridCurve<TKSpace>::ConstIterator ConstIterator;
1027 ConstIterator it ( object.begin() );
1028 ConstIterator itEnd ( object.end() );
1029 for( ; it != itEnd; ++it)
1030 {
1031 aBoard << *it;
1032 }
1033 }
1034}
1035
1036template <typename TKSpace>
1037void DGtal::Display2DFactory::drawFill( DGtal::Board2D & aBoard,
1038 const GridCurve<TKSpace> & object )
1039{
1040
1041
1042 typedef typename GridCurve<TKSpace>::PointsRange::ConstIterator Iterator;
1043 typedef typename GridCurve<TKSpace>::PointsRange Range; //range
1044
1045 Range r = object.getPointsRange();
1046 Iterator it (r.begin());
1047 Iterator itEnd (r.end());
1048
1049 std::vector< LibBoard::Point > aPolygon;
1050 for( ; it != itEnd; ++it)
1051 {
1052 LibBoard::Point pt((*it)[0], (*it)[1]);
1053 aPolygon.push_back(pt);
1054 }
1055 aBoard.fillPolyline(aPolygon);
1056}
1057
1058
1059
1060
1061// GridCurve
1062
1063// SCellsRange
1064template <typename TIterator, typename TSCell>
1065void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1066 const ConstRangeAdapter<TIterator, functors::Identity, TSCell> & object )
1067{
1068 typedef ConstRangeAdapter<TIterator, functors::Identity, TSCell> Range;
1069 typedef typename Range::ConstIterator ConstIterator;
1070
1071 ConstIterator it ( object.begin() );
1072 ConstIterator itEnd ( object.end() );
1073 for( ; it != itEnd; ++it)
1074 {
1075 aBoard << *it;
1076 }
1077}
1078// SCellsRange
1079
1080// PointsRange
1081template <typename TIterator, typename TKSpace>
1082void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1083 const ConstRangeAdapter<TIterator, functors::SCellToPoint<TKSpace>, typename TKSpace::Point> & object )
1084{
1085 typedef ConstRangeAdapter<TIterator, functors::SCellToPoint<TKSpace>, typename TKSpace::Point> Range;
1086 typedef typename Range::ConstIterator ConstIterator;
1087
1088 ConstIterator it ( object.begin() );
1089 ConstIterator itEnd ( object.end() );
1090 for( ; it != itEnd; ++it)
1091 {
1092 aBoard << SetMode(it->className(),"Grid");
1093 aBoard << *it;
1094 }
1095}
1096// PointsRange
1097
1098// MidPointsRange
1099template <typename TIterator, typename TKSpace>
1100void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1101 const ConstRangeAdapter<TIterator, CanonicSCellEmbedder<TKSpace>,
1102 typename TKSpace::Space::RealPoint> & object )
1103{
1104 typedef typename TKSpace::Space::RealPoint RPoint;
1105 typedef ConstRangeAdapter<TIterator, CanonicSCellEmbedder<TKSpace>, RPoint > Range;
1106 typedef typename Range::ConstIterator ConstIterator;
1107
1108 ConstIterator it ( object.begin() );
1109 ConstIterator itEnd ( object.end() );
1110 for( ; it != itEnd; ++it)
1111 {
1112 RPoint p(*it);
1113 double s = 0.1;
1114 aBoard.drawLine( p[0]-s, p[1]-s, p[0]+s, p[1]+s );
1115 aBoard.drawLine( p[0]-s, p[1]+s, p[0]+s, p[1]-s );
1116 }
1117}
1118// MidPointsRange
1119
1120// ArrowsRange
1121template <typename TIterator, typename TKSpace>
1122void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1123 const ConstRangeAdapter<TIterator, functors::SCellToArrow<TKSpace>,
1124 std::pair<typename TKSpace::Point, typename TKSpace::Vector> > & object )
1125{
1126 typedef typename TKSpace::Point Point;
1127 typedef typename TKSpace::Vector Vector;
1128 typedef std::pair<Point, Vector> Arrow;
1129 typedef ConstRangeAdapter<TIterator, functors::SCellToArrow<TKSpace>, Arrow > Range;
1130 typedef typename Range::ConstIterator ConstIterator;
1131
1132 ConstIterator it ( object.begin() );
1133 ConstIterator itEnd ( object.end() );
1134 for( ; it != itEnd; ++it)
1135 {
1136 Arrow a(*it);
1137 Vector shift( a.second );
1138 aBoard << CustomStyle( shift.className(),
1139 new CustomPen( Color::Black, Color::Black, 1.0,
1140 Board2D::Shape::SolidStyle,
1141 Board2D::Shape::RoundCap,
1142 Board2D::Shape::RoundJoin ) );
1143 draw(aBoard, shift, a.first);
1144 }
1145}
1146// ArrowsRange
1147
1148// InnerPointsRange
1149template <typename TIterator, typename TKSpace>
1150void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1151 const ConstRangeAdapter<TIterator, functors::SCellToInnerPoint<TKSpace>,
1152 typename TKSpace::Point > & object )
1153{
1154 typedef typename TKSpace::Point Point;
1155 typedef ConstRangeAdapter<TIterator, functors::SCellToInnerPoint<TKSpace>, Point > Range;
1156 typedef typename Range::ConstIterator ConstIterator;
1157
1158 ConstIterator it ( object.begin() );
1159 ConstIterator itEnd ( object.end() );
1160 for( ; it != itEnd; ++it)
1161 {
1162 aBoard << SetMode( it->className(), "Both" )
1163 << CustomStyle( it->className(),
1164 new CustomFillColor( Color::Blue ) )
1165 << *it;
1166 }
1167}
1168// InnerPointsRange
1169
1170// OuterPointsRange
1171template <typename TIterator, typename TKSpace>
1172void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1173 const ConstRangeAdapter<TIterator, functors::SCellToOuterPoint<TKSpace>,
1174 typename TKSpace::Point > & object )
1175{
1176 typedef typename TKSpace::Point Point;
1177 typedef ConstRangeAdapter<TIterator, functors::SCellToOuterPoint<TKSpace>, Point > Range;
1178 typedef typename Range::ConstIterator ConstIterator;
1179
1180 ConstIterator it ( object.begin() );
1181 ConstIterator itEnd ( object.end() );
1182 for( ; it != itEnd; ++it)
1183 {
1184 aBoard << SetMode( it->className(), "Both" )
1185 << CustomStyle( it->className(),
1186 new CustomFillColor( Color::Green ) )
1187 << *it;
1188 }
1189}
1190// OuterPointsRange
1191
1192// IncidentPointsRange
1193template <typename TIterator, typename TKSpace>
1194void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1195 const ConstRangeAdapter<TIterator, functors::SCellToIncidentPoints<TKSpace>,
1196 std::pair<typename TKSpace::Point, typename TKSpace::Point> > & object )
1197{
1198 typedef typename TKSpace::Point Point;
1199 typedef std::pair<Point, Point> Pair;
1200 typedef ConstRangeAdapter<TIterator, functors::SCellToIncidentPoints<TKSpace>, Pair > Range;
1201 typedef typename Range::ConstIterator ConstIterator;
1202
1203 ConstIterator it ( object.begin() );
1204 ConstIterator itEnd ( object.end() );
1205 for( ; it != itEnd; ++it)
1206 {
1207 Pair pair(*it);
1208 aBoard << SetMode( pair.first.className(), "Both" )
1209 << CustomStyle( pair.first.className(),
1210 new CustomFillColor( Color::Blue ) )
1211 << pair.first
1212 << CustomStyle( pair.second.className(),
1213 new CustomFillColor( Color::Green ) )
1214 << pair.second;
1215 }
1216}
1217// IncidentPointsRange
1218
1219// HyperRectDomain
1220template<typename TSpace>
1221inline
1222void DGtal::Display2DFactory::drawAsGrid( DGtal::Board2D & aboard,
1223 const DGtal::HyperRectDomain<TSpace> & h )
1224{
1225 typedef typename TSpace::Integer Integer;
1226
1227 FATAL_ERROR(TSpace::dimension == 2 || "drawAsGrid-NOT-YET-IMPLEMENTED-in-ND");
1228
1229 if (TSpace::dimension == 2)
1230 {
1231 for (double x = NumberTraits<Integer>::castToDouble(h.myLowerBound[0]);
1232 x <= NumberTraits<Integer>::castToDouble(h.myUpperBound[0]); x++)
1233 aboard.drawLine(x,
1234 NumberTraits<Integer>::castToDouble(h.myLowerBound[1]) -
1235 0.5,
1236 x,
1237 NumberTraits<Integer>::castToDouble(h.myUpperBound[1]) +
1238 0.5);
1239
1240 for (double y = NumberTraits<Integer>::castToDouble(h.myLowerBound[1]);
1241 y <= NumberTraits<Integer>::castToDouble(h.myUpperBound[1]); y++)
1242 aboard.drawLine(NumberTraits<Integer>::castToDouble(h.myLowerBound[0]) -
1243 0.5,
1244 y,
1245 NumberTraits<Integer>::castToDouble(h.myUpperBound[0]) +
1246 0.5,
1247 y);
1248
1249 for (double x = NumberTraits<Integer>::castToDouble(h.myLowerBound[0]);
1250 x <= NumberTraits<Integer>::castToDouble(h.myUpperBound[0]); x++)
1251 for (double y = NumberTraits<Integer>::castToDouble(h.myLowerBound[1]);
1252 y <= NumberTraits<Integer>::castToDouble(h.myUpperBound[1]); y++)
1253 aboard.fillCircle(x, y, 0.1);
1254 }
1255}
1256
1257template<typename TSpace>
1258inline
1259void DGtal::Display2DFactory::drawAsPaving( DGtal::Board2D & aboard,
1260 const DGtal::HyperRectDomain<TSpace> & h )
1261{
1262 typedef typename TSpace::Integer Integer;
1263
1264 FATAL_ERROR(TSpace::dimension==2 || "drawAsPaving-NOT-YET-IMPLEMENTED-in-ND" );
1265
1266 if (TSpace::dimension == 2)
1267 {
1268 for (DGtal::int64_t x = NumberTraits<Integer>::castToInt64_t(h.myLowerBound[0]);
1269 x <= NumberTraits<Integer>::castToInt64_t(h.myUpperBound[0]); x++)
1270 for (DGtal::int64_t y = NumberTraits<Integer>::castToInt64_t(h.myLowerBound[1]);
1271 y <= NumberTraits<Integer>::castToInt64_t(h.myUpperBound[1]); y++)
1272 aboard.drawRectangle(x - 0.5, y + 0.5, 1, 1);
1273 }
1274}
1275
1276template<typename TSpace>
1277inline
1278void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1279 const DGtal::HyperRectDomain<TSpace> & h )
1280{
1281 std::string mode = board.getMode( h.className() );
1282 FATAL_ERROR((mode=="" || mode=="Grid" || mode=="Paving") ||
1283 ("draw( DGtal::Board2D & board, const DGtal::HyperRectDomain<TSpace> & h ): Unknown mode "+mode)=="");
1284
1285 if ( ( mode == "" ) || ( mode == "Grid" ) )
1286 drawAsGrid( board, h );
1287 else if ( mode == "Paving" )
1288 drawAsPaving( board, h );
1289}
1290// HyperRectDomain
1291
1292
1293// ImageContainerByHashTree
1294template <typename C, typename Domain, typename Value, typename HashKey>
1295inline
1296void DGtal::Display2DFactory::drawImageRecursive( DGtal::Board2D & aBoard,
1297 const DGtal::experimental::ImageContainerByHashTree<Domain, Value, HashKey> & i,
1298 HashKey key,
1299 const double p[2],
1300 const double len,
1301 LibBoard::Board & board,
1302 const C& cmap )
1303{
1304
1305 FATAL_ERROR ( Domain::dimension == 2 );
1306
1307 double np[2], nlen;
1308
1309 //Node* n = i.getNode ( key );
1310 if ( i.getNode ( key ) )
1311 {
1312 Color c;
1313 c = cmap ( i.getNode ( key )->getObject() );
1314 board.setFillColorRGBi ( c.red(), c.green(), c.blue() );
1315
1316 board.drawRectangle ( p[0], p[1], len, len );
1317 }
1318 else
1319 {
1320 HashKey children[4];
1321 i.myMorton.childrenKeys ( key, children );
1322
1323 nlen = len / 2.0;
1324
1325 np[0] = p[0];
1326 np[1] = p[1] - nlen;
1327 drawImageRecursive<C>( aBoard, i, children[0], np, nlen, board, cmap );
1328
1329 np[0] = p[0] + nlen;
1330 np[1] = p[1] - nlen;
1331 drawImageRecursive<C>( aBoard, i, children[1], np, nlen, board, cmap );
1332
1333 np[0] = p[0];
1334 np[1] = p[1];
1335 drawImageRecursive<C>( aBoard, i, children[2], np, nlen, board, cmap );
1336
1337 np[0] = p[0] + nlen;
1338 np[1] = p[1];
1339 drawImageRecursive<C>( aBoard, i, children[3], np, nlen, board, cmap );
1340 }
1341}
1342
1343template <typename C, typename Domain, typename Value, typename HashKey>
1344inline
1345void DGtal::Display2DFactory::drawImageHashTree( Board2D & board,
1346 const DGtal::experimental::ImageContainerByHashTree<Domain, Value, HashKey> & i,
1347 const Value &minV, const Value &maxV )
1348{
1349 static const HashKey ROOT_KEY = static_cast<HashKey>(1);
1350
1351 FATAL_ERROR ( Domain::dimension == 2 );
1352
1353 C colormap ( minV, maxV );
1354
1355 double p[2];
1356 double len;
1357
1358 p[0] = i.myOrigin[0];
1359 p[1] = i.myOrigin[1] + i.getSpanSize();
1360
1361 len = i.getSpanSize();
1362
1363 drawImageRecursive<C>( board, i, ROOT_KEY, p, len, board, colormap );
1364}
1365// ImageContainerByHashTree
1366
1367// Draw image generic
1368// ImageContainerBySTLVector, ImageContainerByHashTree, Image and ImageAdapter...
1369template <typename Colormap, typename Image>
1370inline
1371void DGtal::Display2DFactory::drawImage( DGtal::Board2D & board,
1372 const Image & i,
1373 const typename Image::Value & minV,
1374 const typename Image::Value & maxV )
1375{
1376 typedef typename Image::Domain D;
1377
1378 FATAL_ERROR(D::Space::dimension == 2);
1379
1380 Colormap colormap(minV, maxV);
1381 Color c;
1382 typename Image::Value val;
1383 for (typename Image::Domain::ConstIterator it = i.domain().begin();
1384 it != i.domain().end(); ++it)
1385 {
1386 val = i.operator()( (*it) );
1387 c = colormap( val );
1388 board.setFillColorRGBi( c.red(), c.green(), c.blue());
1389 board.drawRectangle( NumberTraits<typename Image::Domain::Space::Integer>::
1390 castToDouble((*it)[0]) - 0.5,
1391 NumberTraits<typename Image::Domain::Space::Integer>::
1392 castToDouble((*it)[1]) + 0.5, 1, 1);
1393 }
1394}
1395
1396// KhalimskyPreCell
1397template < DGtal::Dimension dim, typename TInteger >
1398inline
1399void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1400 const DGtal::KhalimskyCell<dim, TInteger> & k )
1401{
1402 draw( board, k.preCell() );
1403}
1404
1405// KhalimskyPreCell
1406template < DGtal::Dimension dim, typename TInteger >
1407inline
1408void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1409 const DGtal::KhalimskyPreCell<dim, TInteger> & k )
1410{
1411 FATAL_ERROR( dim == 2 );
1412
1413 float x = (float)
1414 ( NumberTraits<TInteger>::castToInt64_t( k.coordinates[0] ) >> 1 );
1415 float y = (float)
1416 ( NumberTraits<TInteger>::castToInt64_t( k.coordinates[1] ) >> 1 );
1417 float retract = 0.05f;
1418 bool xodd = ( k.coordinates[ 0 ] & 1 );
1419 bool yodd = ( k.coordinates[ 1 ] & 1 );
1420 float dx = xodd ? 1.0f - 2.0f*retract : 2.0f*retract;
1421 float dy = yodd ? 1.0f - 2.0f*retract : 2.0f*retract;
1422 board.drawRectangle( !xodd ? x - retract - 0.5 : x + retract - 0.5,
1423 !yodd ? y + retract - 0.5 : y - retract + 0.5,
1424 dx, dy );
1425}
1426// KhalimskyPreCell
1427
1428
1429// Object
1430template <typename TDigitalTopology, typename TDigitalSet>
1431inline
1432void DGtal::Display2DFactory::drawWithAdjacencies( DGtal::Board2D & aBoard,
1433 const DGtal::Object<TDigitalTopology, TDigitalSet> & o )
1434{
1435 typedef TDigitalSet DigitalSet;
1436 typedef typename DigitalSet::Point Point;
1437
1438 typedef TDigitalTopology DigitalTopology;
1439 typedef typename DigitalSet::Domain Domain;
1440 typedef
1441 typename DigitalSetSelector < Domain,
1442 SMALL_DS + HIGH_ITER_DS >::Type SmallSet;
1443 typedef Object<DigitalTopology, SmallSet> SmallObject;
1444
1445 Point p;
1446
1447 for (typename TDigitalSet::ConstIterator it = o.pointSet().begin();
1448 it != o.pointSet().end();
1449 ++it)
1450 {
1451 //Brute-force scan of the neighborhood.
1452 SmallObject neig = o.properNeighborhood(*it);
1453 for (typename SmallObject::DigitalSet::ConstIterator it2 = neig.pointSet().begin();
1454 it2 != neig.pointSet().end();
1455 ++it2)
1456 {
1457 p = (*it2) - (*it);
1458 draw(aBoard, p, (*it));
1459 }
1460 }
1461}
1462
1463template <typename TDigitalTopology, typename TDigitalSet>
1464inline
1465void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1466 const DGtal::Object<TDigitalTopology, TDigitalSet> & o )
1467{
1468 std::string mode = board.getMode( o.className() );
1469 if ( mode == "" )
1470 draw( board, o.pointSet() );
1471 else
1472 if ( mode == "DrawAdjacencies" )
1473 {
1474 draw( board, o.pointSet() );
1475 drawWithAdjacencies( board, o );
1476 }
1477 else
1478 FATAL_ERROR(false && (("draw( DGtal::Board2D & board, const DGtal::Object<TDigitalTopology, TDigitalSet> & o ): Unknown mode " + mode) == ""));
1479}
1480// Object
1481
1482// CubicalComplex
1483template < typename TKSpace, typename TCellContainer >
1484inline
1485void
1486DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1487 const DGtal::CubicalComplex<TKSpace, TCellContainer> & cc )
1488{
1489 FATAL_ERROR( cc.dimension == 2);
1490 typedef DGtal::CubicalComplex<TKSpace, TCellContainer> CC;
1491 typedef typename CC::KSpace KSpace;
1492 typedef typename CC::Point Point;
1493 typedef typename CC::ConstIterator ConstIterator;
1494 typedef typename KSpace::Integer Integer;
1495 for ( ConstIterator it = cc.begin(), itE = cc.end(); it != itE; ++it )
1496 { // We are not using operator << for cells in order to use the
1497 // style specified for the cubical complex.
1498 Point kx = cc.space().uKCoords( *it );
1499 float x = (float) ( NumberTraits<Integer>::castToInt64_t( kx[0] ) >> 1 );
1500 float y = (float) ( NumberTraits<Integer>::castToInt64_t( kx[1] ) >> 1 );
1501 float retract = 0.05f;
1502 bool xodd = ( kx[ 0 ] & 1 );
1503 bool yodd = ( kx[ 1 ] & 1 );
1504 float dx = xodd ? 1.0f - 2.0f*retract : 2.0f*retract;
1505 float dy = yodd ? 1.0f - 2.0f*retract : 2.0f*retract;
1506 board.drawRectangle( !xodd ? x - retract - 0.5 : x + retract - 0.5,
1507 !yodd ? y + retract - 0.5 : y - retract + 0.5,
1508 dx, dy );
1509 }
1510}
1511// CubicalComplex
1512
1513
1514// PointVector
1515template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1516inline
1517void DGtal::Display2DFactory::drawAsPaving( DGtal::Board2D & board,
1518 const DGtal::PointVector<dim, TComponent, TContainer> & p )
1519{
1520 FATAL_ERROR(dim == 2);
1521 board.drawRectangle( (float) NumberTraits<TComponent>::castToDouble(p[0]) - 0.5f,
1522 (float) NumberTraits<TComponent>::castToDouble(p[1]) + 0.5f, 1, 1 );
1523}
1524
1525template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1526inline
1527void DGtal::Display2DFactory::drawAsGrid( DGtal::Board2D & board,
1528 const DGtal::PointVector<dim, TComponent, TContainer> & p )
1529{
1530 FATAL_ERROR(dim == 2);
1531 board.fillCircle((float) NumberTraits<TComponent>::castToDouble(p[0]),
1532 (float) NumberTraits<TComponent>::castToDouble(p[1]),0.1);
1533}
1534
1535template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1536inline
1537void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1538 const DGtal::PointVector<dim,TComponent, TContainer> & p )
1539{
1540 std::string mode = board.getMode( p.className() );
1541 FATAL_ERROR( (mode=="Paving" || mode=="Grid" || mode=="Both" || mode=="") ||
1542 ("draw( DGtal::Board2D & board, const DGtal::PointVector<dim, TComponent, TContainer> & p ): Unknown mode "+mode)=="" );
1543
1544 if ( mode == "Paving" || ( mode == "" ) )
1545 drawAsPaving( board, p );
1546 else if ( mode == "Grid" )
1547 drawAsGrid( board, p );
1548 else if ( ( mode == "Both" ))
1549 {
1550 drawAsPaving( board, p );
1551 drawAsGrid( board, p );
1552 }
1553}
1554
1555template<DGtal::Dimension dim, typename TComponent1, typename TComponent2, typename TContainer1, typename TContainer2>
1556inline
1557void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1558 const DGtal::PointVector<dim, TComponent1, TContainer1> & shift,
1559 const DGtal::PointVector<dim, TComponent2, TContainer2> & basepoint )
1560{
1561 FATAL_ERROR(dim == 2);
1562
1563 board.drawArrow((float)basepoint[0], (float) basepoint[1],
1564 (float) basepoint[0] + shift[0], (float)basepoint[1] + shift[1],
1565 true);
1566}
1567// PointVector
1568
1569
1570// Preimage2D
1571template <typename Shape>
1572inline
1573void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1574 const DGtal::Preimage2D<Shape> & p )
1575{
1576 typedef typename Shape::Point Point;
1577 typedef typename std::list<Point>::const_iterator ConstForwardIterator;
1578
1579 // now with accessor
1580 Shape s( p.shape() );
1581 ConstForwardIterator i = p.pHull().begin();
1582 Point pt(*i);
1583 ++i;
1584 while ( i != p.pHull().end() ) {
1585 s.init(pt, *i);
1586 draw(aBoard, s); //s.setStyle(aBoard);
1587 pt = Point(*i);
1588 ++i;
1589 }
1590
1591 i = p.qHull().begin();
1592 pt = Point(*i);
1593 ++i;
1594 while ( i != p.qHull().end() ) {
1595 s.init(pt, *i);
1596 draw(aBoard, s); //s.setStyle(aBoard);
1597 pt = Point(*i);
1598 ++i;
1599 }
1600
1601 Point Pf(*p.pHull().begin());
1602 Point Pl(*p.pHull().rbegin());
1603 Point Qf(*p.qHull().begin());
1604 Point Ql(*p.qHull().rbegin());
1605
1606 s.init(Pf, Ql);
1607 draw(aBoard, s); //s.setStyle(aBoard);
1608 s.init(Qf, Pl);
1609 draw(aBoard, s); //s.setStyle(aBoard);
1610}
1611// Preimage2D
1612
1613// SignedKhalimskyCell
1614template < DGtal::Dimension dim, typename TInteger >
1615inline
1616void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1617 const DGtal::SignedKhalimskyCell<dim, TInteger> & sk )
1618{
1619 draw( board, static_cast< DGtal::SignedKhalimskyPreCell<dim, TInteger> const& >(sk) );
1620}
1621
1622// SignedKhalimskyPreCell
1623template < DGtal::Dimension dim, typename TInteger >
1624inline
1625void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1626 const DGtal::SignedKhalimskyPreCell<dim, TInteger> & sk )
1627{
1628 FATAL_ERROR( dim == 2 );
1629 float x = (float)
1630 ( NumberTraits<TInteger>::castToInt64_t( sk.coordinates[0] ) >> 1 );
1631 float y = (float)
1632 ( NumberTraits<TInteger>::castToInt64_t( sk.coordinates[1] ) >> 1 );
1633 float retract = 0.05f;
1634 bool xodd = ( sk.coordinates[ 0 ] & 1 );
1635 bool yodd = ( sk.coordinates[ 1 ] & 1 );
1636 float dx = xodd ? 1.0f - 2.0f*retract : 2.0f*retract;
1637 float dy = yodd ? 1.0f - 2.0f*retract : 2.0f*retract;
1638 board.drawRectangle( !xodd ? x - retract - 0.5 : x + retract - 0.5,
1639 !yodd ? y + retract - 0.5 : y - retract + 0.5,
1640 dx, dy );
1641}
1642// SignedKhalimskyPreCell
1643
1644
1645// StraightLineFrom2Points
1646template <typename TPoint>
1647inline
1648void DGtal::Display2DFactory::draw(Board2D & aBoard, const DGtal::StraightLineFrom2Points<TPoint> & slf2p)
1649{
1650 // now with accessor
1651 aBoard.drawLine(slf2p.p()[0],slf2p.p()[1],slf2p.q()[0],slf2p.q()[1]);
1652}
1653// StraightLineFrom2Points
1654
1655
1656//
1657
1658
1659inline
1660void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1661 const DGtal::CustomStyle & cs )
1662{
1663 board.myStyles[ cs.myClassname ] = cs.myStyle;
1664}
1665
1666inline
1667void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1668 const DGtal::SetMode & sm )
1669{
1670 board.myModes[ sm.myClassname ] = sm.myMode;
1671}
1672
1673template <typename TSpace, typename TSequence>
1674inline
1675void
1676DGtal::Display2DFactory::draw
1677( DGtal::Board2D & aBoard,
1678 const DGtal::LatticePolytope2D<TSpace, TSequence> & cip )
1679{
1680 typedef typename LibBoard::Point BoardPoint;
1681 typedef typename DGtal::LatticePolytope2D<TSpace>::Point CIPPoint;
1682 typedef typename DGtal::LatticePolytope2D<TSpace>::ConstIterator ConstIterator;
1683 typedef typename DGtal::LatticePolytope2D<TSpace>::Integer Integer;
1684 std::string mode = aBoard.getMode( cip.className() );
1685 FATAL_ERROR( mode=="Filled" || mode=="" || mode=="Transparent" ||
1686 ("draw(Board2D & aBoard, const DGtal::LatticePolytope2D<Space,Sequence> & cip): Unknown mode "+mode)=="" );
1687
1688 std::vector<BoardPoint> pts;
1689
1690 for ( ConstIterator it = cip.begin(), it_end = cip.end(); it != it_end; ++it )
1691 {
1692 CIPPoint p = *it;
1693 pts.push_back( BoardPoint( NumberTraits<Integer>::castToDouble( p[ 0 ] ),
1694 NumberTraits<Integer>::castToDouble( p[ 1 ] ) ) );
1695 }
1696 aBoard.drawClosedPolyline( pts );
1697}
1698
1699
1700// //
1701///////////////////////////////////////////////////////////////////////////////