1 /*
2 This file is a part of the RepSnapper project.
3 Copyright (C) 2010 Kulitorum
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20
21
22 /*************************************************************************
23
24 TODO LIST:
25
26 Logick: Add more Unittest :)
27
28
29 *************************************************************************/
30 #include "config.h"
31 #include "stdafx.h"
32 #include "modelviewcontroller.h"
33 #include "gcode.h"
34 #include "ui.h"
35
36 #if !defined(WIN32) || defined (UNITTEST)
37
38 GUI *gui;
39
40 #include <boost/thread.hpp>
41
42 using namespace std;
43
44 #include <Polygon2d.h>
45
46 #define BOOST_TEST_MODULE RepSnapperTest
47 #define BOOST_TEST_MAIN 1
48 #define BOOST_TEST_DYN_LINK 1
49 #include <boost/test/unit_test.hpp>
50
51 using namespace PolyLib;
52
53 //// seven ways to detect and report the same error:
54 //BOOST_CHECK( add( 2,2 ) == 4 ); // #1 continues on error
55
56 //BOOST_REQUIRE( add( 2,2 ) == 4 ); // #2 throws on error
57
58 //if( add( 2,2 ) != 4 )
59 // BOOST_ERROR( "Ouch..." ); // #3 continues on error
60
61 //if( add( 2,2 ) != 4 )
62 // BOOST_FAIL( "Ouch..." ); // #4 throws on error
63
64 //if( add( 2,2 ) != 4 ) throw "Ouch..."; // #5 throws on error
65
66 //BOOST_CHECK_MESSAGE( add( 2,2 ) == 4, // #6 continues on error
67 // "add(..) result: " << add( 2,2 ) );
68
69 //BOOST_CHECK_EQUAL( add( 2,2 ), 4 ); // #7 continues on error
70
BOOST_AUTO_TEST_CASE(Logick_Basic_Shrink_Test)71 BOOST_AUTO_TEST_CASE( Logick_Basic_Shrink_Test )
72 {
73 Polygon2d p;
74
75 p.vertices.push_back(Vector2d(10,10));
76 p.vertices.push_back(Vector2d(10,110));
77 p.vertices.push_back(Vector2d(110,110));
78 p.vertices.push_back(Vector2d(110,10));
79
80 list<Polygon2d*> parent;
81 list<Polygon2d*> res;
82
83 p.Shrink(1, parent, res);
84 BOOST_CHECK( p.vertices.size() == res.front()->vertices.size() );
85 BOOST_CHECK( res.front()->vertices.front() == Vector2d(11,11) );
86 BOOST_CHECK( res.front()->vertices.back() == Vector2d(109,11) );
87
88 delete res.front();
89 }
90
BOOST_AUTO_TEST_CASE(Logick_Advanced_Shrink_Test)91 BOOST_AUTO_TEST_CASE( Logick_Advanced_Shrink_Test )
92 {
93 Polygon2d p;
94
95 p.vertices.push_back(Vector2d(10,10));
96 p.vertices.push_back(Vector2d(10,110));
97 p.vertices.push_back(Vector2d(110,110));
98 p.vertices.push_back(Vector2d(120,110));
99 p.vertices.push_back(Vector2d(110,109));
100 p.vertices.push_back(Vector2d(110,10));
101
102 list<Polygon2d*> parent;
103 list<Polygon2d*> res;
104
105 p.Shrink(2, parent, res);
106 BOOST_CHECK( p.vertices.size()-2 == res.front()->vertices.size() );
107 BOOST_CHECK( res.front()->vertices.front() == Vector2d(12,12) );
108 BOOST_CHECK( res.front()->vertices.back() == Vector2d(108,12) );
109
110 delete res.front();
111 }
112
BOOST_AUTO_TEST_CASE(Logick_Advanced_Polygon_Split_Tests)113 BOOST_AUTO_TEST_CASE( Logick_Advanced_Polygon_Split_Tests )
114 {
115 Polygon2d p;
116
117 p.vertices.push_back(Vector2d(10,10));
118 p.vertices.push_back(Vector2d(59,60));
119 p.vertices.push_back(Vector2d(10,110));
120 p.vertices.push_back(Vector2d(110,110));
121 p.vertices.push_back(Vector2d(61,60));
122 p.vertices.push_back(Vector2d(110,10));
123
124 list<Polygon2d*> parent;
125 list<Polygon2d*> res;
126
127 p.Shrink(2, parent, res);
128 BOOST_CHECK( res.size() == 2 );
129
130 for(list<Polygon2d*>::iterator pIt = res.begin(); pIt != res.end(); pIt++)
131 delete *pIt;
132 }
133
BOOST_AUTO_TEST_CASE(Slicing_PointHash)134 BOOST_AUTO_TEST_CASE( Slicing_PointHash )
135 {
136 PointHash h;
137 float x = 10.0, y = 7.0;
138 float d = PointHash::float_epsilon / 2;
139
140 BOOST_CHECK (h.IndexOfPoint (Vector2d(x, y)) < 0);
141 h.InsertPoint (0, Vector2d (x, y));
142
143 // look around that point
144 BOOST_CHECK (h.IndexOfPoint (Vector2d(x, y)) == 0);
145 BOOST_CHECK (h.IndexOfPoint (Vector2d(x + d, y)) == 0);
146 BOOST_CHECK (h.IndexOfPoint (Vector2d(x - d, y)) == 0);
147 BOOST_CHECK (h.IndexOfPoint (Vector2d(x, y + d)) == 0);
148 BOOST_CHECK (h.IndexOfPoint (Vector2d(x, y - d)) == 0);
149 BOOST_CHECK (h.IndexOfPoint (Vector2d(x + d, y + d)) == 0);
150 BOOST_CHECK (h.IndexOfPoint (Vector2d(x - d, y - d)) == 0);
151 BOOST_CHECK (h.IndexOfPoint (Vector2d(x + d, y - d)) == 0);
152 BOOST_CHECK (h.IndexOfPoint (Vector2d(x - d, y + d)) == 0);
153
154 // look nearby but not there
155 float e = PointHash::float_epsilon * 3 / 2;
156 BOOST_CHECK (h.IndexOfPoint (Vector2d(x + e, y)) < 0);
157 BOOST_CHECK (h.IndexOfPoint (Vector2d(x - e, y)) < 0);
158 BOOST_CHECK (h.IndexOfPoint (Vector2d(x, y + e)) < 0);
159 BOOST_CHECK (h.IndexOfPoint (Vector2d(x, y - e)) < 0);
160 BOOST_CHECK (h.IndexOfPoint (Vector2d(x + e, y + e)) < 0);
161 BOOST_CHECK (h.IndexOfPoint (Vector2d(x - e, y - e)) < 0);
162 BOOST_CHECK (h.IndexOfPoint (Vector2d(x + e, y - e)) < 0);
163 BOOST_CHECK (h.IndexOfPoint (Vector2d(x - e, y + e)) < 0);
164 }
165
166
167
168 // Simple neat square
BOOST_AUTO_TEST_CASE(Slicing_Lines_Square_Simple)169 BOOST_AUTO_TEST_CASE( Slicing_Lines_Square_Simple )
170 {
171 CuttingPlane cp;
172
173 // degenerate case
174 BOOST_CHECK (cp.LinkSegments (0.1, 0.001) == true);
175
176 int tl = cp.RegisterPoint (Vector2d (10, 20));
177 int tr = cp.RegisterPoint (Vector2d (20, 20));
178 int bl = cp.RegisterPoint (Vector2d (10, 10));
179 int br = cp.RegisterPoint (Vector2d (20, 10));
180
181 cp.AddLine (CuttingPlane::Segment (tl, tr));
182 cp.AddLine (CuttingPlane::Segment (bl, tl));
183 cp.AddLine (CuttingPlane::Segment (tr, br));
184 cp.AddLine (CuttingPlane::Segment (br, bl));
185
186 BOOST_CHECK (cp.LinkSegments (0.1, 0.001) == true);
187 BOOST_CHECK (cp.GetPolygons().size() == 1);
188 BOOST_CHECK (cp.GetPolygons()[0].points.size() == 4);
189 }
190
191 // Dis-connected square
BOOST_AUTO_TEST_CASE(Slicing_Lines_Square_Nastier)192 BOOST_AUTO_TEST_CASE( Slicing_Lines_Square_Nastier )
193 {
194 CuttingPlane cp;
195 float d = PointHash::float_epsilon / 2;
196 int tl = cp.RegisterPoint (Vector2d (10, 20));
197 int tln = cp.RegisterPoint (Vector2d (10, 20 + 0.01));
198 int tr = cp.RegisterPoint (Vector2d (20, 20));
199 int trn = cp.RegisterPoint (Vector2d (20 + d, 20));
200 int bl = cp.RegisterPoint (Vector2d (10, 10));
201 int bln = cp.RegisterPoint (Vector2d (10 + 0.5, 10 + 0.5));
202 int br = cp.RegisterPoint (Vector2d (20, 10));
203 int brn = cp.RegisterPoint (Vector2d (20 + 0.5, 10 + d));
204
205 cp.AddLine (CuttingPlane::Segment (tl, trn));
206 cp.AddLine (CuttingPlane::Segment (bl, tln));
207 cp.AddLine (CuttingPlane::Segment (tr, brn));
208 cp.AddLine (CuttingPlane::Segment (br, bln));
209
210 BOOST_CHECK (cp.LinkSegments (0.1, 0.001) == true);
211 BOOST_CHECK (cp.GetPolygons().size() == 1);
212 // fprintf (stderr, "lines %d\n", cp.GetPolygons()[0].points.size());
213 // BOOST_CHECK (cp.GetPolygons()[0].points.size() == 4);
214 }
215
216 // Multi-point shape
217 // a---b
218 // | |
219 // c---d---e
220 // | |
221 // f---g
BOOST_AUTO_TEST_CASE(Slicing_Lines_Single_Co_Incident)222 BOOST_AUTO_TEST_CASE( Slicing_Lines_Single_Co_Incident )
223 {
224 CuttingPlane cp;
225 int a = cp.RegisterPoint (Vector2d (10, 30));
226 int b = cp.RegisterPoint (Vector2d (20, 30));
227 int c = cp.RegisterPoint (Vector2d (10, 20));
228 int d = cp.RegisterPoint (Vector2d (20, 20));
229 int e = cp.RegisterPoint (Vector2d (30, 20));
230 int f = cp.RegisterPoint (Vector2d (20, 10));
231 int g = cp.RegisterPoint (Vector2d (30, 10));
232
233 cp.AddLine (CuttingPlane::Segment (a, b));
234 cp.AddLine (CuttingPlane::Segment (b, d));
235 cp.AddLine (CuttingPlane::Segment (d, c));
236 cp.AddLine (CuttingPlane::Segment (c, a));
237 cp.AddLine (CuttingPlane::Segment (d, e));
238 cp.AddLine (CuttingPlane::Segment (e, g));
239 cp.AddLine (CuttingPlane::Segment (g, f));
240 cp.AddLine (CuttingPlane::Segment (f, d));
241
242 BOOST_CHECK (cp.LinkSegments (0.1, 0.001) == true);
243 BOOST_CHECK (cp.GetPolygons().size() == 2);
244 }
245
246 // Co-incident boundary
247 // a---b
248 // | |
249 // c---d
250 // | |
251 // e---f
BOOST_AUTO_TEST_CASE(Slicing_Lines_Boundary_Co_Incident)252 BOOST_AUTO_TEST_CASE( Slicing_Lines_Boundary_Co_Incident )
253 {
254 CuttingPlane cp;
255 int a = cp.RegisterPoint (Vector2d (10, 30));
256 int b = cp.RegisterPoint (Vector2d (20, 30));
257 int c = cp.RegisterPoint (Vector2d (10, 20));
258 int d = cp.RegisterPoint (Vector2d (20, 20));
259 int e = cp.RegisterPoint (Vector2d (10, 10));
260 int f = cp.RegisterPoint (Vector2d (20, 10));
261
262 cp.AddLine (CuttingPlane::Segment (a, b));
263 cp.AddLine (CuttingPlane::Segment (b, d));
264 cp.AddLine (CuttingPlane::Segment (d, c));
265 cp.AddLine (CuttingPlane::Segment (c, a));
266 cp.AddLine (CuttingPlane::Segment (d, f));
267 cp.AddLine (CuttingPlane::Segment (f, e));
268 cp.AddLine (CuttingPlane::Segment (e, c));
269 cp.AddLine (CuttingPlane::Segment (c, d));
270
271 BOOST_CHECK (cp.LinkSegments (0.1, 0.001) == true);
272 BOOST_CHECK (cp.GetPolygons().size() == 1);
273 BOOST_CHECK (cp.GetPolygons()[0].points.size() == 4);
274 }
275
276 #endif // !defined(WIN32) || defined (UNITTEST)
277