rays 0.1.46 → 0.1.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.doc/ext/rays/bitmap.cpp +258 -0
 - data/.doc/ext/rays/defs.cpp +3 -3
 - data/.doc/ext/rays/painter.cpp +38 -3
 - data/.doc/ext/rays/polygon.cpp +81 -4
 - data/.doc/ext/rays/rays.cpp +11 -11
 - data/.github/workflows/test.yml +0 -1
 - data/ChangeLog.md +15 -0
 - data/Rakefile +4 -4
 - data/VERSION +1 -1
 - data/ext/rays/bitmap.cpp +259 -0
 - data/ext/rays/defs.cpp +3 -3
 - data/ext/rays/painter.cpp +45 -8
 - data/ext/rays/polygon.cpp +89 -4
 - data/ext/rays/rays.cpp +11 -11
 - data/include/rays/defs.h +26 -0
 - data/include/rays/matrix.h +2 -0
 - data/include/rays/painter.h +15 -1
 - data/include/rays/polygon.h +6 -1
 - data/include/rays/polyline.h +4 -0
 - data/lib/rays/painter.rb +1 -1
 - data/lib/rays/polygon.rb +36 -7
 - data/rays.gemspec +2 -2
 - data/src/color_space.cpp +2 -2
 - data/src/matrix.cpp +8 -0
 - data/src/painter.cpp +72 -5
 - data/src/polygon.cpp +385 -91
 - data/src/polyline.cpp +33 -18
 - data/src/polyline.h +2 -2
 - data/test/test_bitmap.rb +7 -0
 - data/test/test_polygon.rb +2 -2
 - data/test/test_polygon_line.rb +5 -5
 - data/test/test_polyline.rb +7 -7
 - metadata +6 -6
 
    
        data/src/polygon.cpp
    CHANGED
    
    | 
         @@ -4,7 +4,7 @@ 
     | 
|
| 
       4 
4 
     | 
    
         
             
            #include <math.h>
         
     | 
| 
       5 
5 
     | 
    
         
             
            #include <assert.h>
         
     | 
| 
       6 
6 
     | 
    
         
             
            #include <utility>
         
     | 
| 
       7 
     | 
    
         
            -
            #include < 
     | 
| 
      
 7 
     | 
    
         
            +
            #include <earcut.hpp>
         
     | 
| 
       8 
8 
     | 
    
         
             
            #include <Splines.h>
         
     | 
| 
       9 
9 
     | 
    
         
             
            #include <xot/util.h>
         
     | 
| 
       10 
10 
     | 
    
         
             
            #include "rays/color.h"
         
     | 
| 
         @@ -17,21 +17,170 @@ 
     | 
|
| 
       17 
17 
     | 
    
         
             
            namespace clip = ClipperLib;
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         | 
| 
      
 20 
     | 
    
         
            +
            namespace mapbox
         
     | 
| 
      
 21 
     | 
    
         
            +
            {
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            	namespace util
         
     | 
| 
      
 24 
     | 
    
         
            +
            	{
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            		template<>
         
     | 
| 
      
 27 
     | 
    
         
            +
            		struct nth<0, Rays::Point>
         
     | 
| 
      
 28 
     | 
    
         
            +
            		{
         
     | 
| 
      
 29 
     | 
    
         
            +
            			inline static auto get (const Rays::Point& p)
         
     | 
| 
      
 30 
     | 
    
         
            +
            			{
         
     | 
| 
      
 31 
     | 
    
         
            +
            				return p.x;
         
     | 
| 
      
 32 
     | 
    
         
            +
            			}
         
     | 
| 
      
 33 
     | 
    
         
            +
            		};
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            		template<>
         
     | 
| 
      
 36 
     | 
    
         
            +
            		struct nth<1, Rays::Point>
         
     | 
| 
      
 37 
     | 
    
         
            +
            		{
         
     | 
| 
      
 38 
     | 
    
         
            +
            			inline static auto get (const Rays::Point& p)
         
     | 
| 
      
 39 
     | 
    
         
            +
            			{
         
     | 
| 
      
 40 
     | 
    
         
            +
            				return p.y;
         
     | 
| 
      
 41 
     | 
    
         
            +
            			}
         
     | 
| 
      
 42 
     | 
    
         
            +
            		};
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            	}// util
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            }// mapbox
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
       20 
49 
     | 
    
         
             
            namespace Rays
         
     | 
| 
       21 
