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