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.
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.
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/>.
18 * @file Display2DFactory.ih
19 * @author Martial Tola <http://liris.cnrs.fr/martial.tola/>
20 * @date mercredi 28 septembre 2011
24 * Implementation of inline methods defined in Display2DFactory.h
26 * This file is part of the DGtal library.
29 #include <DGtal/io/Style2DFactory.h>
30 #include <DGtal/io/colormaps/GradientColorMap.h>
31 #include <DGtal/topology/CanonicSCellEmbedder.h>
33 ///////////////////////////////////////////////////////////////////////////////
34 // Implementation of inline methods //
37 ///////////////////////////////////////////////////////////////////////////////
38 // Implementation of inline functions and external operators //
39 template <DGtal::Dimension dim, typename TInteger>
42 DGtal::Display2DFactory::drawDECSignedKhalimskyCell(DGtal::Board2D& board, const DGtal::SignedKhalimskyCell<dim, TInteger>& sk)
44 drawDECSignedKhalimskyCell( board, sk.preCell() );
47 template <DGtal::Dimension dim, typename TInteger>
50 DGtal::Display2DFactory::drawDECSignedKhalimskyCell(DGtal::Board2D& board, const DGtal::SignedKhalimskyPreCell<dim, TInteger>& sk)
52 FATAL_ERROR( dim == 2 );
54 using KPS = DGtal::Z2i::KPreSpace;
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 );
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 );
73 if ( KPS::sSign(sk) == KPS::NEG ) DGtal::trace.warning() << "negative khalimsky 0-cell" << std::endl;
74 board.drawCircle(x, y, retract);
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);
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);
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);
93 // DiscreteExteriorCalculus
94 template <DGtal::Dimension dimEmbedded, DGtal::Dimension dimAmbient, typename TLinearAlgebraBackend, typename TInteger>
97 DGtal::Display2DFactory::draw(DGtal::Board2D& board, const DGtal::DiscreteExteriorCalculus<dimEmbedded, dimAmbient, TLinearAlgebraBackend, TInteger>& calculus)
99 BOOST_STATIC_ASSERT(( dimAmbient == 2 ));
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;
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++)
111 const Cell& cell = ci->first;
112 if (calculus.myKSpace.uDim(cell) != static_cast<DGtal::Dimension>(kk)) continue;
114 const bool& flipped = ci->second.flipped;
115 const SCell displayed_cell = calculus.myKSpace.signs(cell, flipped ? KSpace::NEG : KSpace::POS);
117 drawDECSignedKhalimskyCell(board, displayed_cell);
120 // DiscreteExteriorCalculus
123 template <typename TCalculus, DGtal::Order order, DGtal::Duality duality>
126 DGtal::Display2DFactory::draw(DGtal::Board2D& board, const DGtal::KForm<TCalculus, order, duality>& kform)
128 BOOST_STATIC_ASSERT(( TCalculus::dimensionAmbient == 2 ));
129 ASSERT( kform.myCalculus );
131 typedef typename TCalculus::Scalar Scalar;
132 typedef typename TCalculus::Index Index;
136 DGtal::ColorGradientPreset cmap_preset = CMAP_JET;
140 const DGtal::KFormStyle2D* style = dynamic_cast<const DGtal::KFormStyle2D*>(board.myStyles["KForm"].get());
143 cmap_min = style->cmap_min;
144 cmap_max = style->cmap_max;
145 cmap_preset = style->cmap_preset;
146 cmap_repeat = style->cmap_repeat;
150 if (cmap_min == 0 && cmap_max == 0)
153 for (Index index=0; index<kform.myContainer.rows(); index++)
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;
163 if (cmap_min == cmap_max) cmap_max += 1;
165 board.setLineWidth( .5 );
167 if (cmap_repeat < 1 && cmap_preset == DGtal::CMAP_JET)
169 typedef typename DGtal::GradientColorMap<Scalar, DGtal::CMAP_JET> ColorMap;
170 const ColorMap colormap(cmap_min, cmap_max);
171 drawWithColorMap(board, kform, colormap);
175 if (cmap_repeat < 1 && cmap_preset == DGtal::CMAP_GRAYSCALE)
177 typedef typename DGtal::GradientColorMap<Scalar, DGtal::CMAP_GRAYSCALE> ColorMap;
178 const ColorMap colormap(cmap_min, cmap_max);
179 drawWithColorMap(board, kform, colormap);
183 // @todo FIXME add other colomaps
186 typedef typename DGtal::GradientColorMap<Scalar, DGtal::CMAP_HOT> ColorMap;
187 const ColorMap colormap(cmap_min, cmap_max);
188 drawWithColorMap(board, kform, colormap);
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);
198 template <typename TCalculus, DGtal::Order order, DGtal::Duality duality, typename TColorMap>
201 DGtal::Display2DFactory::drawWithColorMap(DGtal::Board2D& board, const DGtal::KForm<TCalculus, order, duality>& kform, const TColorMap& colormap)
203 typedef typename TCalculus::Scalar Scalar;
204 typedef typename TCalculus::SCell SCell;
206 for (typename TCalculus::Index index=0; index<kform.length(); index++)
208 const SCell displayed_cell = kform.getSCell(index);
209 const Scalar displayed_value = kform.myContainer(index);
211 if (std::isfinite(displayed_value)) board.setFillColor( colormap(displayed_value) );
214 drawDECSignedKhalimskyCell(board, displayed_cell);
220 template <typename TCalculus, DGtal::Duality duality>
222 DGtal::Display2DFactory::draw(DGtal::Board2D& board, const DGtal::VectorField<TCalculus, duality>& vector_field)
224 BOOST_STATIC_ASSERT(( TCalculus::dimensionAmbient == 2 ));
225 ASSERT( vector_field.myCalculus );
227 typedef typename DGtal::VectorField<TCalculus, duality>::Vector Vector;
229 typename TCalculus::Scalar scale = .25;
230 typename TCalculus::Scalar epsilon = 1e-8;
233 const DGtal::VectorFieldStyle2D* style = dynamic_cast<const DGtal::VectorFieldStyle2D*>(board.myStyles["VectorField"].get());
236 scale = style->scale;
237 epsilon = style->epsilon;
241 for (typename TCalculus::Index index=0; index<vector_field.length(); index++)
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.;
246 Vector vector = vector_field.getVector(index);
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;
254 board.drawArrow(origin[0],origin[1],origin[0]+vector[0],origin[1]+vector[1]);
260 // AngleLinearMinimizer
262 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
263 const DGtal::AngleLinearMinimizer & a )
266 board.setLineWidth(3.0);
267 board.setPenColor(Color(20,20,200));
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;
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;
285 // AngleLinearMinimizer
288 template <typename TCoordinate, typename TInteger, unsigned short adjacency>
290 void DGtal::Display2DFactory::drawAsBoundingBox( DGtal::Board2D & aBoard,
291 const DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency> & a )
293 typedef typename DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency>::PointD PointD;
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());
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]);
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);
312 aBoard.drawClosedPolyline(bb);
315 template <typename TCoordinate, typename TInteger, unsigned short adjacency>
317 void DGtal::Display2DFactory::drawAsDigitalPoints( DGtal::Board2D & aBoard,
318 const DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency> & a )
320 typedef typename DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency>::ConstIterator ConstIterator;
321 typedef typename IteratorCirculatorTraits<ConstIterator>::Value Point;
323 // Draw a linking polygonal line if the pixels are drawn as points.
324 if(aBoard.getMode("PointVector")=="Grid" || aBoard.getMode("PointVector")=="")
326 std::vector<LibBoard::Point> contour;
327 for (ConstIterator it = a.begin(), itEnd = a.end();
331 double xp = NumberTraits<TInteger>::castToDouble(p[0]);
332 double yp = NumberTraits<TInteger>::castToDouble(p[1]);
333 contour.push_back(LibBoard::Point(xp,yp));
335 aBoard.drawPolyline(contour);
339 for (ConstIterator it = a.begin(), itEnd = a.end();
347 template <typename TCoordinate, typename TInteger, unsigned short adjacency>
349 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
350 const DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency> & a )
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 == "" ) )
359 auto style = new DefaultDrawStyleBB_ArithmeticalDSS();
360 drawAsDigitalPoints( board, a );
361 Style2DFactory::draw( board, style);
362 drawAsBoundingBox( board, a );
366 ASSERT(false && ("draw( DGtal::Board2D & board, const DGtal::ArithmeticalDSS<TCoordinate,TInteger,adjacency> & a ): Unknown mode "+mode)=="" );
370 // ArithmeticalDSSComputer
371 template <typename TIterator, typename TInteger, int connectivity>
373 void DGtal::Display2DFactory::drawAsBoundingBox( DGtal::Board2D & aBoard,
374 const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a )
376 typedef DGtal::PointVector<2,double> PointD;
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);
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]);
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);
396 aBoard.drawClosedPolyline(bb);
399 template <typename TIterator, typename TInteger, int connectivity>
401 void DGtal::Display2DFactory::drawAsDigitalPoints( DGtal::Board2D & aBoard,
402 const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a )
404 typedef TIterator ConstIterator;
405 typedef typename IteratorCirculatorTraits<ConstIterator>::Value Point;
407 ConstIterator itend = a.myL; ++itend;
409 // Draw a linking polygonal line if the pixels are drawn as points.
410 if(aBoard.getMode("PointVector")=="Grid" || aBoard.getMode("PointVector")=="")
412 std::vector<LibBoard::Point> contour;
413 for (ConstIterator i = a.myF; i != itend; ++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));
419 aBoard.drawPolyline(contour);
423 for (ConstIterator i = a.myF; i != itend; ++i) {
429 template <typename TIterator, typename TInteger, int connectivity>
431 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
432 const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a )
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 == "" ) )
441 drawAsDigitalPoints( board, a );
442 drawAsBoundingBox( board, a );
445 FATAL_ERROR_MSG(false, "draw( DGtal::Board2D & board, const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a ): Unknown mode "+mode);
448 // ArithmeticalDSSComputer
451 // AlphaThickSegmentComputer
452 template <typename TInputPoint, typename TConstIterator>
453 void DGtal::Display2DFactory::drawAsBoundingBox( DGtal::Board2D & aBoard,
454 const DGtal::AlphaThickSegmentComputer< TInputPoint, TConstIterator> & anAlphaThickSegment){
455 typedef DGtal::PointVector<2,double> PointD;
457 PointD topLeft, topRight, bottomRight, bottomLeft;
458 anAlphaThickSegment.getBoundingBox(topLeft, topRight, bottomRight, bottomLeft);
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]);
467 template < typename TInputPoint, typename TConstIterator>
468 void 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")=="")
476 std::vector<LibBoard::Point> contour;
477 if (anAlphaThickSegment.isStoringSegmentPoints()){
478 for (ContConstIterator it = anAlphaThickSegment.containerBegin();
479 it != anAlphaThickSegment.containerEnd(); 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));
487 for (ConstIterator it = anAlphaThickSegment.begin(); it != anAlphaThickSegment.end(); 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));
494 if(contour.size()>0){
495 aBoard.drawPolyline(contour);
499 if (anAlphaThickSegment.isStoringSegmentPoints()){
500 for (ContConstIterator it = anAlphaThickSegment.containerBegin();
501 it != anAlphaThickSegment.containerEnd(); it++) {
506 for (ConstIterator it = anAlphaThickSegment.begin(); it != anAlphaThickSegment.end(); it++) {
513 template < typename TInputPoint, typename TConstIterator>
514 void 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 == "" ) )
523 drawAsDigitalPoints( aBoard, anAlphaThickSegment );
524 drawAsBoundingBox( aBoard, anAlphaThickSegment );
527 FATAL_ERROR_MSG(false, "draw( DGtal::Board2D & board, const DGtal::ArithmeticalDSSComputer<TIterator,TInteger,connectivity> & a ): Unknown mode "+mode);
529 // AlphaThickSegmentComputer
533 template <typename TPoint>
535 void DGtal::Display2DFactory::draw(Board2D & aBoard, const DGtal::CircleFrom2Points<TPoint> & cf2p)
538 CircleFrom3Points<TPoint> c(cf2p.pole(),cf2p.p(),cf2p.q());
539 drawArc(aBoard,c,cf2p.p(),cf2p.q(),true);
545 template <typename Point>
547 void DGtal::Display2DFactory::drawArc(Board2D & aBoard, const DGtal::CircleFrom3Points<Point> & cf3p, const Point& aPoint1, const Point& aPoint2, bool anOrientation)
549 typedef typename Point::Coordinate Coordinate;
550 typedef Point Vector;
552 double cx = 0, cy = 0, radius = 1;
556 cf3p.getParameters(cx, cy, radius);
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;
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;
569 aBoard.drawArc (cx, cy, radius, alpha1, alpha2, orientation);
571 catch ( InfiniteNumberException& e )
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]) );
580 template <typename Point>
582 void DGtal::Display2DFactory::drawSector(Board2D & aBoard, const DGtal::CircleFrom3Points<Point> & cf3p, const Point& aPoint1, const Point& aPoint2, bool anOrientation)
584 typedef typename Point::Coordinate Coordinate;
585 typedef Point Vector;
587 double cx = 0, cy = 0, radius = 1;
591 cf3p.getParameters(cx, cy, radius);
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;
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;
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 );
614 catch ( InfiniteNumberException& e )
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]) );
623 template <typename Point>
625 void DGtal::Display2DFactory::drawAnnulus(Board2D & aBoard, const DGtal::CircleFrom3Points<Point> & cf3p,
626 const Point& aPoint1, const Point& aPoint2, bool anOrientation, const double& w)
628 typedef typename Point::Coordinate Coordinate;
629 typedef Point Vector;
631 double cx = 0, cy = 0, radius = 1;
635 cf3p.getParameters(cx, cy, radius);
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;
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;
648 aBoard.drawArc (cx, cy, radius-w, alpha1, alpha2, orientation);
650 aBoard.drawArc (cx, cy, radius+w, alpha1, alpha2, orientation);
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);
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);
664 catch ( InfiniteNumberException& e )
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]) );
673 template <typename Point>
675 void DGtal::Display2DFactory::draw(Board2D & aBoard, const DGtal::CircleFrom3Points<Point> & cf3p, const Point& aPoint1, const Point& aPoint2, bool anOrientation)
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)=="" );
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);
689 template <typename TPoint>
691 void DGtal::Display2DFactory::draw(Board2D & aBoard, const DGtal::CircleFrom3Points<TPoint> & cf3p)
693 typedef typename TPoint::Coordinate Coordinate;
695 double cx = 0, cy = 0, radius = 1;
698 cf3p.getParameters(cx,cy,radius);
699 aBoard.drawCircle (cx,cy,radius);
701 catch ( InfiniteNumberException& e )
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]) );
712 // DigitalSetBySTLSet
713 template<typename Domain, typename Compare>
715 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
716 const DGtal::DigitalSetBySTLSet<Domain, Compare> & s )
718 typedef typename Domain::Point Point;
719 typedef typename std::set<Point>::const_iterator ConstIterator;
721 BOOST_STATIC_ASSERT(Domain::Space::dimension == 2);
722 for(ConstIterator it = s.begin(); it != s.end(); ++it)
725 // DigitalSetBySTLSet
728 // DigitalSetByAssociativeContainer
729 template<typename Domain, typename Container>
731 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
732 const DGtal::DigitalSetByAssociativeContainer<Domain,Container> & s )
734 typedef typename DigitalSetByAssociativeContainer<Domain,Container>::ConstIterator ConstIterator;
736 BOOST_STATIC_ASSERT(Domain::Space::dimension == 2);
737 for(ConstIterator it = s.begin(); it != s.end(); ++it)
740 // DigitalSetByAssociativeContainer
743 // DigitalSetBySTLVector
744 template<typename Domain>
746 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
747 const DGtal::DigitalSetBySTLVector<Domain> & v )
749 typedef typename Domain::Point Point;
750 typedef typename std::vector<Point>::const_iterator ConstIterator;
752 if (Domain::dimension == 2)
754 for(ConstIterator it = v.begin(); it != v.end(); ++it)
758 FATAL_ERROR_MSG(false, "draw-NOT-YET-IMPLEMENTED-in-ND");
760 // DigitalSetBySTLVector
764 template <typename TIterator, typename TInteger, int connectivity>
766 void DGtal::Display2DFactory::drawAsPolygon( DGtal::Board2D & aBoard,
767 const DGtal::FP<TIterator,TInteger,connectivity> & fp )
769 typedef DGtal::PointVector<2,TInteger> Point;
770 typedef std::list<Point> Polygon;
772 typedef typename Polygon::const_iterator ConstIterator;
775 std::vector<LibBoard::Point> polyline;
778 ConstIterator i = fp.polygon().begin();
779 for ( ;i != fp.polygon().end();++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));
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));
793 aBoard.drawPolyline(polyline);
796 template <typename TIterator, typename TInteger, int connectivity>
798 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
799 const DGtal::FP<TIterator,TInteger,connectivity> & fp )
801 std::string mode = board.getMode( fp.className() );
802 if ( mode == "Polygon" )
803 drawAsPolygon( board, fp );
804 else if ( ( mode == "Both" ) || ( mode == "" ) )
806 drawAsPolygon( board, fp );
810 FATAL_ERROR_MSG(false, "draw( DGtal::Board2D & board, const DGtal::FP<TIterator,TInteger,connectivity> & fp ): Unknown mode "+mode);
817 template <typename TInteger>
819 void DGtal::Display2DFactory::drawAsGrid( DGtal::Board2D & aBoard,
820 const DGtal::FreemanChain<TInteger> & f )
822 typedef TInteger Integer;
823 typedef PointVector<2, Integer> Point;
825 std::vector<Point> aVContour;
826 FreemanChain<TInteger>::getContourPoints(f, aVContour);
827 TInteger minX, minY, maxX, maxY;
828 f.computeBoundingBox(minX, minY, maxX, maxY);
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])));
835 aBoard.drawPolyline(contour);
838 template <typename TInteger>
840 void DGtal::Display2DFactory::drawAsInterGrid( DGtal::Board2D & aBoard,
841 const DGtal::FreemanChain<TInteger> & f )
843 typedef TInteger Integer;
844 typedef PointVector<2, Integer> Point;
846 std::vector<Point> aVContour;
847 FreemanChain<TInteger>::getContourPoints(f, aVContour);
848 TInteger minX, minY, maxX, maxY;
849 f.computeBoundingBox(minX, minY, maxX, maxY);
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));
856 aBoard.drawPolyline(contour);
859 template <typename TInteger>
861 void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
862 const DGtal::FreemanChain<TInteger> & f )
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);
868 if ( mode == "Grid" || ( mode == "" ) )
869 drawAsGrid( aBoard, f );
870 else if ( mode == "InterGrid" )
871 drawAsInterGrid( aBoard, f );
876 // StabbingLineComputer
877 template <typename TConstIterator>
879 void DGtal::Display2DFactory::draw(DGtal::Board2D & aBoard,
880 const DGtal::StabbingLineComputer<TConstIterator> & g)
882 typedef TConstIterator ConstIterator;
883 typedef typename IteratorCirculatorTraits<ConstIterator>::Value Pair;
884 typedef typename Pair::first_type Point;
886 double alpha, beta, gamma;
887 g.getParameters(alpha, beta, gamma);
889 typedef typename Point::Coordinate Coordinate;
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);
902 ConstIterator it (g.end());
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);
913 aBoard.drawLine(fx,fy,lx,ly);
915 // StabbingLineComputer
917 // StabbingCircleComputer
918 template <typename TConstIterator>
920 void DGtal::Display2DFactory::draw(DGtal::Board2D & aBoard,
921 const DGtal::StabbingCircleComputer<TConstIterator> & g)
924 typedef TConstIterator ConstIterator;
925 typedef typename IteratorCirculatorTraits<ConstIterator>::Value Pair;
926 typedef typename Pair::first_type Point;
932 typedef typename Point::Coordinate Coordinate;
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 );
942 ConstIterator it (g.end());
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 );
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) );
965 FATAL_ERROR( g.getStabbingLineComputerPtr().get() != 0 );
966 bool orientation = g.getStabbingLineComputerPtr()->isClockwiseOriented();
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 );
975 drawArc( aBoard, circleToDraw, p1, p2, orientation );
979 FATAL_ERROR( g.getStabbingLineComputerPtr().get() != 0 );
980 aBoard << ( *(g.getStabbingLineComputerPtr()) );
985 // StabbingCircleComputer
990 template <typename TIterator,typename TInteger>
992 void DGtal::Display2DFactory::draw(DGtal::Board2D & aBoard, const DGtal::FrechetShortcut<TIterator,TInteger> & f)
994 typedef TIterator Iterator;
995 typedef PointVector<2,TInteger> Point;
996 typedef typename Point::Coordinate Coordinate;
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]);
1003 // get last point of the shortcut
1004 Iterator it (f.end());
1007 double px2 = NumberTraits<Coordinate>::castToDouble(p2[0]);
1008 double py2 = NumberTraits<Coordinate>::castToDouble(p2[1]);
1010 aBoard.drawLine(px1,py1,px2,py2);
1017 template <typename TKSpace>
1018 void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1019 const GridCurve<TKSpace> & object )
1022 std::string mode = aBoard.getMode( object.className() );
1024 DGtal::Display2DFactory::drawFill(aBoard, object);
1026 typedef typename GridCurve<TKSpace>::ConstIterator ConstIterator;
1027 ConstIterator it ( object.begin() );
1028 ConstIterator itEnd ( object.end() );
1029 for( ; it != itEnd; ++it)
1036 template <typename TKSpace>
1037 void DGtal::Display2DFactory::drawFill( DGtal::Board2D & aBoard,
1038 const GridCurve<TKSpace> & object )
1042 typedef typename GridCurve<TKSpace>::PointsRange::ConstIterator Iterator;
1043 typedef typename GridCurve<TKSpace>::PointsRange Range; //range
1045 Range r = object.getPointsRange();
1046 Iterator it (r.begin());
1047 Iterator itEnd (r.end());
1049 std::vector< LibBoard::Point > aPolygon;
1050 for( ; it != itEnd; ++it)
1052 LibBoard::Point pt((*it)[0], (*it)[1]);
1053 aPolygon.push_back(pt);
1055 aBoard.fillPolyline(aPolygon);
1064 template <typename TIterator, typename TSCell>
1065 void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1066 const ConstRangeAdapter<TIterator, functors::Identity, TSCell> & object )
1068 typedef ConstRangeAdapter<TIterator, functors::Identity, TSCell> Range;
1069 typedef typename Range::ConstIterator ConstIterator;
1071 ConstIterator it ( object.begin() );
1072 ConstIterator itEnd ( object.end() );
1073 for( ; it != itEnd; ++it)
1081 template <typename TIterator, typename TKSpace>
1082 void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1083 const ConstRangeAdapter<TIterator, functors::SCellToPoint<TKSpace>, typename TKSpace::Point> & object )
1085 typedef ConstRangeAdapter<TIterator, functors::SCellToPoint<TKSpace>, typename TKSpace::Point> Range;
1086 typedef typename Range::ConstIterator ConstIterator;
1088 ConstIterator it ( object.begin() );
1089 ConstIterator itEnd ( object.end() );
1090 for( ; it != itEnd; ++it)
1092 aBoard << SetMode(it->className(),"Grid");
1099 template <typename TIterator, typename TKSpace>
1100 void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1101 const ConstRangeAdapter<TIterator, CanonicSCellEmbedder<TKSpace>,
1102 typename TKSpace::Space::RealPoint> & object )
1104 typedef typename TKSpace::Space::RealPoint RPoint;
1105 typedef ConstRangeAdapter<TIterator, CanonicSCellEmbedder<TKSpace>, RPoint > Range;
1106 typedef typename Range::ConstIterator ConstIterator;
1108 ConstIterator it ( object.begin() );
1109 ConstIterator itEnd ( object.end() );
1110 for( ; it != itEnd; ++it)
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 );
1121 template <typename TIterator, typename TKSpace>
1122 void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1123 const ConstRangeAdapter<TIterator, functors::SCellToArrow<TKSpace>,
1124 std::pair<typename TKSpace::Point, typename TKSpace::Vector> > & object )
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;
1132 ConstIterator it ( object.begin() );
1133 ConstIterator itEnd ( object.end() );
1134 for( ; it != itEnd; ++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);
1149 template <typename TIterator, typename TKSpace>
1150 void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1151 const ConstRangeAdapter<TIterator, functors::SCellToInnerPoint<TKSpace>,
1152 typename TKSpace::Point > & object )
1154 typedef typename TKSpace::Point Point;
1155 typedef ConstRangeAdapter<TIterator, functors::SCellToInnerPoint<TKSpace>, Point > Range;
1156 typedef typename Range::ConstIterator ConstIterator;
1158 ConstIterator it ( object.begin() );
1159 ConstIterator itEnd ( object.end() );
1160 for( ; it != itEnd; ++it)
1162 aBoard << SetMode( it->className(), "Both" )
1163 << CustomStyle( it->className(),
1164 new CustomFillColor( Color::Blue ) )
1171 template <typename TIterator, typename TKSpace>
1172 void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1173 const ConstRangeAdapter<TIterator, functors::SCellToOuterPoint<TKSpace>,
1174 typename TKSpace::Point > & object )
1176 typedef typename TKSpace::Point Point;
1177 typedef ConstRangeAdapter<TIterator, functors::SCellToOuterPoint<TKSpace>, Point > Range;
1178 typedef typename Range::ConstIterator ConstIterator;
1180 ConstIterator it ( object.begin() );
1181 ConstIterator itEnd ( object.end() );
1182 for( ; it != itEnd; ++it)
1184 aBoard << SetMode( it->className(), "Both" )
1185 << CustomStyle( it->className(),
1186 new CustomFillColor( Color::Green ) )
1192 // IncidentPointsRange
1193 template <typename TIterator, typename TKSpace>
1194 void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1195 const ConstRangeAdapter<TIterator, functors::SCellToIncidentPoints<TKSpace>,
1196 std::pair<typename TKSpace::Point, typename TKSpace::Point> > & object )
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;
1203 ConstIterator it ( object.begin() );
1204 ConstIterator itEnd ( object.end() );
1205 for( ; it != itEnd; ++it)
1208 aBoard << SetMode( pair.first.className(), "Both" )
1209 << CustomStyle( pair.first.className(),
1210 new CustomFillColor( Color::Blue ) )
1212 << CustomStyle( pair.second.className(),
1213 new CustomFillColor( Color::Green ) )
1217 // IncidentPointsRange
1220 template<typename TSpace>
1222 void DGtal::Display2DFactory::drawAsGrid( DGtal::Board2D & aboard,
1223 const DGtal::HyperRectDomain<TSpace> & h )
1225 typedef typename TSpace::Integer Integer;
1227 FATAL_ERROR(TSpace::dimension == 2 || "drawAsGrid-NOT-YET-IMPLEMENTED-in-ND");
1229 if (TSpace::dimension == 2)
1231 for (double x = NumberTraits<Integer>::castToDouble(h.myLowerBound[0]);
1232 x <= NumberTraits<Integer>::castToDouble(h.myUpperBound[0]); x++)
1234 NumberTraits<Integer>::castToDouble(h.myLowerBound[1]) -
1237 NumberTraits<Integer>::castToDouble(h.myUpperBound[1]) +
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]) -
1245 NumberTraits<Integer>::castToDouble(h.myUpperBound[0]) +
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);
1257 template<typename TSpace>
1259 void DGtal::Display2DFactory::drawAsPaving( DGtal::Board2D & aboard,
1260 const DGtal::HyperRectDomain<TSpace> & h )
1262 typedef typename TSpace::Integer Integer;
1264 FATAL_ERROR(TSpace::dimension==2 || "drawAsPaving-NOT-YET-IMPLEMENTED-in-ND" );
1266 if (TSpace::dimension == 2)
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);
1276 template<typename TSpace>
1278 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1279 const DGtal::HyperRectDomain<TSpace> & h )
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)=="");
1285 if ( ( mode == "" ) || ( mode == "Grid" ) )
1286 drawAsGrid( board, h );
1287 else if ( mode == "Paving" )
1288 drawAsPaving( board, h );
1293 // ImageContainerByHashTree
1294 template <typename C, typename Domain, typename Value, typename HashKey>
1296 void DGtal::Display2DFactory::drawImageRecursive( DGtal::Board2D & aBoard,
1297 const DGtal::experimental::ImageContainerByHashTree<Domain, Value, HashKey> & i,
1301 LibBoard::Board & board,
1305 FATAL_ERROR ( Domain::dimension == 2 );
1309 //Node* n = i.getNode ( key );
1310 if ( i.getNode ( key ) )
1313 c = cmap ( i.getNode ( key )->getObject() );
1314 board.setFillColorRGBi ( c.red(), c.green(), c.blue() );
1316 board.drawRectangle ( p[0], p[1], len, len );
1320 HashKey children[4];
1321 i.myMorton.childrenKeys ( key, children );
1326 np[1] = p[1] - nlen;
1327 drawImageRecursive<C>( aBoard, i, children[0], np, nlen, board, cmap );
1329 np[0] = p[0] + nlen;
1330 np[1] = p[1] - nlen;
1331 drawImageRecursive<C>( aBoard, i, children[1], np, nlen, board, cmap );
1335 drawImageRecursive<C>( aBoard, i, children[2], np, nlen, board, cmap );
1337 np[0] = p[0] + nlen;
1339 drawImageRecursive<C>( aBoard, i, children[3], np, nlen, board, cmap );
1343 template <typename C, typename Domain, typename Value, typename HashKey>
1345 void DGtal::Display2DFactory::drawImageHashTree( Board2D & board,
1346 const DGtal::experimental::ImageContainerByHashTree<Domain, Value, HashKey> & i,
1347 const Value &minV, const Value &maxV )
1349 static const HashKey ROOT_KEY = static_cast<HashKey>(1);
1351 FATAL_ERROR ( Domain::dimension == 2 );
1353 C colormap ( minV, maxV );
1358 p[0] = i.myOrigin[0];
1359 p[1] = i.myOrigin[1] + i.getSpanSize();
1361 len = i.getSpanSize();
1363 drawImageRecursive<C>( board, i, ROOT_KEY, p, len, board, colormap );
1365 // ImageContainerByHashTree
1367 // Draw image generic
1368 // ImageContainerBySTLVector, ImageContainerByHashTree, Image and ImageAdapter...
1369 template <typename Colormap, typename Image>
1371 void DGtal::Display2DFactory::drawImage( DGtal::Board2D & board,
1373 const typename Image::Value & minV,
1374 const typename Image::Value & maxV )
1376 typedef typename Image::Domain D;
1378 FATAL_ERROR(D::Space::dimension == 2);
1380 Colormap colormap(minV, maxV);
1382 typename Image::Value val;
1383 for (typename Image::Domain::ConstIterator it = i.domain().begin();
1384 it != i.domain().end(); ++it)
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);
1397 template < DGtal::Dimension dim, typename TInteger >
1399 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1400 const DGtal::KhalimskyCell<dim, TInteger> & k )
1402 draw( board, k.preCell() );
1406 template < DGtal::Dimension dim, typename TInteger >
1408 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1409 const DGtal::KhalimskyPreCell<dim, TInteger> & k )
1411 FATAL_ERROR( dim == 2 );
1414 ( NumberTraits<TInteger>::castToInt64_t( k.coordinates[0] ) >> 1 );
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,
1430 template <typename TDigitalTopology, typename TDigitalSet>
1432 void DGtal::Display2DFactory::drawWithAdjacencies( DGtal::Board2D & aBoard,
1433 const DGtal::Object<TDigitalTopology, TDigitalSet> & o )
1435 typedef TDigitalSet DigitalSet;
1436 typedef typename DigitalSet::Point Point;
1438 typedef TDigitalTopology DigitalTopology;
1439 typedef typename DigitalSet::Domain Domain;
1441 typename DigitalSetSelector < Domain,
1442 SMALL_DS + HIGH_ITER_DS >::Type SmallSet;
1443 typedef Object<DigitalTopology, SmallSet> SmallObject;
1447 for (typename TDigitalSet::ConstIterator it = o.pointSet().begin();
1448 it != o.pointSet().end();
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();
1458 draw(aBoard, p, (*it));
1463 template <typename TDigitalTopology, typename TDigitalSet>
1465 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1466 const DGtal::Object<TDigitalTopology, TDigitalSet> & o )
1468 std::string mode = board.getMode( o.className() );
1470 draw( board, o.pointSet() );
1472 if ( mode == "DrawAdjacencies" )
1474 draw( board, o.pointSet() );
1475 drawWithAdjacencies( board, o );
1478 FATAL_ERROR(false && (("draw( DGtal::Board2D & board, const DGtal::Object<TDigitalTopology, TDigitalSet> & o ): Unknown mode " + mode) == ""));
1483 template < typename TKSpace, typename TCellContainer >
1486 DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1487 const DGtal::CubicalComplex<TKSpace, TCellContainer> & cc )
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,
1515 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1517 void DGtal::Display2DFactory::drawAsPaving( DGtal::Board2D & board,
1518 const DGtal::PointVector<dim, TComponent, TContainer> & p )
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 );
1525 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1527 void DGtal::Display2DFactory::drawAsGrid( DGtal::Board2D & board,
1528 const DGtal::PointVector<dim, TComponent, TContainer> & p )
1530 FATAL_ERROR(dim == 2);
1531 board.fillCircle((float) NumberTraits<TComponent>::castToDouble(p[0]),
1532 (float) NumberTraits<TComponent>::castToDouble(p[1]),0.1);
1535 template<DGtal::Dimension dim, typename TComponent, typename TContainer>
1537 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1538 const DGtal::PointVector<dim,TComponent, TContainer> & p )
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)=="" );
1544 if ( mode == "Paving" || ( mode == "" ) )
1545 drawAsPaving( board, p );
1546 else if ( mode == "Grid" )
1547 drawAsGrid( board, p );
1548 else if ( ( mode == "Both" ))
1550 drawAsPaving( board, p );
1551 drawAsGrid( board, p );
1555 template<DGtal::Dimension dim, typename TComponent1, typename TComponent2, typename TContainer1, typename TContainer2>
1557 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1558 const DGtal::PointVector<dim, TComponent1, TContainer1> & shift,
1559 const DGtal::PointVector<dim, TComponent2, TContainer2> & basepoint )
1561 FATAL_ERROR(dim == 2);
1563 board.drawArrow((float)basepoint[0], (float) basepoint[1],
1564 (float) basepoint[0] + shift[0], (float)basepoint[1] + shift[1],
1571 template <typename Shape>
1573 void DGtal::Display2DFactory::draw( DGtal::Board2D & aBoard,
1574 const DGtal::Preimage2D<Shape> & p )
1576 typedef typename Shape::Point Point;
1577 typedef typename std::list<Point>::const_iterator ConstForwardIterator;
1579 // now with accessor
1580 Shape s( p.shape() );
1581 ConstForwardIterator i = p.pHull().begin();
1584 while ( i != p.pHull().end() ) {
1586 draw(aBoard, s); //s.setStyle(aBoard);
1591 i = p.qHull().begin();
1594 while ( i != p.qHull().end() ) {
1596 draw(aBoard, s); //s.setStyle(aBoard);
1601 Point Pf(*p.pHull().begin());
1602 Point Pl(*p.pHull().rbegin());
1603 Point Qf(*p.qHull().begin());
1604 Point Ql(*p.qHull().rbegin());
1607 draw(aBoard, s); //s.setStyle(aBoard);
1609 draw(aBoard, s); //s.setStyle(aBoard);
1613 // SignedKhalimskyCell
1614 template < DGtal::Dimension dim, typename TInteger >
1616 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1617 const DGtal::SignedKhalimskyCell<dim, TInteger> & sk )
1619 draw( board, static_cast< DGtal::SignedKhalimskyPreCell<dim, TInteger> const& >(sk) );
1622 // SignedKhalimskyPreCell
1623 template < DGtal::Dimension dim, typename TInteger >
1625 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1626 const DGtal::SignedKhalimskyPreCell<dim, TInteger> & sk )
1628 FATAL_ERROR( dim == 2 );
1630 ( NumberTraits<TInteger>::castToInt64_t( sk.coordinates[0] ) >> 1 );
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,
1642 // SignedKhalimskyPreCell
1645 // StraightLineFrom2Points
1646 template <typename TPoint>
1648 void DGtal::Display2DFactory::draw(Board2D & aBoard, const DGtal::StraightLineFrom2Points<TPoint> & slf2p)
1650 // now with accessor
1651 aBoard.drawLine(slf2p.p()[0],slf2p.p()[1],slf2p.q()[0],slf2p.q()[1]);
1653 // StraightLineFrom2Points
1660 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1661 const DGtal::CustomStyle & cs )
1663 board.myStyles[ cs.myClassname ] = cs.myStyle;
1667 void DGtal::Display2DFactory::draw( DGtal::Board2D & board,
1668 const DGtal::SetMode & sm )
1670 board.myModes[ sm.myClassname ] = sm.myMode;
1673 template <typename TSpace, typename TSequence>
1676 DGtal::Display2DFactory::draw
1677 ( DGtal::Board2D & aBoard,
1678 const DGtal::LatticePolytope2D<TSpace, TSequence> & cip )
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)=="" );
1688 std::vector<BoardPoint> pts;
1690 for ( ConstIterator it = cip.begin(), it_end = cip.end(); it != it_end; ++it )
1693 pts.push_back( BoardPoint( NumberTraits<Integer>::castToDouble( p[ 0 ] ),
1694 NumberTraits<Integer>::castToDouble( p[ 1 ] ) ) );
1696 aBoard.drawClosedPolyline( pts );
1701 ///////////////////////////////////////////////////////////////////////////////