50 
     | 
    
         
             
            {
         
     | 
| 
       22 
51 
     | 
    
         | 
| 
       23 
52 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
            	 
     | 
| 
       25 
     | 
    
         
            -
            	to_poly2tri (const Point& point)
         
     | 
| 
      
 53 
     | 
    
         
            +
            	class Triangulator
         
     | 
| 
       26 
54 
     | 
    
         
             
            	{
         
     | 
| 
       27 
     | 
    
         
            -
            		return p2t::Point(point.x, point.y);
         
     | 
| 
       28 
     | 
    
         
            -
            	}
         
     | 
| 
       29 
55 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
      
 56 
     | 
    
         
            +
            		public:
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            			Triangulator (size_t npoints)
         
     | 
| 
      
 59 
     | 
    
         
            +
            			{
         
     | 
| 
      
 60 
     | 
    
         
            +
            				points.reserve(npoints);
         
     | 
| 
      
 61 
     | 
    
         
            +
            			}
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            			size_t begin (bool hole = false)
         
     | 
| 
      
 64 
     | 
    
         
            +
            			{
         
     | 
| 
      
 65 
     | 
    
         
            +
            				segments.emplace_back(points.size(), 0, hole);
         
     | 
| 
      
 66 
     | 
    
         
            +
            				return segments.back().begin;
         
     | 
| 
      
 67 
     | 
    
         
            +
            			}
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            			void end (size_t n)
         
     | 
| 
      
 70 
     | 
    
         
            +
            			{
         
     | 
| 
      
 71 
     | 
    
         
            +
            				if (segments.empty())
         
     | 
| 
      
 72 
     | 
    
         
            +
            					invalid_state_error(__FILE__, __LINE__);
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            				auto& seg = segments.back();
         
     | 
| 
      
 75 
     | 
    
         
            +
            				if (n != seg.begin)
         
     | 
| 
      
 76 
     | 
    
         
            +
            					argument_error(__FILE__, __LINE__);
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            				seg.end = points.size();
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
            				if (seg.empty()) segments.pop_back();
         
     | 
| 
      
 81 
     | 
    
         
            +
            			}
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
            			void append (const Point& point)
         
     | 
| 
      
 84 
     | 
    
         
            +
            			{
         
     | 
| 
      
 85 
     | 
    
         
            +
            				points.emplace_back(point);
         
     | 
| 
      
 86 
     | 
    
         
            +
            			}
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
            			void triangulate ()
         
     | 
| 
      
 89 
     | 
    
         
            +
            			{
         
     | 
| 
      
 90 
     | 
    
         
            +
            				if (segments.empty()) return;
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
            				PolylineList polylines;
         
     | 
| 
      
 93 
     | 
    
         
            +
            				size_t index_offset = 0;
         
     | 
| 
      
 94 
     | 
    
         
            +
            				for (const auto& seg : segments)
         
     | 
| 
      
 95 
     | 
    
         
            +
            				{
         
     | 
| 
      
 96 
     | 
    
         
            +
            					Polyline polyline(&points[0] + seg.begin, seg.end - seg.begin);
         
     | 
| 
      
 97 
     | 
    
         
            +
            					if (!seg.hole)
         
     | 
| 
      
 98 
     | 
    
         
            +
            					{
         
     | 
| 
      
 99 
     | 
    
         
            +
            						triangulate(polylines, index_offset);
         
     | 
| 
      
 100 
     | 
    
         
            +
            						polylines.clear();
         
     | 
| 
      
 101 
     | 
    
         
            +
            						index_offset = seg.begin;
         
     | 
| 
      
 102 
     | 
    
         
            +
            					}
         
     | 
| 
      
 103 
     | 
    
         
            +
            					polylines.emplace_back(polyline);
         
     | 
| 
      
 104 
     | 
    
         
            +
            				}
         
     | 
| 
      
 105 
     | 
    
         
            +
            				triangulate(polylines, index_offset);
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
            				segments.clear();
         
     | 
| 
      
 108 
     | 
    
         
            +
            				segments.shrink_to_fit();
         
     | 
| 
      
 109 
     | 
    
         
            +
            			}
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
            			bool get_triangles (Polygon::TrianglePointList* triangles) const
         
     | 
| 
      
 112 
     | 
    
         
            +
            			{
         
     | 
| 
      
 113 
     | 
    
         
            +
            				if (indices.empty()) return false;
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
            				triangles->reserve(triangles->size() + indices.size());
         
     | 
| 
      
 116 
     | 
    
         
            +
            				for (const auto& index : indices)
         
     | 
| 
      
 117 
     | 
    
         
            +
            					triangles->emplace_back(points[index]);
         
     | 
| 
      
 118 
     | 
    
         
            +
            				return true;
         
     | 
| 
      
 119 
     | 
    
         
            +
            			}
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
            		private:
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
            			struct Segment
         
     | 
| 
      
 124 
     | 
    
         
            +
            			{
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
            				size_t begin, end;
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
            				bool hole;
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
            				Segment (size_t begin, size_t end, bool hole = false)
         
     | 
| 
      
 131 
     | 
    
         
            +
            				:	begin(begin), end(end), hole(hole)
         
     | 
| 
      
 132 
     | 
    
         
            +
            				{
         
     | 
| 
      
 133 
     | 
    
         
            +
            				}
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
            				bool empty () const
         
     | 
| 
      
 136 
     | 
    
         
            +
            				{
         
     | 
| 
      
 137 
     | 
    
         
            +
            					return begin == end;
         
     | 
| 
      
 138 
     | 
    
         
            +
            				}
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
            			};// Segment
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
            			class Polyline
         
     | 
| 
      
 143 
     | 
    
         
            +
            			{
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
            				const Point* points;
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
            				size_t size_;
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
            				public:
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
            					typedef Point value_type;
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
            					Polyline (const Point* points, size_t size)
         
     | 
| 
      
 154 
     | 
    
         
            +
            					:	points(points), size_(size)
         
     | 
| 
      
 155 
     | 
    
         
            +
            					{
         
     | 
| 
      
 156 
     | 
    
         
            +
            					}
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
            					size_t size () const {return size_;}
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
            					bool empty () const {return size_ == 0;}
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
            					const Point& operator [] (size_t i) const {return points[i];}
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
            			};// Polyline
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
            			typedef std::vector<Polyline> PolylineList;
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
            			std::vector<Segment> segments;
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
      
 170 
     | 
    
         
            +
            			std::vector<Point> points;
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
            			std::vector<uint32_t> indices;
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
            			void triangulate (const PolylineList& polylines, size_t index_offset)
         
     | 
| 
      
 175 
     | 
    
         
            +
            			{
         
     | 
| 
      
 176 
     | 
    
         
            +
            				if (polylines.empty()) return;
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
            				auto result = mapbox::earcut<uint32_t>(polylines);
         
     | 
| 
      
 179 
     | 
    
         
            +
            				for (const auto& index : result)
         
     | 
| 
      
 180 
     | 
    
         
            +
            					indices.emplace_back(index_offset + index);
         
     | 
| 
      
 181 
     | 
    
         
            +
            			}
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
            	};// Triangulator
         
     | 
| 
       35 
184 
     | 
    
         | 
| 
       36 
185 
     | 
    
         | 
| 
       37 
186 
     | 
    
         
             
            	struct Polygon::Data
         
     | 
| 
         @@ -39,16 +188,40 @@ namespace Rays 
     | 
|
| 
       39 
188 
     | 
    
         | 
| 
       40 
189 
     | 
    
         
             
            		LineList lines;
         
     | 
| 
       41 
190 
     | 
    
         | 
| 
      
 191 
     | 
    
         
            +
            		mutable std::unique_ptr<Bounds> pbounds;
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
            		mutable std::unique_ptr<Triangulator> ptriangulator;
         
     | 
| 
      
 194 
     | 
    
         
            +
             
     | 
| 
       42 
195 
     | 
    
         
             
            		virtual ~Data ()
         
     | 
| 
       43 
196 
     | 
    
         
             
            		{
         
     | 
| 
       44 
197 
     | 
    
         
             
            		}
         
     | 
| 
       45 
198 
     | 
    
         | 
| 
      
 199 
     | 
    
         
            +
            		const Bounds& bounds () const
         
     | 
| 
      
 200 
     | 
    
         
            +
            		{
         
     | 
| 
      
 201 
     | 
    
         
            +
            			if (!pbounds)
         
     | 
| 
      
 202 
     | 
    
         
            +
            			{
         
     | 
| 
      
 203 
     | 
    
         
            +
            				if (lines.empty())
         
     | 
| 
      
 204 
     | 
    
         
            +
            					pbounds.reset(new Bounds(-1, -1, -1));
         
     | 
| 
      
 205 
     | 
    
         
            +
            				else
         
     | 
| 
      
 206 
     | 
    
         
            +
            				{
         
     | 
| 
      
 207 
     | 
    
         
            +
            					pbounds.reset(new Bounds(lines[0][0], 0));
         
     | 
| 
      
 208 
     | 
    
         
            +
            					for (const auto& line : lines)
         
     | 
| 
      
 209 
     | 
    
         
            +
            					{
         
     | 
| 
      
 210 
     | 
    
         
            +
            						for (const auto& point : line)
         
     | 
| 
      
 211 
     | 
    
         
            +
            							*pbounds |= point;
         
     | 
| 
      
 212 
     | 
    
         
            +
            					}
         
     | 
| 
      
 213 
     | 
    
         
            +
            				}
         
     | 
| 
      
 214 
     | 
    
         
            +
            			}
         
     | 
| 
      
 215 
     | 
    
         
            +
            			return *pbounds;
         
     | 
| 
      
 216 
     | 
    
         
            +
            		}
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
       46 
218 
     | 
    
         
             
            		void append (const Polyline& polyline, bool hole = false)
         
     | 
| 
       47 
