1 #ifndef __2GEOM_SHAPE_H
2 #define __2GEOM_SHAPE_H
4 #include <vector>
5 #include <set>
7 #include "region.h"
9 //TODO: BBOX optimizations
11 namespace Geom {
13 enum {
14 BOOLOP_JUST_A = 1,
15 BOOLOP_JUST_B = 2,
16 BOOLOP_BOTH = 4,
17 BOOLOP_NEITHER = 8
18 };
20 enum {
21 BOOLOP_NULL = 0,
22 BOOLOP_INTERSECT = BOOLOP_BOTH,
23 BOOLOP_SUBTRACT_A_B = BOOLOP_JUST_B,
24 BOOLOP_IDENTITY_A = BOOLOP_JUST_A | BOOLOP_BOTH,
25 BOOLOP_SUBTRACT_B_A = BOOLOP_JUST_A,
26 BOOLOP_IDENTITY_B = BOOLOP_JUST_B | BOOLOP_BOTH,
27 BOOLOP_EXCLUSION = BOOLOP_JUST_A | BOOLOP_JUST_B,
28 BOOLOP_UNION = BOOLOP_JUST_A | BOOLOP_JUST_B | BOOLOP_BOTH
29 };
31 class Shape {
32 Regions content;
33 mutable bool fill;
34 //friend Shape shape_region_boolean(bool rev, Shape const & a, Region const & b);
35 friend CrossingSet crossings_between(Shape const &a, Shape const &b);
36 friend Shape shape_boolean(bool rev, Shape const &, Shape const &, CrossingSet const &);
37 friend Shape boolop(Shape const &a, Shape const &b, unsigned);
38 friend Shape boolop(Shape const &a, Shape const &b, unsigned, CrossingSet const &);
39 friend void add_to_shape(Shape &s, Path const &p, bool);
40 public:
41 Shape() : fill(true) {}
42 explicit Shape(Region const & r) {
43 content = Regions(1, r);
44 fill = r.fill;
45 }
46 explicit Shape(Regions const & r) : content(r) { update_fill(); }
47 explicit Shape(bool f) : fill(f) {}
48 Shape(Regions const & r, bool f) : content(r), fill(f) {}
50 Regions getContent() const { return content; }
51 bool isFill() const { return fill; }
53 unsigned size() const { return content.size(); }
54 const Region &operator[](unsigned ix) const { return content[ix]; }
56 Shape inverse() const;
57 Shape operator*(Matrix const &m) const;
59 bool contains(Point const &p) const;
61 bool inside_invariants() const; //semi-slow & easy to violate : checks that the insides are inside, the outsides are outside
62 bool region_invariants() const; //semi-slow : checks for self crossing
63 bool cross_invariants() const; //slow : checks that everything is disjoint
64 bool invariants() const; //vera slow (combo, checks the above)
66 private:
67 std::vector<unsigned> containment_list(Point p) const;
68 void update_fill() const {
69 unsigned ix = outer_index(content);
70 if(ix < size())
71 fill = content[ix].fill;
72 else if(size() > 0)
73 fill = content.front().fill;
74 else
75 fill = true;
76 }
77 };
79 inline CrossingSet crossings_between(Shape const &a, Shape const &b) { return crossings(paths_from_regions(a.content), paths_from_regions(b.content)); }
81 Shape shape_boolean(bool rev, Shape const &, Shape const &, CrossingSet const &);
82 Shape shape_boolean(bool rev, Shape const &, Shape const &);
84 //unsigned pick_coincident(unsigned ix, unsigned jx, bool &rev, std::vector<Path> const &ps, CrossingSet const &crs);
85 //void outer_crossing(unsigned &ix, unsigned &jx, bool & dir, std::vector<Path> const & ps, CrossingSet const & crs);
86 void crossing_dual(unsigned &i, unsigned &j, CrossingSet const & crs);
87 unsigned crossing_along(double t, unsigned ix, unsigned jx, bool dir, Crossings const & crs);
89 Shape boolop(Shape const &, Shape const &, unsigned flags);
90 Shape boolop(Shape const &, Shape const &, unsigned flags, CrossingSet &);
92 Shape sanitize(std::vector<Path> const &ps);
94 Shape stopgap_cleaner(std::vector<Path> const &ps);
96 inline std::vector<Path> desanitize(Shape const & s) {
97 return paths_from_regions(s.getContent());
98 }
100 }
102 #endif