Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
kopftracer2011.cpp
Go to the documentation of this file.
1/* This file is part of the libdepixelize project
2 Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
3
4 GNU Lesser General Public License Usage
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Lesser General Public License as published by the
7 Free Software Foundation; either version 2.1 of the License, or (at your
8 option) any later version.
9 You should have received a copy of the GNU Lesser General Public License
10 along with this library. If not, see <http://www.gnu.org/licenses/>.
11
12 GNU General Public License Usage
13 Alternatively, this library may be used under the terms of the GNU General
14 Public License as published by the Free Software Foundation, either version
15 2 of the License, or (at your option) any later version.
16 You should have received a copy of the GNU General Public License along with
17 this library. If not, see <http://www.gnu.org/licenses/>.
18
19 This library is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 Lesser General Public License for more details.
23*/
24
25#ifdef HAVE_CONFIG_H
26# include <config.h>
27#endif
28
29#include <glibmm.h>
30
31#include <algorithm>
32#include "kopftracer2011.h"
33#include "priv/colorspace.h"
35#include "priv/branchless.h"
37#include "priv/iterator.h"
38
39#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
40#include <glibmm/datetime.h>
41#include <iostream>
42#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
43
44namespace Tracer {
45namespace Heuristics {
46
50
51struct SparsePixels
52{
53 enum Diagonal {
57 MAIN_DIAGONAL = 0,
61 SECONDARY_DIAGONAL = 1
62 };
63
64 typedef std::pair<PixelGraph::const_iterator, PixelGraph::const_iterator>
65 Edge;
66 typedef std::pair<Edge, int> EdgeWeight;
67
68 void operator()(const PixelGraph &graph, unsigned radius);
69
70 static bool similar_colors(PixelGraph::const_iterator n,
71 const guint8 (&a)[4], const guint8 (&b)[4]);
72
73 /*
74 * Precondition: Must be filled according to Diagonal enum.
75 */
76 EdgeWeight diagonals[2];
77};
78
79} // namespace Heuristics
80
81Splines Kopf2011::to_voronoi(const std::string &filename,
82 const Options &options)
83{
84 return to_voronoi(Gdk::Pixbuf::create_from_file(filename), options);
85}
86
87Splines Kopf2011::to_voronoi(const Glib::RefPtr<Gdk::Pixbuf const> &buf,
88 const Options &options)
89{
90#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
92 = _voronoi<Precision, false>(buf, options);
93
94 Glib::DateTime profiling_info[2];
95 profiling_info[0] = Glib::DateTime::create_now_utc();
96
97 Splines ret(voronoi);
98
99 profiling_info[1] = Glib::DateTime::create_now_utc();
100 std::cerr << "Tracer::Splines construction time: "
101 << profiling_info[1].difference(profiling_info[0])
102 << std::endl;
103
104 return ret;
105#else // LIBDEPIXELIZE_PROFILE_KOPF2011
106 return Splines(_voronoi<Precision, false>(buf, options));
107#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
108}
109
110Splines Kopf2011::to_grouped_voronoi(const std::string &filename,
111 const Options &options)
112{
113 return to_grouped_voronoi(Gdk::Pixbuf::create_from_file(filename), options);
114}
115
116Splines Kopf2011::to_grouped_voronoi(const Glib::RefPtr<Gdk::Pixbuf const> &buf,
117 const Options &options)
118{
119#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
121 = _voronoi<Precision, false>(buf, options);
122
123 Glib::DateTime profiling_info[2];
124 profiling_info[0] = Glib::DateTime::create_now_utc();
125
126 HomogeneousSplines<Precision> splines(voronoi);
127
128#else // LIBDEPIXELIZE_PROFILE_KOPF2011
129 HomogeneousSplines<Precision> splines(_voronoi<Precision, false>
130 (buf, options));
131#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
132
133#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
134 profiling_info[1] = Glib::DateTime::create_now_utc();
135 std::cerr << "Tracer::HomogeneousSplines<" << typeid(Precision).name()
136 << ">(Tracer::SimplifiedVoronoi<" << typeid(Precision).name()
137 << ",false>) construction time: "
138 << profiling_info[1].difference(profiling_info[0])
139 << std::endl;
140 profiling_info[0] = Glib::DateTime::create_now_utc();
141#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
142
144 end = splines.end() ; it != end ; ++it ) {
146 it2 = it->vertices.begin(), end2 = it->vertices.end()
147 ; it2 != end2 ; ++it2 ) {
148 it2->smooth = false;
149 }
151 it2 = it->holes.begin(), end2 = it->holes.end()
152 ; it2 != end2 ; ++it2 ) {
154 it3 = it2->begin(), end3 = it2->end()
155 ; it3 != end3 ; ++it3 ) {
156 it3->smooth = false;
157 }
158 }
159 }
160
161#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
162 profiling_info[1] = Glib::DateTime::create_now_utc();
163 std::cerr << "Tracer::Kopf2011::to_grouped_voronoi internal work time: "
164 << profiling_info[1].difference(profiling_info[0])
165 << std::endl;
166 profiling_info[0] = Glib::DateTime::create_now_utc();
167
168 Splines ret(splines, false, options.nthreads);
169
170 profiling_info[1] = Glib::DateTime::create_now_utc();
171 std::cerr << "Tracer::Splines construction time: "
172 << profiling_info[1].difference(profiling_info[0])
173 << std::endl;
174
175 return ret;
176#else // LIBDEPIXELIZE_PROFILE_KOPF2011
177 return Splines(splines, false, options.nthreads);
178#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
179}
180
181Splines Kopf2011::to_splines(const std::string &filename,
182 const Options &options)
183{
184 return to_splines(Gdk::Pixbuf::create_from_file(filename), options);
185}
186
187Splines Kopf2011::to_splines(const Glib::RefPtr<Gdk::Pixbuf const> &buf,
188 const Options &options)
189{
190#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
192 = _voronoi<Precision, true>(buf, options);
193
194 Glib::DateTime profiling_info[2];
195 profiling_info[0] = Glib::DateTime::create_now_utc();
196
197 HomogeneousSplines<Precision> splines(voronoi);
198
199 profiling_info[1] = Glib::DateTime::create_now_utc();
200 std::cerr << "Tracer::HomogeneousSplines<" << typeid(Precision).name()
201 << "> construction time: "
202 << profiling_info[1].difference(profiling_info[0])
203 << std::endl;
204
205 profiling_info[0] = Glib::DateTime::create_now_utc();
206
207 Splines ret(splines, options.optimize, options.nthreads);
208
209 profiling_info[1] = Glib::DateTime::create_now_utc();
210 std::cerr << "Tracer::Splines construction time: "
211 << profiling_info[1].difference(profiling_info[0])
212 << std::endl;
213
214 return ret;
215#else // LIBDEPIXELIZE_PROFILE_KOPF2011
216 HomogeneousSplines<Precision> splines(_voronoi<Precision, true>
217 (buf, options));
218 return Splines(splines, options.optimize, options.nthreads);
219#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
220}
221
222template<class T, bool adjust_splines>
224Kopf2011::_voronoi(const Glib::RefPtr<Gdk::Pixbuf const> &buf,
225 const Options &options)
226{
227#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
228 Glib::DateTime profiling_info[2];
229 profiling_info[0] = Glib::DateTime::create_now_utc();
230#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
231
232 PixelGraph graph(buf);
233
234#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
235 profiling_info[1] = Glib::DateTime::create_now_utc();
236 std::cerr << "Tracer::PixelGraph creation time: "
237 << profiling_info[1].difference(profiling_info[0]) << std::endl;
238#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
239
240 // gdk-pixbuf2 already checks if image size is meaningful, but asserts state
241 // preconditions and will be useful if gdk-pixbuf is replaced later
242 assert(graph.width() > 0);
243 assert(graph.height() > 0);
244
245#ifndef NDEBUG
246 graph.checkConsistency();
247#endif
248
249#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
250 profiling_info[0] = Glib::DateTime::create_now_utc();
251#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
252
253 // This step could be part of the initialization of PixelGraph
254 // and decrease the necessary number of passes
255 graph.connectAllNeighbors();
256
257#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
258 profiling_info[1] = Glib::DateTime::create_now_utc();
259 std::cerr << "Tracer::PixelGraph::connectAllNeighbors() time: "
260 << profiling_info[1].difference(profiling_info[0]) << std::endl;
261#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
262
263#ifndef NDEBUG
264 graph.checkConsistency();
265#endif
266
267#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
268 profiling_info[0] = Glib::DateTime::create_now_utc();
269#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
270
271 // This step can't be part of PixelGraph initilization without adding some
272 // cache misses due to random access patterns that might be injected
274
275#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
276 profiling_info[1] = Glib::DateTime::create_now_utc();
277 std::cerr << "Tracer::Kopf2011::"
278 "_disconnect_neighbors_with_dissimilar_colors(Tracer::PixelGraph) time: "
279 << profiling_info[1].difference(profiling_info[0]) << std::endl;
280#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
281
282#ifndef NDEBUG
283 graph.checkConsistency();
284#endif
285
286#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
287 profiling_info[0] = Glib::DateTime::create_now_utc();
288#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
289
290 {
291 // edges_safe and edges_unsafe must be executed in separate.
292 // Otherwise, there will be colateral effects due to misassumption about
293 // the data being read.
295
296#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
297 profiling_info[1] = Glib::DateTime::create_now_utc();
298 std::cerr << "Tracer::PixelGraph::crossingEdges() time: "
299 << profiling_info[1].difference(profiling_info[0]) << std::endl;
300 profiling_info[0] = Glib::DateTime::create_now_utc();
301#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
302
304
305#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
306 profiling_info[1] = Glib::DateTime::create_now_utc();
307 std::cerr << "Tracer::Kopf2011::_remove_crossing_edges_safe"
308 "(Tracer::PixelGraph) time: "
309 << profiling_info[1].difference(profiling_info[0])
310 << std::endl;
311#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
312
313#ifndef NDEBUG
314 graph.checkConsistency();
315#endif
316
317#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
318 profiling_info[0] = Glib::DateTime::create_now_utc();
319#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
320
321 _remove_crossing_edges_unsafe(graph, edges, options);
322 }
323
324#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
325 profiling_info[1] = Glib::DateTime::create_now_utc();
326 std::cerr << "Tracer::Kopf2011::_remove_crossing_edges_unsafe"
327 "(Tracer::PixelGraph) time: "
328 << profiling_info[1].difference(profiling_info[0]) << std::endl;
329#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
330
331#ifndef NDEBUG
332 graph.checkConsistency();
333#endif
334
335 assert(graph.crossingEdges().size() == 0);
336
337#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
338 profiling_info[0] = Glib::DateTime::create_now_utc();
339
341
342 profiling_info[1] = Glib::DateTime::create_now_utc();
343 std::cerr << "Tracer::SimplifiedVoronoi<" << typeid(T).name() << ','
344 << (adjust_splines ? "true" : "false")
345 << ">(Tracer::PixelGraph) construction time: "
346 << profiling_info[1].difference(profiling_info[0]) << std::endl;
347
348 return ret;
349#else // LIBDEPIXELIZE_PROFILE_KOPF2011
351#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
352}
353
354// TODO: move this function (plus connectAllNeighbors) to PixelGraph constructor
355inline void
357{
359 for ( PixelGraph::iterator it = graph.begin(), end = graph.end() ; it != end
360 ; ++it ) {
361 if ( it->adj.top )
362 it->adj.top = similar_colors(it->rgba, (it - graph.width())->rgba);
363 if ( it->adj.topright ) {
364 it->adj.topright
365 = similar_colors(it->rgba, (it - graph.width() + 1)->rgba);
366 }
367 if ( it->adj.right )
368 it->adj.right = similar_colors(it->rgba, (it + 1)->rgba);
369 if ( it->adj.bottomright ) {
370 it->adj.bottomright
371 = similar_colors(it->rgba, (it + graph.width() + 1)->rgba);
372 }
373 if ( it->adj.bottom ) {
374 it->adj.bottom
375 = similar_colors(it->rgba, (it + graph.width())->rgba);
376 }
377 if ( it->adj.bottomleft ) {
378 it->adj.bottomleft
379 = similar_colors(it->rgba, (it + graph.width() - 1)->rgba);
380 }
381 if ( it->adj.left )
382 it->adj.left = similar_colors(it->rgba, (it - 1)->rgba);
383 if ( it->adj.topleft ) {
384 it->adj.topleft = similar_colors(it->rgba,
385 (it - graph.width() - 1)->rgba);
386 }
387 }
388}
389
396template<class T>
398{
399 for ( typename T::reverse_iterator it = container.rbegin(),
400 end = container.rend() ; it != end ; ) {
401 /* A | B
402 --+--
403 C | D */
404 PixelGraph::iterator a = it->first.first;
405 PixelGraph::iterator b = it->second.first;
406 PixelGraph::iterator c = it->second.second;
407 PixelGraph::iterator d = it->first.second;
408
409 if ( !a->adj.right || !a->adj.bottom || !b->adj.bottom
410 || !c->adj.right ) {
411 ++it;
412 continue;
413 }
414
415 // main diagonal
416 a->adj.bottomright = 0;
417 d->adj.topleft = 0;
418
419 // secondary diagonal
420 b->adj.bottomleft = 0;
421 c->adj.topright = 0;
422
423 // base iterator is always past one
424 typename T::iterator current = --(it.base());
425 ++it;
426 container.erase(current);
427 }
428}
429
433template<class T>
435 const Options &options)
436{
437 std::vector< std::pair<int, int> > weights(edges.size(),
438 std::make_pair(0, 0));
439
440 // Compute weights
441 for ( typename T::size_type i = 0 ; i != edges.size() ; ++i ) {
442 /* A | B
443 --+--
444 C | D */
445 PixelGraph::iterator a = edges[i].first.first;
446 PixelGraph::iterator b = edges[i].second.first;
447 PixelGraph::iterator c = edges[i].second.second;
448 PixelGraph::iterator d = edges[i].first.second;
449
450 // Curves heuristic
451 weights[i].first += Heuristics::curves(graph, a, d)
452 * options.curvesMultiplier;
453 weights[i].second += Heuristics::curves(graph, b, c)
454 * options.curvesMultiplier;
455
456 // Islands heuristic
457 weights[i].first += Heuristics::islands(a, d) * options.islandsWeight;
458 weights[i].second += Heuristics::islands(b, c) * options.islandsWeight;
459
460 // Sparse pixels heuristic
461 using Heuristics::SparsePixels;
462 SparsePixels sparse_pixels;
463
464 sparse_pixels.diagonals[SparsePixels::MAIN_DIAGONAL].first
465 = edges[i].first;
466 sparse_pixels.diagonals[SparsePixels::SECONDARY_DIAGONAL].first
467 = edges[i].second;
468
469 sparse_pixels(graph, options.sparsePixelsRadius);
470
471 weights[i].first
472 += sparse_pixels.diagonals[SparsePixels::MAIN_DIAGONAL].second
473 * options.sparsePixelsMultiplier;
474 weights[i].second
475 += sparse_pixels.diagonals[SparsePixels::SECONDARY_DIAGONAL].second
476 * options.sparsePixelsMultiplier;
477 }
478
479 // Remove edges with lower weight
480 for ( typename T::size_type i = 0 ; i != edges.size() ; ++i ) {
481 /* A | B
482 --+--
483 C | D */
484 PixelGraph::iterator a = edges[i].first.first;
485 PixelGraph::iterator b = edges[i].second.first;
486 PixelGraph::iterator c = edges[i].second.second;
487 PixelGraph::iterator d = edges[i].first.second;
488
489 if ( weights[i].first > weights[i].second ) {
490 b->adj.bottomleft = 0;
491 c->adj.topright = 0;
492 } else if ( weights[i].first < weights[i].second ) {
493 a->adj.bottomright = 0;
494 d->adj.topleft = 0;
495 } else {
496 a->adj.bottomright = 0;
497 b->adj.bottomleft = 0;
498 c->adj.topright = 0;
499 d->adj.topleft = 0;
500 }
501 }
502
503 edges.clear();
504}
505
506inline int Heuristics::curves(const PixelGraph &graph,
509{
510 int count = 1;
512 ToIter<PixelGraph::Node> to_iter(graph.begin());
513
514 // b -> a
515 // and then a -> b
516 for ( int i = 0 ; i != 2 ; ++i ) {
517 PixelGraph::const_iterator it = i ? a : b;
518 PixelGraph::const_iterator prev = i ? b : a;
519 int local_count = 0;
520
521 // Used to avoid inifinite loops in circular-like edges
522 const PixelGraph::const_iterator initial = it;
523
524 while ( it->adjsize() == 2 ) {
525 ++local_count;
526
527 // Iterate to next
528 {
529 // There are only two values that won't be zero'ed
530 // and one of them has the same value of prev
531 guintptr aux = (it->adj.top
532 * guintptr(to_ptr(graph.nodeTop(it))))
533 + (it->adj.topright
534 * guintptr(to_ptr(graph.nodeTopRight(it))))
535 + (it->adj.right
536 * guintptr(to_ptr(graph.nodeRight(it))))
537 + (it->adj.bottomright
538 * guintptr(to_ptr(graph.nodeBottomRight(it))))
539 + (it->adj.bottom
540 * guintptr(to_ptr(graph.nodeBottom(it))))
541 + (it->adj.bottomleft
542 * guintptr(to_ptr(graph.nodeBottomLeft(it))))
543 + (it->adj.left
544 * guintptr(to_ptr(graph.nodeLeft(it))))
545 + (it->adj.topleft
546 * guintptr(to_ptr(graph.nodeTopLeft(it))))
547 - guintptr(to_ptr(prev));
548 prev = it;
549 it = to_iter(reinterpret_cast<PixelGraph::Node const*>(aux));
550 }
551
552 // Break infinite loops
553 if ( it == initial )
554 return local_count;
555 }
556 count += local_count;
557 }
558
559 return count;
560}
561
562inline void Heuristics::SparsePixels::operator ()(const PixelGraph &graph,
563 unsigned radius)
564{
565 if ( !graph.width() || !graph.height() )
566 return;
567
568 // Clear weights
569 for ( int i = 0 ; i != 2 ; ++i )
570 diagonals[i].second = 0;
571
572 if ( !radius )
573 return;
574
575 // Fix radius/bounds
576 {
577 unsigned x = graph.toX(diagonals[MAIN_DIAGONAL].first.first);
578 unsigned y = graph.toY(diagonals[MAIN_DIAGONAL].first.first);
579 unsigned displace = radius - 1;
580
581 {
582 unsigned minor = std::min(x, y);
583
584 if ( displace > minor ) {
585 displace = minor;
586 radius = displace + 1;
587 }
588 }
589
590 displace = radius;
591
592 if ( x + displace >= unsigned(graph.width()) ) {
593 displace = unsigned(graph.width()) - x - 1;
594 radius = displace;
595 }
596
597 if ( y + displace >= unsigned(graph.height()) ) {
598 displace = unsigned(graph.height()) - y - 1;
599 radius = displace;
600 }
601 }
602
603 if ( !radius )
604 return;
605
606 // Iterate over nodes and count them
607 {
608 PixelGraph::const_iterator it = diagonals[MAIN_DIAGONAL].first.first;
609 for ( unsigned i = radius - 1 ; i ; --i )
610 it = graph.nodeTopLeft(it);
611
612 bool invert = false;
613 for ( unsigned i = 0 ; i != 2 * radius ; ++i ) {
614 for ( unsigned j = 0 ; j != 2 * radius ; ++j ) {
615 for ( int k = 0 ; k != 2 ; ++k ) {
616 diagonals[k].second
617 += similar_colors(it, diagonals[k].first.first->rgba,
618 diagonals[k].first.second->rgba);
619 }
620 it = (invert ? graph.nodeLeft(it) : graph.nodeRight(it));
621 }
622 it = (invert ? graph.nodeRight(it) : graph.nodeLeft(it));
623
624
625 invert = !invert;
626 it = graph.nodeBottom(it);
627 }
628 }
629
630 int minor = std::min(diagonals[0].second, diagonals[1].second);
631 for ( int i = 0 ; i != 2 ; ++i )
632 diagonals[i].second -= minor;
633 std::swap(diagonals[0].second, diagonals[1].second);
634}
635
636inline bool
637Heuristics::SparsePixels::similar_colors(PixelGraph::const_iterator n,
638 const guint8 (&a)[4],
639 const guint8 (&b)[4])
640{
642 return similar_colors(n->rgba, a) || similar_colors(n->rgba, b);
643}
644
647{
648 if ( a->adjsize() == 1 || b->adjsize() == 1 )
649 return true;
650
651 return false;
652}
653
654} // namespace Tracer
655
656/*
657 Local Variables:
658 mode:c++
659 c-file-style:"stroustrup"
660 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
661 indent-tabs-mode:nil
662 fill-column:99
663 End:
664*/
665// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
std::vector< Polygon >::iterator iterator
static Splines to_splines(const std::string &filename, const Options &options=Options())
static Splines to_voronoi(const std::string &filename, const Options &options=Options())
static void _remove_crossing_edges_safe(T &container)
This method removes crossing edges if the 2x2 block is fully connected.
static void _disconnect_neighbors_with_dissimilar_colors(PixelGraph &graph)
static Splines to_grouped_voronoi(const std::string &filename, const Options &options=Options())
static SimplifiedVoronoi< T, adjust_splines > _voronoi(const Glib::RefPtr< Gdk::Pixbuf const > &buf, const Options &options)
Geom::Coord Precision
static void _remove_crossing_edges_unsafe(PixelGraph &graph, T &edges, const Options &options)
This method removes crossing edges using the heuristics.
iterator nodeLeft(iterator n)
Definition pixelgraph.h:192
void connectAllNeighbors()
Definition pixelgraph.h:369
int width() const
Definition pixelgraph.h:158
int toY(const_iterator n) const
Definition pixelgraph.h:177
std::vector< EdgePair > EdgePairContainer
Definition pixelgraph.h:82
EdgePairContainer crossingEdges()
Definition pixelgraph.h:509
std::vector< Node >::const_iterator const_iterator
Definition pixelgraph.h:76
iterator nodeTopLeft(iterator n)
Definition pixelgraph.h:202
iterator nodeBottomLeft(iterator n)
Definition pixelgraph.h:212
std::vector< Node >::iterator iterator
Definition pixelgraph.h:75
iterator nodeBottomRight(iterator n)
Definition pixelgraph.h:217
iterator nodeTopRight(iterator n)
Definition pixelgraph.h:207
iterator nodeRight(iterator n)
Definition pixelgraph.h:197
int height() const
Definition pixelgraph.h:163
iterator nodeTop(iterator n)
Definition pixelgraph.h:182
iterator nodeBottom(iterator n)
Definition pixelgraph.h:187
int toX(const_iterator n) const
Definition pixelgraph.h:172
double c[8][4]
static char const *const current
Definition dir-util.cpp:71
Geom::Point end
int n
Definition spiro.cpp:57
bool islands(PixelGraph::const_iterator a, PixelGraph::const_iterator b)
int curves(const PixelGraph &graph, PixelGraph::const_iterator a, PixelGraph::const_iterator b)
bool similar_colors(const guint8 a[], const guint8 b[])
Definition colorspace.h:72
const T * to_ptr(typename std::vector< T >::const_iterator it)
Definition iterator.h:34
int buf
Edges edges(Path const &p, Crossings const &cr, unsigned ix)
Definition sanitize.cpp:36
void invert(const double v[16], double alpha[16])
std::vector< Points >::iterator holes_iter
Glib::ustring name
Definition toolbars.cpp:55