219 
     | 
    
         
             
            		{
         
     | 
| 
       48 
220 
     | 
    
         
             
            			if (polyline.empty())
         
     | 
| 
       49 
221 
     | 
    
         
             
            				return;
         
     | 
| 
       50 
222 
     | 
    
         | 
| 
       51 
     | 
    
         
            -
            			lines.emplace_back( 
     | 
| 
      
 223 
     | 
    
         
            +
            			lines.emplace_back(polyline, hole);
         
     | 
| 
      
 224 
     | 
    
         
            +
            			pbounds.reset();
         
     | 
| 
       52 
225 
     | 
    
         
             
            		}
         
     | 
| 
       53 
226 
     | 
    
         | 
| 
       54 
227 
     | 
    
         
             
            		void append (const Line& line)
         
     | 
| 
         @@ -57,48 +230,30 @@ namespace Rays 
     | 
|
| 
       57 
230 
     | 
    
         
             
            				return;
         
     | 
| 
       58 
231 
     | 
    
         | 
| 
       59 
232 
     | 
    
         
             
            			lines.emplace_back(line);
         
     | 
| 
      
 233 
     | 
    
         
            +
            			pbounds.reset();
         
     | 
| 
       60 
234 
     | 
    
         
             
            		}
         
     | 
| 
       61 
235 
     | 
    
         | 
| 
       62 
236 
     | 
    
         
             
            		bool triangulate (TrianglePointList* triangles) const
         
     | 
| 
       63 
237 
     | 
    
         
             
            		{
         
     | 
| 
       64 
238 
     | 
    
         
             
            			assert(triangles);
         
     | 
| 
       65 
239 
     | 
    
         | 
| 
       66 
     | 
    
         
            -
            			 
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
            			if (!can_triangulate())
         
     | 
| 
       69 
     | 
    
         
            -
            				return false;
         
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
            			size_t npoint = count_points();
         
     | 
| 
       72 
     | 
    
         
            -
            			if (npoint <= 0)
         
     | 
| 
       73 
     | 
    
         
            -
            				return true;
         
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
            			std::unique_ptr<p2t::CDT> cdt;
         
     | 
| 
       76 
     | 
    
         
            -
            			std::vector<p2t::Point> points;
         
     | 
| 
       77 
     | 
    
         
            -
            			std::vector<p2t::Point*> pointers;
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
            			points.reserve(npoint);
         
     | 
| 
       80 
     | 
    
         
            -
            			for (const auto& line : lines)
         
     | 
| 
      
 240 
     | 
    
         
            +
            			if (!ptriangulator)
         
     | 
| 
       81 
241 
     | 
    
         
             
            			{
         
     | 
| 
       82 
     | 
    
         
            -
            				 
     | 
| 
       83 
     | 
    
         
            -
            				 
     | 
| 
       84 
     | 
    
         
            -
            				for (const auto& point : line)
         
     | 
| 
       85 
     | 
    
         
            -
            				{
         
     | 
| 
       86 
     | 
    
         
            -
            					points.emplace_back(to_poly2tri(point));
         
     | 
| 
       87 
     | 
    
         
            -
            					pointers.emplace_back(&points.back());
         
     | 
| 
       88 
     | 
    
         
            -
            				}
         
     | 
| 
      
 242 
     | 
    
         
            +
            				ptriangulator.reset(new Triangulator(count_points_for_triangulation()));
         
     | 
| 
      
 243 
     | 
    
         
            +
            				auto& t = *ptriangulator;
         
     | 
| 
       89 
244 
     | 
    
         | 
| 
       90 
     | 
    
         
            -
            				 
     | 
| 
      
 245 
     | 
    
         
            +
            				for (const auto& line : lines)
         
     | 
| 
       91 
246 
     | 
    
         
             
            				{
         
     | 
| 
       92 
     | 
    
         
            -
            					 
     | 
| 
       93 
     | 
    
         
            -
            					 
     | 
| 
      
 247 
     | 
    
         
            +
            					size_t n = t.begin(line.hole());
         
     | 
| 
      
 248 
     | 
    
         
            +
            					for (const auto& point : line)
         
     | 
| 
      
 249 
     | 
    
         
            +
            						t.append(point);
         
     | 
| 
      
 250 
     | 
    
         
            +
            					t.end(n);
         
     | 
| 
       94 
251 
     | 
    
         
             
            				}
         
     | 
| 
       95 
     | 
    
         
            -
            				 
     | 
| 
       96 
     | 
    
         
            -
            					cdt->AddHole(pointers);
         
     | 
| 
      
 252 
     | 
    
         
            +
            				t.triangulate();
         
     | 
| 
       97 
253 
     | 
    
         
             
            			}
         
     | 
| 
       98 
254 
     | 
    
         | 
| 
       99 
     | 
    
         
            -
            			 
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
            			return true;
         
     | 
| 
      
 255 
     | 
    
         
            +
            			triangles->clear();
         
     | 
| 
      
 256 
     | 
    
         
            +
            			return ptriangulator->get_triangles(triangles);
         
     | 
| 
       102 
257 
     | 
    
         
             
            		}
         
     | 
| 
       103 
258 
     | 
    
         | 
| 
       104 
259 
     | 
    
         
             
            		virtual void fill (Painter* painter, const Color& color) const = 0;
         
     | 
| 
         @@ -110,47 +265,35 @@ namespace Rays 
     | 
|
| 
       110 
265 
     | 
    
         | 
| 
       111 
266 
     | 
    
         
             
            			coord stroke_width = painter->stroke_width();
         
     | 
| 
       112 
267 
     | 
    
         
             
            			if (stroke_width > 0)
         
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
      
 268 
     | 
    
         
            +
            			{
         
     | 
| 
      
 269 
     | 
    
         
            +
            				stroke_with_width(
         
     | 
| 
      
 270 
     | 
    
         
            +
            					polygon, painter, color, stroke_width, painter->stroke_outset());
         
     | 
| 
      
 271 
     | 
    
         
            +
            			}
         
     | 
| 
       114 
272 
     | 
    
         
             
            			else
         
     | 
| 
       115 
273 
     | 
    
         
             
            				stroke_without_width(painter, color);
         
     | 
| 
       116 
274 
     | 
    
         
             
            		}
         
     | 
| 
       117 
275 
     | 
    
         | 
| 
       118 
276 
     | 
    
         
             
            		private:
         
     | 
| 
       119 
277 
     | 
    
         | 
| 
       120 
     | 
    
         
            -
            			 
     | 
| 
      
 278 
     | 
    
         
            +
            			size_t count_points_for_triangulation () const
         
     | 
| 
       121 
279 
     | 
    
         
             
            			{
         
     | 
| 
      
 280 
     | 
    
         
            +
            				size_t count = 0;
         
     | 
| 
       122 
281 
     | 
    
         
             
            				for (const auto& line : lines)
         
     | 
| 
       123 
282 
     | 
    
         
             
            				{
         
     | 
| 
       124 
     | 
    
         
            -
            					if ( 
     | 
| 
       125 
     | 
    
         
            -
            						 
     | 
| 
      
 283 
     | 
    
         
            +
            					if (can_triangulate(line))
         
     | 
| 
      
 284 
     | 
    
         
            +
            						count += line.size();
         
     | 
| 
       126 
285 
     | 
    
         
             
            				}
         
     | 
| 
       127 
     | 
    
         
            -
            				return false;
         
     | 
| 
       128 
     | 
    
         
            -
            			}
         
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
            			size_t count_points () const
         
     | 
| 
       131 
     | 
    
         
            -
            			{
         
     | 
| 
       132 
     | 
    
         
            -
            				size_t count = 0;
         
     | 
| 
       133 
     | 
    
         
            -
            				for (const auto& line : lines)
         
     | 
| 
       134 
     | 
    
         
            -
            					count += line.size();
         
     | 
| 
       135 
286 
     | 
    
         
             
            				return count;
         
     | 
| 
       136 
287 
     | 
    
         
             
            			}
         
     | 
| 
       137 
288 
     | 
    
         | 
| 
       138 
     | 
    
         
            -
            			 
     | 
| 
      
 289 
     | 
    
         
            +
            			bool can_triangulate (const Line& line) const
         
     | 
| 
       139 
290 
     | 
    
         
             
            			{
         
     | 
| 
       140 
     | 
    
         
            -
            				 
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
       142 
     | 
    
         
            -
            				cdt->Triangulate();
         
     | 
| 
       143 
     | 
    
         
            -
             
     | 
| 
       144 
     | 
    
         
            -
            				for (auto* triangle : cdt->GetTriangles())
         
     | 
| 
       145 
     | 
    
         
            -
            				{
         
     | 
| 
       146 
     | 
    
         
            -
            					for (int i = 0; i < 3; ++i)
         
     | 
| 
       147 
     | 
    
         
            -
            						triangles->emplace_back(from_poly2tri(*triangle->GetPoint(i)));
         
     | 
| 
       148 
     | 
    
         
            -
            				}
         
     | 
| 
      
 291 
     | 
    
         
            +
            				return (line.fill() || line.hole()) && line.size() >= 3;
         
     | 
| 
       149 
292 
     | 
    
         
             
            			}
         
     | 
| 
       150 
293 
     | 
    
         | 
| 
       151 
294 
     | 
    
         
             
            			void stroke_with_width (
         
     | 
| 
       152 
295 
     | 
    
         
             
            				const Polygon& polygon, Painter* painter,
         
     | 
| 
       153 
     | 
    
         
            -
            				const Color& color, coord stroke_width) const
         
     | 
| 
      
 296 
     | 
    
         
            +
            				const Color& color, coord stroke_width, float stroke_outset) const
         
     | 
| 
       154 
297 
     | 
    
         
             
            			{
         
     | 
| 
       155 
298 
     | 
    
         
             
            				assert(painter && color && stroke_width > 0);
         
     | 
| 
       156 
299 
     | 
    
         | 
| 
         @@ -163,30 +306,45 @@ namespace Rays 
     | 
|
| 
       163 
306 
     | 
    
         
             
            				bool has_loop = false;
         
     | 
| 
       164 
307 
     | 
    
         
             
            				for (const auto& polyline : polygon)
         
     | 
| 
       165 
308 
     | 
    
         
             
            				{
         
     | 
| 
       166 
     | 
    
         
            -
            					if (!polyline || polyline.empty())
         
     | 
| 
       167 
     | 
    
         
            -
            						continue;
         
     | 
| 
       168 
     | 
    
         
            -
             
     | 
| 
       169 
309 
     | 
    
         
             
            					if (polyline.loop())
         
     | 
| 
       170 
310 
     | 
    
         
             
            					{
         
     | 
| 
       171 
311 
     | 
    
         
             
            						has_loop = true;
         
     | 
| 
       172 
312 
     | 
    
         
             
            						continue;
         
     | 
| 
       173 
313 
     | 
    
         
             
            					}
         
     | 
| 
      
 314 
     | 
    
         
            +
            					stroke_polyline(polyline, painter, color, stroke_width, cap, join, ml);
         
     | 
| 
      
 315 
     | 
    
         
            +
            				}
         
     | 
| 
       174 
316 
     | 
    
         | 
| 
       175 
     | 
    
         
            -
             
     | 
| 
       176 
     | 
    
         
            -
            					if (!polyline.expand(&stroke, stroke_width / 2, cap, join, ml))
         
     | 
| 
       177 
     | 
    
         
            -
            						continue;
         
     | 
| 
      
 317 
     | 
    
         
            +
            				if (!has_loop) return;
         
     | 
| 
       178 
318 
     | 
    
         | 
| 
       179 
     | 
    
         
            -
             
     | 
| 
       180 
     | 
    
         
            -
            				 
     | 
| 
      
 319 
     | 
    
         
            +
            				coord inset = (-0.5 + stroke_outset) * stroke_width;
         
     | 
| 
      
 320 
     | 
    
         
            +
            				Polygon outline;
         
     | 
| 
      
 321 
     | 
    
         
            +
            				if (inset == 0)
         
     | 
| 
      
 322 
     | 
    
         
            +
            					outline = polygon;
         
     | 
| 
      
 323 
     | 
    
         
            +
            				else if (!polygon.expand(&outline, inset, cap, join, ml))
         
     | 
| 
      
 324 
     | 
    
         
            +
            					return;
         
     | 
| 
       181 
325 
     | 
    
         | 
| 
       182 
     | 
    
         
            -
            				 
     | 
| 
      
 326 
     | 
    
         
            +
            				for (const auto& polyline : outline)
         
     | 
| 
       183 
327 
     | 
    
         
             
            				{
         
     | 
| 
       184 
     | 
    
         
            -
            					 
     | 
| 
       185 
     | 
    
         
            -
             
     | 
| 
       186 
     | 
    
         
            -
            						Polygon_fill(polygon - hole, painter, color);
         
     | 
| 
      
 328 
     | 
    
         
            +
            					if (polyline.loop())
         
     | 
| 
      
 329 
     | 
    
         
            +
            						stroke_polyline(polyline, painter, color, stroke_width, cap, join, ml);
         
     | 
| 
       187 
330 
     | 
    
         
             
            				}
         
     | 
| 
       188 
331 
     | 
    
         
             
            			}
         
     | 
| 
       189 
332 
     | 
    
         | 
| 
      
 333 
     | 
    
         
            +
            			void stroke_polyline (
         
     | 
| 
      
 334 
     | 
    
         
            +
            				const Polyline& polyline, Painter* painter,
         
     | 
| 
      
 335 
     | 
    
         
            +
            				const Color& color, coord stroke_width,
         
     | 
| 
      
 336 
     | 
    
         
            +
            				CapType cap, JoinType join, coord miter_limit) const
         
     | 
| 
      
 337 
     | 
    
         
            +
            			{
         
     | 
| 
      
 338 
     | 
    
         
            +
            				assert(stroke_width > 0);
         
     | 
| 
      
 339 
     | 
    
         
            +
             
     | 
| 
      
 340 
     | 
    
         
            +
            				if (!polyline || polyline.empty())
         
     | 
| 
      
 341 
     | 
    
         
            +
            					return;
         
     | 
| 
      
 342 
     | 
    
         
            +
             
     | 
| 
      
 343 
     | 
    
         
            +
            				Polygon stroke;
         
     | 
| 
      
 344 
     | 
    
         
            +
            				if (polyline.expand(&stroke, stroke_width / 2, cap, join, miter_limit))
         
     | 
| 
      
 345 
     | 
    
         
            +
            					Polygon_fill(stroke, painter, color);
         
     | 
| 
      
 346 
     | 
    
         
            +
            			}
         
     | 
| 
      
 347 
     | 
    
         
            +
             
     | 
| 
       190 
348 
     | 
    
         
             
            			void stroke_without_width (Painter* painter, const Color& color) const
         
     | 
| 
       191 
349 
     | 
    
         
             
            			{
         
     | 
| 
       192 
350 
     | 
    
         
             
            				assert(painter && color);
         
     | 
| 
         @@ -746,7 +904,7 @@ namespace Rays 
     | 
|
| 
       746 
904 
     | 
    
         | 
| 
       747 
905 
     | 
    
         
             
            				if (!has_hole)
         
     | 
| 
       748 
906 
     | 
    
         
             
            				{
         
     | 
| 
       749 
     | 
    
         
            -
            					points.emplace_back( 
     | 
| 
      
 907 
     | 
    
         
            +
            					points.emplace_back(x + width / 2, y + height / 2);
         
     | 
| 
       750 
908 
     | 
    
         
             
            					mode = GL_TRIANGLE_FAN;
         
     | 
| 
       751 
909 
     | 
    
         
             
            				}
         
     | 
| 
       752 
910 
     | 
    
         | 
| 
         @@ -788,6 +946,130 @@ namespace Rays 
     | 
|
| 
       788 
946 
     | 
    
         
             
            	};// EllipseData
         
     | 
| 
       789 
947 
     | 
    
         | 
| 
       790 
948 
     | 
    
         | 
| 
      
 949 
     | 
    
         
            +
            	static const char*
         
     | 
| 
      
 950 
     | 
    
         
            +
            	get_draw_mode_name (DrawMode mode)
         
     | 
| 
      
 951 
     | 
    
         
            +
            	{
         
     | 
| 
      
 952 
     | 
    
         
            +
            		switch (mode)
         
     | 
| 
      
 953 
     | 
    
         
            +
            		{
         
     | 
| 
      
 954 
     | 
    
         
            +
            			case DRAW_POINTS:         return "DRAW_POINTS";
         
     | 
| 
      
 955 
     | 
    
         
            +
            			case DRAW_LINES:          return "DRAW_LINES";
         
     | 
| 
      
 956 
     | 
    
         
            +
            			case DRAW_LINE_STRIP:     return "DRAW_LINE_STRIP";
         
     | 
| 
      
 957 
     | 
    
         
            +
            			case DRAW_TRIANGLES:      return "DRAW_TRIANGLES";
         
     | 
| 
      
 958 
     | 
    
         
            +
            			case DRAW_TRIANGLE_STRIP: return "DRAW_TRIANGLE_STRIP";
         
     | 
| 
      
 959 
     | 
    
         
            +
            			case DRAW_TRIANGLE_FAN:   return "DRAW_TRIANGLE_FAN";
         
     | 
| 
      
 960 
     | 
    
         
            +
            			case DRAW_QUADS:          return "DRAW_QUADS";
         
     | 
| 
      
 961 
     | 
    
         
            +
            			case DRAW_QUAD_STRIP:     return "DRAW_QUAD_STRIP";
         
     | 
| 
      
 962 
     | 
    
         
            +
            			case DRAW_POLYGON:        return "DRAW_POLYGON";
         
     | 
| 
      
 963 
     | 
    
         
            +
            			default: argument_error(__FILE__, __LINE__, "unknown draw mode");
         
     | 
| 
      
 964 
     | 
    
         
            +
            		}
         
     | 
| 
      
 965 
     | 
    
         
            +
            	}
         
     | 
| 
      
 966 
     | 
    
         
            +
             
     | 
| 
      
 967 
     | 
    
         
            +
            	static void
         
     | 
| 
      
 968 
     | 
    
         
            +
            	create_polygon (Polygon* polygon, const Point* points, size_t size, bool loop)
         
     | 
| 
      
 969 
     | 
    
         
            +
            	{
         
     | 
| 
      
 970 
     | 
    
         
            +
            		polygon->self->append(Polyline(points, size, loop, true));
         
     | 
| 
      
 971 
     | 
    
         
            +
            	}
         
     | 
| 
      
 972 
     | 
    
         
            +
             
     | 
| 
      
 973 
     | 
    
         
            +
            	static void
         
     | 
| 
      
 974 
     | 
    
         
            +
            	create_points (Polygon* polygon, const Point* points, size_t size)
         
     | 
| 
      
 975 
     | 
    
         
            +
            	{
         
     | 
| 
      
 976 
     | 
    
         
            +
            		for (size_t i = 0; i < size; ++i)
         
     | 
| 
      
 977 
     | 
    
         
            +
            			polygon->self->append(Polyline(&points[i], 1, false, false));
         
     | 
| 
      
 978 
     | 
    
         
            +
            	}
         
     | 
| 
      
 979 
     | 
    
         
            +
             
     | 
| 
      
 980 
     | 
    
         
            +
            	static void
         
     | 
| 
      
 981 
     | 
    
         
            +
            	create_lines (Polygon* polygon, const Point* points, size_t size)
         
     | 
| 
      
 982 
     | 
    
         
            +
            	{
         
     | 
| 
      
 983 
     | 
    
         
            +
            		for (size_t i = 0; i + 1 < size; i += 2)
         
     | 
| 
      
 984 
     | 
    
         
            +
            			polygon->self->append(Polyline(&points[i], 2, false, false));
         
     | 
| 
      
 985 
     | 
    
         
            +
            	}
         
     | 
| 
      
 986 
     | 
    
         
            +
             
     | 
| 
      
 987 
     | 
    
         
            +
            	static void
         
     | 
| 
      
 988 
     | 
    
         
            +
            	create_line_strip (
         
     | 
| 
      
 989 
     | 
    
         
            +
            		Polygon* polygon, const Point* points, size_t size, bool loop)
         
     | 
| 
      
 990 
     | 
    
         
            +
            	{
         
     | 
| 
      
 991 
     | 
    
         
            +
            		if (!loop || size < 3)
         
     | 
| 
      
 992 
     | 
    
         
            +
            			polygon->self->append(Polyline(points, size, loop, false));
         
     | 
| 
      
 993 
     | 
    
         
            +
            		else
         
     | 
| 
      
 994 
     | 
    
         
            +
            		{
         
     | 
| 
      
 995 
     | 
    
         
            +
            			std::vector<Point> array;
         
     | 
| 
      
 996 
     | 
    
         
            +
            			array.reserve(size + 1);
         
     | 
| 
      
 997 
     | 
    
         
            +
            			array.insert(array.begin(), points, points + size);
         
     | 
| 
      
 998 
     | 
    
         
            +
            			array.emplace_back(points[0]);
         
     | 
| 
      
 999 
     | 
    
         
            +
            			polygon->self->append(Polyline(&array[0], array.size(), true, false));
         
     | 
| 
      
 1000 
     | 
    
         
            +
            		}
         
     | 
| 
      
 1001 
     | 
    
         
            +
            	}
         
     | 
| 
      
 1002 
     | 
    
         
            +
             
     | 
| 
      
 1003 
     | 
    
         
            +
            	static void
         
     | 
| 
      
 1004 
     | 
    
         
            +
            	create_triangles (
         
     | 
| 
      
 1005 
     | 
    
         
            +
            		Polygon* polygon, const Point* points, size_t size, bool loop)
         
     | 
| 
      
 1006 
     | 
    
         
            +
            	{
         
     | 
| 
      
 1007 
     | 
    
         
            +
            		for (size_t i = 0; i + 2 < size; i += 3)
         
     | 
| 
      
 1008 
     | 
    
         
            +
            			polygon->self->append(Polyline(&points[i], 3, loop, true));
         
     | 
| 
      
 1009 
     | 
    
         
            +
            	}
         
     | 
| 
      
 1010 
     | 
    
         
            +
             
     | 
| 
      
 1011 
     | 
    
         
            +
            	static void
         
     | 
| 
      
 1012 
     | 
    
         
            +
            	create_triangle_strip (Polygon* polygon, const Point* points, size_t size)
         
     | 
| 
      
 1013 
     | 
    
         
            +
            	{
         
     | 
| 
      
 1014 
     | 
    
         
            +
            		if (size < 3) return;
         
     | 
| 
      
 1015 
     | 
    
         
            +
             
     | 
| 
      
 1016 
     | 
    
         
            +
            		size_t     last = size - 1;
         
     | 
| 
      
 1017 
     | 
    
         
            +
            		size_t  in_last = last % 2 == 0 ? last - 1 : last;
         
     | 
| 
      
 1018 
     | 
    
         
            +
            		size_t out_last = last % 2 == 0 ? last     : last - 1;
         
     | 
| 
      
 1019 
     | 
    
         
            +
             
     | 
| 
      
 1020 
     | 
    
         
            +
            		std::vector<Point> array;
         
     | 
| 
      
 1021 
     | 
    
         
            +
            		array.emplace_back(points[0]);
         
     | 
| 
      
 1022 
     | 
    
         
            +
            		for (size_t i = 1; i <= in_last; i += 2)
         
     | 
| 
      
 1023 
     | 
    
         
            +
            			array.emplace_back(points[i]);
         
     | 
| 
      
 1024 
     | 
    
         
            +
            		for (size_t i = out_last; i >= 2; i -= 2)
         
     | 
| 
      
 1025 
     | 
    
         
            +
            			array.emplace_back(points[i]);
         
     | 
| 
      
 1026 
     | 
    
         
            +
             
     | 
| 
      
 1027 
     | 
    
         
            +
            		polygon->self->append(Polyline(&array[0], array.size(), true));
         
     | 
| 
      
 1028 
     | 
    
         
            +
            		if (size >= 4)
         
     | 
| 
      
 1029 
     | 
    
         
            +
            			polygon->self->append(Polyline(&points[1], size - 2));
         
     | 
| 
      
 1030 
     | 
    
         
            +
            	}
         
     | 
| 
      
 1031 
     | 
    
         
            +
             
     | 
| 
      
 1032 
     | 
    
         
            +
            	static void
         
     | 
| 
      
 1033 
     | 
    
         
            +
            	create_triangle_fan (Polygon* polygon, const Point* points, size_t size)
         
     | 
| 
      
 1034 
     | 
    
         
            +
            	{
         
     | 
| 
      
 1035 
     | 
    
         
            +
            		create_polygon(polygon, points, size, true);
         
     | 
| 
      
 1036 
     | 
    
         
            +
             
     | 
| 
      
 1037 
     | 
    
         
            +
            		Point array[2];
         
     | 
| 
      
 1038 
     | 
    
         
            +
            		array[0] = points[0];
         
     | 
| 
      
 1039 
     | 
    
         
            +
            		for (size_t i = 2; i < size - 1; ++i)
         
     | 
| 
      
 1040 
     | 
    
         
            +
            		{
         
     | 
| 
      
 1041 
     | 
    
         
            +
            			array[1] = points[i];
         
     | 
| 
      
 1042 
     | 
    
         
            +
            			polygon->self->append(Polyline(&array[0], 2));
         
     | 
| 
      
 1043 
     | 
    
         
            +
            		}
         
     | 
| 
      
 1044 
     | 
    
         
            +
            	}
         
     | 
| 
      
 1045 
     | 
    
         
            +
             
     | 
| 
      
 1046 
     | 
    
         
            +
            	static void
         
     | 
| 
      
 1047 
     | 
    
         
            +
            	create_quads (Polygon* polygon, const Point* points, size_t size, bool loop)
         
     | 
| 
      
 1048 
     | 
    
         
            +
            	{
         
     | 
| 
      
 1049 
     | 
    
         
            +
            		for (size_t i = 0; i + 3 < size; i += 4)
         
     | 
| 
      
 1050 
     | 
    
         
            +
            			polygon->self->append(Polyline(&points[i], 4, loop, true));
         
     | 
| 
      
 1051 
     | 
    
         
            +
            	}
         
     | 
| 
      
 1052 
     | 
    
         
            +
             
     | 
| 
      
 1053 
     | 
    
         
            +
            	static void
         
     | 
| 
      
 1054 
     | 
    
         
            +
            	create_quad_strip (Polygon* polygon, const Point* points, size_t size)
         
     | 
| 
      
 1055 
     | 
    
         
            +
            	{
         
     | 
| 
      
 1056 
     | 
    
         
            +
            		if (size < 4) return;
         
     | 
| 
      
 1057 
     | 
    
         
            +
             
     | 
| 
      
 1058 
     | 
    
         
            +
            		if (size % 2 != 0) --size;
         
     | 
| 
      
 1059 
     | 
    
         
            +
            		size_t  in_last = size - 2;
         
     | 
| 
      
 1060 
     | 
    
         
            +
            		size_t out_last = size - 1;
         
     | 
| 
      
 1061 
     | 
    
         
            +
             
     | 
| 
      
 1062 
     | 
    
         
            +
            		std::vector<Point> array;
         
     | 
| 
      
 1063 
     | 
    
         
            +
            		for (size_t i = 0; i <= in_last; i += 2)
         
     | 
| 
      
 1064 
     | 
    
         
            +
            			array.emplace_back(points[i]);
         
     | 
| 
      
 1065 
     | 
    
         
            +
            		for (int i = (int) out_last; i >= 1; i -= 2)
         
     | 
| 
      
 1066 
     | 
    
         
            +
            			array.emplace_back(points[i]);
         
     | 
| 
      
 1067 
     | 
    
         
            +
             
     | 
| 
      
 1068 
     | 
    
         
            +
            		polygon->self->append(Polyline(&array[0], array.size(), true));
         
     | 
| 
      
 1069 
     | 
    
         
            +
            		for (size_t i = 2; i < in_last; i += 2)
         
     | 
| 
      
 1070 
     | 
    
         
            +
            			polygon->self->append(Polyline(&points[i], 2));
         
     | 
| 
      
 1071 
     | 
    
         
            +
            	}
         
     | 
| 
      
 1072 
     | 
    
         
            +
             
     | 
| 
       791 
1073 
     | 
    
         
             
            	Polygon
         
     | 
| 
       792 
1074 
     | 
    
         
             
            	create_line (coord x1, coord y1, coord x2, coord y2)
         
     | 
| 
       793 
1075 
     | 
    
         
             
            	{
         
     | 
| 
         @@ -1069,7 +1351,30 @@ namespace Rays 
     | 
|
| 
       1069 
1351 
     | 
    
         
             
            	{
         
     | 
| 
       1070 
1352 
     | 
    
         
             
            		if (!points || size <= 0) return;
         
     | 
| 
       1071 
1353 
     | 
    
         | 
| 
       1072 
     | 
    
         
            -
            		 
     | 
| 
      
 1354 
     | 
    
         
            +
            		create_polygon(this, points, size, loop);
         
     | 
| 
      
 1355 
     | 
    
         
            +
            	}
         
     | 
| 
      
 1356 
     | 
    
         
            +
             
     | 
| 
      
 1357 
     | 
    
         
            +
            	Polygon::Polygon (DrawMode mode, const Point* points, size_t size, bool loop)
         
     | 
| 
      
 1358 
     | 
    
         
            +
            	:	self(new PolygonData())
         
     | 
| 
      
 1359 
     | 
    
         
            +
            	{
         
     | 
| 
      
 1360 
     | 
    
         
            +
            		if (!points || size <= 0) return;
         
     | 
| 
      
 1361 
     | 
    
         
            +
             
     | 
| 
      
 1362 
     | 
    
         
            +
            		switch (mode)
         
     | 
| 
      
 1363 
     | 
    
         
            +
            		{
         
     | 
| 
      
 1364 
     | 
    
         
            +
            			case DRAW_POINTS:         create_points(        this, points, size);       break;
         
     | 
| 
      
 1365 
     | 
    
         
            +
            			case DRAW_LINES:          create_lines(         this, points, size);       break;
         
     | 
| 
      
 1366 
     | 
    
         
            +
            			case DRAW_LINE_STRIP:     create_line_strip(    this, points, size, loop); break;
         
     | 
| 
      
 1367 
     | 
    
         
            +
            			case DRAW_TRIANGLES:      create_triangles(     this, points, size, loop); break;
         
     | 
| 
      
 1368 
     | 
    
         
            +
            			case DRAW_TRIANGLE_STRIP: create_triangle_strip(this, points, size);       break;
         
     | 
| 
      
 1369 
     | 
    
         
            +
            			case DRAW_TRIANGLE_FAN:   create_triangle_fan(  this, points, size);       break;
         
     | 
| 
      
 1370 
     | 
    
         
            +
            			case DRAW_QUADS:          create_quads(         this, points, size, loop); break;
         
     | 
| 
      
 1371 
     | 
    
         
            +
            			case DRAW_QUAD_STRIP:     create_quad_strip(    this, points, size);       break;
         
     | 
| 
      
 1372 
     | 
    
         
            +
            			case DRAW_POLYGON:        create_polygon(       this, points, size, loop); break;
         
     | 
| 
      
 1373 
     | 
    
         
            +
            			default:
         
     | 
| 
      
 1374 
     | 
    
         
            +
            				argument_error(
         
     | 
| 
      
 1375 
     | 
    
         
            +
            					__FILE__, __LINE__,
         
     | 
| 
      
 1376 
     | 
    
         
            +
            					Xot::stringf("unknown draw mode '%s'", get_draw_mode_name(mode)));
         
     | 
| 
      
 1377 
     | 
    
         
            +
            		}
         
     | 
| 
       1073 
1378 
     | 
    
         
             
            	}
         
     | 
| 
       1074 
1379 
     | 
    
         | 
| 
       1075 
1380 
     | 
    
         
             
            	Polygon::Polygon (const Polyline& polyline)
         
     | 
| 
         @@ -1107,15 +1412,7 @@ namespace Rays 
     | 
|
| 
       1107 
1412 
     | 
    
         
             
            	Bounds
         
     | 
| 
       1108 
1413 
     | 
    
         
             
            	Polygon::bounds () const
         
     | 
| 
       1109 
1414 
     | 
    
         
             
            	{
         
     | 
| 
       1110 
     | 
    
         
            -
            		 
     | 
| 
       1111 
     | 
    
         
            -
             
     | 
| 
       1112 
     | 
    
         
            -
            		Bounds b(self->lines[0][0], 0);
         
     | 
| 
       1113 
     | 
    
         
            -
            		for (const auto& line : *this)
         
     | 
| 
       1114 
     | 
    
         
            -
            		{
         
     | 
| 
       1115 
     | 
    
         
            -
            			for (const auto& point : line)
         
     | 
| 
       1116 
     | 
    
         
            -
            				b |= point;
         
     | 
| 
       1117 
     | 
    
         
            -
            		}
         
     | 
| 
       1118 
     | 
    
         
            -
            		return b;
         
     | 
| 
      
 1415 
     | 
    
         
            +
            		return self->bounds();
         
     | 
| 
       1119 
1416 
     | 
    
         
             
            	}
         
     | 
| 
       1120 
1417 
     | 
    
         | 
| 
       1121 
1418 
     | 
    
         
             
            	size_t
         
     | 
| 
         @@ -1248,10 +1545,7 @@ namespace Rays 
     | 
|
| 
       1248 
1545 
     | 
    
         | 
| 
       1249 
1546 
     | 
    
         
             
            	Polygon::Line::operator bool () const
         
     | 
| 
       1250 
1547 
     | 
    
         
             
            	{
         
     | 
| 
       1251 
     | 
    
         
            -
            		 
     | 
| 
       1252 
     | 
    
         
            -
            			return false;
         
     | 
| 
       1253 
     | 
    
         
            -
             
     | 
| 
       1254 
     | 
    
         
            -
            		return loop() || !hole();
         
     | 
| 
      
 1548 
     | 
    
         
            +
            		return Super::operator bool() && (loop() || !hole());
         
     | 
| 
       1255 
1549 
     | 
    
         
             
            	}
         
     | 
| 
       1256 
1550 
     | 
    
         | 
| 
       1257 
1551 
     | 
    
         
             
            	bool
         
     | 
    
        data/src/polyline.cpp
    CHANGED
    
    | 
         @@ -17,21 +17,24 @@ namespace Rays 
     | 
|
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
            		PointList points;
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
            		bool loop = false;
         
     | 
| 
      
 20 
     | 
    
         
            +
            		bool loop = false, fill = false;
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
            		template <typename I, typename FUN>
         
     | 
| 
       23 
     | 
    
         
            -
            		void reset (I begin, I end, bool loop_, FUN to_point_fun)
         
     | 
| 
      
 23 
     | 
    
         
            +
            		void reset (I begin, I end, bool loop_, bool fill_, FUN to_point_fun)
         
     | 
| 
       24 
24 
     | 
    
         
             
            		{
         
     | 
| 
       25 
     | 
    
         
            -
            			 
     | 
| 
       26 
     | 
    
         
            -
            			if (0 < size && size < 3 && loop_)
         
     | 
| 
      
 25 
     | 
    
         
            +
            			if (begin > end)
         
     | 
| 
       27 
26 
     | 
    
         
             
            				argument_error(__FILE__, __LINE__);
         
     | 
| 
       28 
27 
     | 
    
         | 
| 
       29 
28 
     | 
    
         
             
            			points.clear();
         
     | 
| 
      
 29 
     | 
    
         
            +
            			loop = loop_;
         
     | 
| 
      
 30 
     | 
    
         
            +
            			fill = fill_;
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            			size_t size = end - begin;
         
     | 
| 
      
 33 
     | 
    
         
            +
            			if (size <= 0) return;
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
       30 
35 
     | 
    
         
             
            			points.reserve(size);
         
     | 
| 
       31 
36 
     | 
    
         
             
            			for (auto it = begin; it != end; ++it)
         
     | 
| 
       32 
37 
     | 
    
         
             
            				points.emplace_back(to_point_fun(*it));
         
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
            			loop = loop_ && size > 0;
         
     | 
| 
       35 
38 
     | 
    
         
             
            		}
         
     | 
| 
       36 
39 
     | 
    
         | 
| 
       37 
40 
     | 
    
         
             
            	};// Polyline::Data
         
     | 
| 
         @@ -39,18 +42,16 @@ namespace Rays 
     | 
|
| 
       39 
42 
     | 
    
         | 
| 
       40 
43 
     | 
    
         
             
            	void
         
     | 
| 
       41 
44 
     | 
    
         
             
            	Polyline_create (
         
     | 
| 
       42 
     | 
    
         
            -
            		Polyline* polyline, const Path& path, bool loop, bool  
     | 
| 
      
 45 
     | 
    
         
            +
            		Polyline* polyline, const Path& path, bool loop, bool hole)
         
     | 
| 
       43 
46 
     | 
    
         
             
            	{
         
     | 
| 
       44 
     | 
    
         
            -
            		assert(polyline);
         
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
47 
     | 
    
         
             
            		Path cleaned;
         
     | 
| 
       47 
48 
     | 
    
         
             
            		ClipperLib::CleanPolygon(path, cleaned);
         
     | 
| 
       48 
49 
     | 
    
         | 
| 
       49 
     | 
    
         
            -
            		auto  
     | 
| 
       50 
     | 
    
         
            -
            		if ( 
     | 
| 
       51 
     | 
    
         
            -
            			polyline->self->reset(cleaned.rbegin(), cleaned.rend(), loop,  
     | 
| 
      
 50 
     | 
    
         
            +
            		auto fun = [](const IntPoint& point) {return from_clipper(point);};
         
     | 
| 
      
 51 
     | 
    
         
            +
            		if (hole)
         
     | 
| 
      
 52 
     | 
    
         
            +
            			polyline->self->reset(cleaned.rbegin(), cleaned.rend(), loop, loop, fun);
         
     | 
| 
       52 
53 
     | 
    
         
             
            		else
         
     | 
| 
       53 
     | 
    
         
            -
            			polyline->self->reset(cleaned. begin(), cleaned. end(), loop,  
     | 
| 
      
 54 
     | 
    
         
            +
            			polyline->self->reset(cleaned. begin(), cleaned. end(), loop, loop, fun);
         
     | 
| 
       54 
55 
     | 
    
         
             
            	}
         
     | 
| 
       55 
56 
     | 
    
         | 
| 
       56 
57 
     | 
    
         
             
            	template <typename I>
         
     | 
| 
         @@ -63,12 +64,12 @@ namespace Rays 
     | 
|
| 
       63 
64 
     | 
    
         
             
            	}
         
     | 
| 
       64 
65 
     | 
    
         | 
| 
       65 
66 
     | 
    
         
             
            	void
         
     | 
| 
       66 
     | 
    
         
            -
            	Polyline_get_path (Path* path, const Polyline& polyline, bool  
     | 
| 
      
 67 
     | 
    
         
            +
            	Polyline_get_path (Path* path, const Polyline& polyline, bool hole)
         
     | 
| 
       67 
68 
     | 
    
         
             
            	{
         
     | 
| 
       68 
69 
     | 
    
         
             
            		assert(path);
         
     | 
| 
       69 
70 
     | 
    
         | 
| 
       70 
71 
     | 
    
         
             
            		const auto& points = polyline.self->points;
         
     | 
| 
       71 
     | 
    
         
            -
            		if ( 
     | 
| 
      
 72 
     | 
    
         
            +
            		if (hole)
         
     | 
| 
       72 
73 
     | 
    
         
             
            			reset_path(path, points.rbegin(), points.rend());
         
     | 
| 
       73 
74 
     | 
    
         
             
            		else
         
     | 
| 
       74 
75 
     | 
    
         
             
            			reset_path(path, points. begin(), points. end());
         
     | 
| 
         @@ -81,7 +82,16 @@ namespace Rays 
     | 
|
| 
       81 
82 
     | 
    
         | 
| 
       82 
83 
     | 
    
         
             
            	Polyline::Polyline (const Point* points, size_t size, bool loop)
         
     | 
| 
       83 
84 
     | 
    
         
             
            	{
         
     | 
| 
       84 
     | 
    
         
            -
            		self->reset( 
     | 
| 
      
 85 
     | 
    
         
            +
            		self->reset(
         
     | 
| 
      
 86 
     | 
    
         
            +
            			points, points + size, loop, loop,
         
     | 
| 
      
 87 
     | 
    
         
            +
            			[](const Point& p) {return p;});
         
     | 
| 
      
 88 
     | 
    
         
            +
            	}
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
            	Polyline::Polyline (const Point* points, size_t size, bool loop, bool fill)
         
     | 
| 
      
 91 
     | 
    
         
            +
            	{
         
     | 
| 
      
 92 
     | 
    
         
            +
            		self->reset(
         
     | 
| 
      
 93 
     | 
    
         
            +
            			points, points + size, loop, fill,
         
     | 
| 
      
 94 
     | 
    
         
            +
            			[](const Point& p) {return p;});
         
     | 
| 
       85 
95 
     | 
    
         
             
            	}
         
     | 
| 
       86 
96 
     | 
    
         | 
| 
       87 
97 
     | 
    
         
             
            	Polyline::~Polyline ()
         
     | 
| 
         @@ -114,6 +124,12 @@ namespace Rays 
     | 
|
| 
       114 
124 
     | 
    
         
             
            		return self->loop;
         
     | 
| 
       115 
125 
     | 
    
         
             
            	}
         
     | 
| 
       116 
126 
     | 
    
         | 
| 
      
 127 
     | 
    
         
            +
            	bool
         
     | 
| 
      
 128 
     | 
    
         
            +
            	Polyline::fill () const
         
     | 
| 
      
 129 
     | 
    
         
            +
            	{
         
     | 
| 
      
 130 
     | 
    
         
            +
            		return self->fill;
         
     | 
| 
      
 131 
     | 
    
         
            +
            	}
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
       117 
133 
     | 
    
         
             
            	size_t
         
     | 
| 
       118 
134 
     | 
    
         
             
            	Polyline::size () const
         
     | 
| 
       119 
135 
     | 
    
         
             
            	{
         
     | 
| 
         @@ -146,8 +162,7 @@ namespace Rays 
     | 
|
| 
       146 
162 
     | 
    
         | 
| 
       147 
163 
     | 
    
         
             
            	Polyline::operator bool () const
         
     | 
| 
       148 
164 
     | 
    
         
             
            	{
         
     | 
| 
       149 
     | 
    
         
            -
            		 
     | 
| 
       150 
     | 
    
         
            -
            		return !((s == 1 || s == 2) && self->loop);
         
     | 
| 
      
 165 
     | 
    
         
            +
            		return true;
         
     | 
| 
       151 
166 
     | 
    
         
             
            	}
         
     | 
| 
       152 
167 
     | 
    
         | 
| 
       153 
168 
     | 
    
         
             
            	bool
         
     |