1 /*! \file kbool/src/line.cpp
2     \brief Mainly used for calculating crossings
3     \author Klaas Holwerda
4 
5     Copyright: 2001-2004 (C) Klaas Holwerda
6 
7     Licence: see kboollicense.txt
8 
9     RCS-ID: $Id: line.cpp,v 1.10 2005/06/17 22:48:46 kbluck Exp $
10 */
11 
12 #ifdef __GNUG__
13 #pragma implementation
14 #endif
15 
16 // Standard include files
17 #include <assert.h>
18 #include <math.h>
19 
20 #include "kbool/include/booleng.h"
21 
22 // Include files for forward declarations
23 #include "kbool/include/link.h"
24 #include "kbool/include/node.h"
25 
26 // header
27 #include "kbool/include/line.h"
28 
29 #include "kbool/include/graph.h"
30 #include "kbool/include/graphlst.h"
31 
32 //
33 // The default constructor
34 //
KBoolLine(Bool_Engine * GC)35 KBoolLine::KBoolLine(Bool_Engine* GC)
36 {
37     m_GC=GC;
38 	m_AA = 0.0;
39 	m_BB = 0.0;
40 	m_CC = 0.0;
41 	m_link = 0;
42 	linecrosslist = NULL;
43 	m_valid_parameters = false;
44 }
45 
~KBoolLine()46 KBoolLine::~KBoolLine()
47 {
48 	if (linecrosslist)
49 		delete linecrosslist;
50 }
51 
52 //
53 // constructor with a link
54 //
KBoolLine(KBoolLink * a_link,Bool_Engine * GC)55 KBoolLine::KBoolLine(KBoolLink *a_link,Bool_Engine* GC)
56 {
57 	m_GC=GC;
58 	// a_link must exist
59 	assert(a_link);
60 	// points may not be equal
61 	// must be an if statement because if an assert is used there will
62 	// be a macro expansion error
63 
64 	//if (a_link->GetBeginNode()->Equal(a_link->GetEndNode(), 1))
65 	//	assert(!a_link);
66 
67 	linecrosslist = NULL;
68 	m_link = a_link;
69 	m_valid_parameters = false;
70 }
71 
72 
73 
74 // ActionOnTable1
75 // This function decide which action must be taken, after PointInLine
76 // has given the results of two points in relation to a line. See table 1 in the report
77 //
78 // input Result_beginnode:
79 //			Result_endnode :
80 //       The results can be LEFT_SIDE, RIGHT_SIDE, ON_AREA, IN_AREA
81 //
82 // return -1: Illegal combination
83 //         0: No action, no crosspoints
84 //         1: Investigate results points in relation to the other line
85 //         2: endnode is a crosspoint, no further investigation
86 //         3: beginnode is a crosspoint, no further investigation
87 //			  4: beginnode and endnode are crosspoints, no further investigation
88 //         5: beginnode is a crosspoint, need further investigation
89 //         6: endnode is a crosspoint, need further investigation
ActionOnTable1(PointStatus Result_beginnode,PointStatus Result_endnode)90 int KBoolLine::ActionOnTable1(PointStatus Result_beginnode, PointStatus Result_endnode)
91 {
92 	// Action 1.5 beginnode and endnode are crosspoints, no further investigation needed
93 	if (
94 		 (Result_beginnode == IN_AREA)
95 		 &&
96 		 (Result_endnode == IN_AREA)
97 		)
98 		return 4;
99    // Action 1.1, there are no crosspoints, no action
100 	if (
101 		 (
102 		  (Result_beginnode == LEFT_SIDE)
103 		  &&
104 		  (Result_endnode == LEFT_SIDE)
105 		 )
106 		 ||
107 		 (
108 		  (Result_beginnode == RIGHT_SIDE)
109 		  &&
110 		  (Result_endnode == RIGHT_SIDE)
111 		 )
112 		)
113 		return 0;
114 	// Action 1.2, maybe there is a crosspoint, further investigation needed
115 	if (
116 		 (
117 		  (Result_beginnode == LEFT_SIDE)
118 		  &&
119 		  (
120 			(Result_endnode == RIGHT_SIDE)
121 			||
122 			(Result_endnode == ON_AREA)
123 		  )
124 		 )
125 		 ||
126 		 (
127 		  (Result_beginnode == RIGHT_SIDE)
128 		  &&
129 		  (
130 			(Result_endnode == LEFT_SIDE)
131 			||
132 			(Result_endnode == ON_AREA)
133 		  )
134 		 )
135 		 ||
136 		 (
137 		  (Result_beginnode == ON_AREA)
138 		  &&
139 		  (
140 			(Result_endnode == LEFT_SIDE)
141 			||
142 			(Result_endnode == RIGHT_SIDE)
143 			||
144 			(Result_endnode == ON_AREA)
145 		  )
146 		 )
147 		)
148 		return 1;
149 	// Action 1.3, there is a crosspoint, no further investigation
150 	if (
151 		 (
152 		  (Result_beginnode == LEFT_SIDE)
153 		  ||
154 		  (Result_beginnode == RIGHT_SIDE)
155 		 )
156 		 &&
157 		 (Result_endnode == IN_AREA)
158 		)
159 		return 2;
160 	// Action 1.4  there is a crosspoint, no further investigation
161 	if (
162 		 (Result_beginnode == IN_AREA)
163 		 &&
164 		 (
165 		  (Result_endnode == LEFT_SIDE)
166 		  ||
167 		  (Result_endnode == RIGHT_SIDE)
168 		 )
169 		)
170 		return 3;
171 	// Action 1.6  beginnode is a crosspoint, further investigation needed
172 	if (
173 		 (Result_beginnode == IN_AREA)
174 		 &&
175 		 (Result_endnode == ON_AREA)
176 		)
177 		return 5;
178 	// Action 1.7  endnode is a crosspoint, further investigation needed
179 	if (
180 		 (Result_beginnode == ON_AREA)
181 		 &&
182 		 (Result_endnode == IN_AREA)
183 		)
184 		return 6;
185 	// All other combinations are illegal
186 	return -1;
187 }
188 
189 
190 // ActionOnTable2
191 // This function decide which action must be taken, after PointInLine
192 // has given the results of two points in relation to a line. It can only give a
193 // correct decision if first the relation of the points from the line
194 // are investigated in relation to the line wich can be constucted from the points.
195 //
196 // input Result_beginnode:
197 //			Result_endnode :
198 //       The results can be LEFT_SIDE, RIGHT_SIDE, ON_AREA, IN_AREA
199 //
200 // return -1: Illegal combination
201 //         0: No action, no crosspoints
202 //         1: Calculate crosspoint
203 //         2: endnode is a crosspoint
204 //         3: beginnode is a crosspoint
205 //         4: beginnode and endnode are crosspoints
ActionOnTable2(PointStatus Result_beginnode,PointStatus Result_endnode)206 int KBoolLine::ActionOnTable2(PointStatus Result_beginnode, PointStatus Result_endnode)
207 {
208 	// Action 2.5, beginnode and eindpoint are crosspoints
209 	if (
210 		 (Result_beginnode == IN_AREA)
211 		 &&
212 		 (Result_endnode == IN_AREA)
213 		)
214 		return 4;
215 	// Action 2.1, there are no crosspoints
216 	if (
217 		 (
218 		  (Result_beginnode == LEFT_SIDE)
219 		  &&
220 		  (
221 			(Result_endnode == LEFT_SIDE)
222 			||
223 			(Result_endnode == ON_AREA)
224 		  )
225 		 )
226 		 ||
227 		 (
228 		  (Result_beginnode == RIGHT_SIDE)
229 		  &&
230 		  (
231 			(Result_endnode == RIGHT_SIDE)
232 			||
233 			(Result_endnode == ON_AREA)
234 		  )
235 		 )
236 		 ||
237 		 (
238 		  (Result_beginnode == ON_AREA)
239 		  &&
240 		  (
241 			(Result_endnode == LEFT_SIDE)
242 			||
243 			(Result_endnode == RIGHT_SIDE)
244 			||
245 			(Result_endnode == ON_AREA)
246 		  )
247 		 )
248 		)
249 		return 0;
250 	// Action 2.2, there is a real intersection, which must be calculated
251 	if (
252 		 (
253 		  (Result_beginnode == LEFT_SIDE)
254 		  &&
255 		  (Result_endnode == RIGHT_SIDE)
256 		 )
257 		 ||
258 		 (
259 		  (Result_beginnode == RIGHT_SIDE)
260 		  &&
261 		  (Result_endnode == LEFT_SIDE)
262 		 )
263 		)
264 		return 1;
265 	// Action 2.3, endnode is a crosspoint
266 	if (
267 		 (
268 		  (Result_beginnode == LEFT_SIDE)
269 		  ||
270 		  (Result_beginnode == RIGHT_SIDE)
271 		  ||
272 		  (Result_beginnode == ON_AREA)
273 		 )
274 		 &&
275 		 (Result_endnode == IN_AREA)
276 		)
277 		return 2;
278 	// Action 2.4, beginnode is a crosspoint
279 	if (
280 		 (Result_beginnode == IN_AREA)
281 		 &&
282 		 (
283 		  (Result_endnode == LEFT_SIDE)
284 		  ||
285 		  (Result_endnode == RIGHT_SIDE)
286 		  ||
287 		  (Result_endnode == ON_AREA)
288 		 )
289 		)
290 		return 3;
291 	// All other combinations are illegal
292 	return -1;
293 }
294 
295 //
296 // This fucntion will ad a crossing to this line and the other line
297 // the crossing will be put in the link, because the line will be destructed
298 // after use of the variable
299 //
AddLineCrossing(B_INT X,B_INT Y,KBoolLine * other_line)300 void KBoolLine::AddLineCrossing(B_INT X, B_INT Y, KBoolLine *other_line)
301 {
302 	// the other line must exist
303 	assert(other_line);
304 	// the links of the lines must exist
305 	assert(other_line->m_link && m_link);
306 	other_line->AddCrossing(AddCrossing(X,Y));
307 }
308 
309 // Calculate the Y when the X is given
310 //
Calculate_Y(B_INT X)311 B_INT KBoolLine::Calculate_Y(B_INT X)
312 {
313 	// link must exist to get info about the nodes
314 	assert(m_link);
315 
316 	CalculateLineParameters();
317 	if (m_AA != 0)
318 		return (B_INT)(-(m_AA * X + m_CC) / m_BB);
319 	else
320 		// horizontal line
321 		return m_link->GetBeginNode()->GetY();
322 }
323 
Calculate_Y_from_X(B_INT X)324 B_INT KBoolLine::Calculate_Y_from_X(B_INT X)
325 {
326 	// link must exist to get info about the nodes
327 	assert(m_link);
328 	assert(m_valid_parameters);
329 
330 	if (m_AA != 0)
331 		return (B_INT) ((-(m_AA * X + m_CC) / m_BB)+0.5);
332 	else
333 		// horizontal line
334 		return m_link->GetBeginNode()->GetY();
335 }
336 
Virtual_Point(LPoint * a_point,double distance)337 void KBoolLine::Virtual_Point(LPoint *a_point,double distance)
338 {
339 	// link must exist to get info about the nodes
340 	assert(m_link);
341 	assert(m_valid_parameters);
342 
343 	//calculate the distance using the slope of the line
344    //and rotate 90 degrees
345 
346 	a_point->SetY((B_INT)(a_point->GetY() + (distance * -(m_BB))));
347 	a_point->SetX((B_INT)(a_point->GetX() - (distance * m_AA   )));
348 }
349 
350 
351 
352 //
353 // Calculate the lineparameters for the line if nessecary
354 //
CalculateLineParameters()355 void KBoolLine::CalculateLineParameters()
356 {
357 	// linkmust exist to get beginnode AND endnode
358 	assert(m_link);
359 
360 	// if not valid_parameters calculate the parameters
361 	if (!m_valid_parameters)
362 	{
363 		Node *bp, *ep;
364 		double length;
365 
366 		// get the begin and endnode via the link
367 		bp = m_link->GetBeginNode();
368 		ep = m_link->GetEndNode();
369 
370 		// bp AND ep may not be the same
371 		if (bp == ep)
372 			assert (bp != ep);
373 
374 		m_AA = (double) (ep->GetY() - bp->GetY()); // A = (Y2-Y1)
375 		m_BB = (double) (bp->GetX() - ep->GetX()); // B = (X1-X2)
376 
377 		// the parameters A end B can now be normalized
378 		length = sqrt(m_AA*m_AA + m_BB*m_BB);
379 
380 		if(length ==0)
381 			m_GC->error("length = 0","CalculateLineParameters");
382 
383 		m_AA = (m_AA / length);
384 		m_BB = (m_BB / length);
385 
386 		m_CC = -((m_AA * bp->GetX()) + (bp->GetY() * m_BB));
387 
388 		m_valid_parameters = true;
389 	}
390 }
391 
392 
393 // Checks if a line intersect with another line
394 // inout    Line : another line
395 //          Marge: optional, standard on MARGE (declared in MISC.CPP)
396 //
397 // return	true : lines are crossing
398 // 			false: lines are not crossing
399 //
CheckIntersect(KBoolLine * lijn,double Marge)400 int KBoolLine::CheckIntersect (KBoolLine * lijn, double Marge)
401 {
402 	double distance=0;
403 	// link must exist
404 	assert(m_link);
405 	// lijn must exist
406 	assert(lijn);
407 
408 	// points may not be equal
409 	// must be an if statement because if an assert is used there will
410 	// be a macro expansion error
411 	if (m_link->GetBeginNode() == m_link->GetEndNode())
412 		assert(!m_link);
413 
414 	int Take_Action1, Take_Action2, Total_Result;
415 	Node *bp, *ep;
416 	PointStatus Result_beginnode,Result_endnode;
417 
418 	bp = lijn->m_link->GetBeginNode();
419 	ep = lijn->m_link->GetEndNode();
420 	Result_beginnode = PointInLine(bp,distance,Marge);
421 	Result_endnode   = PointInLine(ep,distance,Marge);
422 	Take_Action1 = ActionOnTable1(Result_beginnode,Result_endnode);
423 	switch (Take_Action1)
424 	{
425 		case 0: Total_Result = false ; break;
426 		case 1: {
427 						bp = m_link->GetBeginNode();
428 						ep = m_link->GetEndNode();
429 						Result_beginnode = lijn->PointInLine(bp,distance,Marge);
430 						Result_endnode   = lijn->PointInLine(ep,distance,Marge);
431 						Take_Action2 = ActionOnTable2(Result_beginnode,Result_endnode);
432 						switch (Take_Action2)
433 						{
434 							case 0: Total_Result = false; break;
435 							case 1: case 2: case 3: case 4: Total_Result = true; break;
436               default: Total_Result = false; assert( Total_Result );
437 						}
438 				  }; break; // This break belongs to the switch(Take_Action1)
439 		case 2: case 3: case 4: case 5: case 6: Total_Result = true; break;
440     default: Total_Result = false; assert( Total_Result );
441 	}
442 	return Total_Result; //This is the final decision
443 }
444 
445 
446 //
447 // Get the beginnode from the line
448 // usage: Node *anode = a_line.GetBeginNode()
449 //
GetBeginNode()450 Node *KBoolLine::GetBeginNode()
451 {
452   // link must exist
453   assert(m_link);
454   return m_link->GetBeginNode();
455 }
456 
457 
458 //
459 // Get the endnode from the line
460 // usage: Node *anode = a_line.GetEndNode()
461 //
GetEndNode()462 Node *KBoolLine::GetEndNode()
463 {
464 	// link must exist
465 	assert(m_link);
466 	return m_link->GetEndNode();
467 }
468 
469 // Intersects two lines
470 // input    Line : another line
471 //          Marge: optional, standard on MARGE
472 //
473 // return	0: If there are no crossings
474 //				1: If there is one crossing
475 //				2: If there are two crossings
Intersect(KBoolLine * lijn,double Marge)476 int KBoolLine::Intersect(KBoolLine * lijn, double Marge)
477 {
478 	double distance=0;
479 	// lijn must exist
480 	assert(lijn);
481 
482 	// points may not be equal
483 	// must be an if statement because if an assert is used there will
484 	// be a macro expansion error
485 	if (m_link->GetBeginNode() == m_link->GetEndNode())
486 		assert(!m_link);
487 
488 	Node *bp, *ep;
489 	PointStatus Result_beginnode,Result_endnode;
490 	int Take_Action1, Take_Action2, Number_of_Crossings = 0;
491 
492 	// Get the nodes from lijn via the link
493 	bp = lijn->m_link->GetBeginNode();
494 	ep = lijn->m_link->GetEndNode();
495 
496   	Result_beginnode = PointInLine(bp,distance,Marge);
497 	Result_endnode   = PointInLine(ep,distance,Marge);
498 
499 	Take_Action1 = ActionOnTable1(Result_beginnode,Result_endnode);
500 
501 	// The first switch will insert a crosspoint immediatly
502 	switch (Take_Action1)
503 	{
504 		// for the cases see the returnvalue of ActionTable1
505 		case 2: case 6: AddCrossing(ep);
506 							 Number_of_Crossings = 1;
507 							 break;
508 		case 3: case 5: AddCrossing(bp);
509 							 Number_of_Crossings = 1;
510 							 break;
511 		case 4: 			 AddCrossing(bp);
512 							 AddCrossing(ep);
513 							 Number_of_Crossings = 2;
514 							 break;
515 	}
516 	// This switch wil investigate the points of this line in relation to lijn
517 	switch (Take_Action1)
518 	{
519 		// for the cases see the returnvalue of ActionTable1
520 		case 1: case 5: case 6:
521 		  {
522 				// Get the nodes from this line via the link
523 				bp = m_link->GetBeginNode();
524 				ep = m_link->GetEndNode();
525             Result_beginnode = lijn->PointInLine(bp,distance,Marge);
526             Result_endnode   = lijn->PointInLine(ep,distance,Marge);
527 				Take_Action2 = ActionOnTable2(Result_beginnode,Result_endnode);
528 				switch (Take_Action2)
529 				{
530 					// for the cases see the returnvalue of ActionTable2
531 					case 1: {   // begin of scope to calculate the intersection
532 									double X, Y, Denominator;
533 									CalculateLineParameters();
534 									Denominator  = (m_AA * lijn->m_BB) - (lijn->m_AA * m_BB);
535 									// Denominator may not be 0
536 									assert(Denominator != 0.0);
537 									// Calculate intersection of both linesegments
538 									X = ((m_BB * lijn->m_CC) - (lijn->m_BB * m_CC)) / Denominator;
539 									Y = ((lijn->m_AA * m_CC) - (m_AA * lijn->m_CC)) / Denominator;
540 
541                            //make a decent rounding to B_INT
542                            AddLineCrossing((B_INT)X,(B_INT)Y,lijn);
543 							  }   // end of scope to calculate the intersection
544 							  Number_of_Crossings++;
545 							  break;
546 					case 2: lijn->AddCrossing(ep);
547 							  Number_of_Crossings++;
548 							  break;
549 					case 3: lijn->AddCrossing(bp);
550 							  Number_of_Crossings++;
551 							  break;
552 					case 4: lijn->AddCrossing(bp);
553 							  lijn->AddCrossing(ep);
554 							  Number_of_Crossings = 2;
555 							  break;
556 				}
557 		  }; break; // This break belongs to the outer switch
558 	}
559 	return Number_of_Crossings; //This is de final number of crossings
560 }
561 
562 
563 // Intersects two lines there must be a crossing
Intersect_simple(KBoolLine * lijn)564 int KBoolLine::Intersect_simple(KBoolLine * lijn)
565 {
566 	// lijn must exist
567 	assert(lijn);
568 
569 	double X, Y, Denominator;
570 	Denominator  = (m_AA * lijn->m_BB) - (lijn->m_AA * m_BB);
571 	// Denominator may not be 0
572 	if (Denominator == 0.0)
573 			m_GC->error("colliniar lines","line");
574 	// Calculate intersection of both linesegments
575 	X = ((m_BB * lijn->m_CC) - (lijn->m_BB * m_CC)) / Denominator;
576 	Y = ((lijn->m_AA * m_CC) - (m_AA * lijn->m_CC)) / Denominator;
577 	AddLineCrossing((B_INT)X,(B_INT)Y,lijn);
578 
579 	return(0);
580 }
581 
582 // Intersects two lines there must be a crossing
Intersect2(Node * crossing,KBoolLine * lijn)583 bool KBoolLine::Intersect2(Node* crossing,KBoolLine * lijn)
584 {
585 	// lijn must exist
586 	assert(lijn);
587 
588 	double X, Y, Denominator;
589 	Denominator  = (m_AA * lijn->m_BB) - (lijn->m_AA * m_BB);
590 	// Denominator may not be 0
591 	if (Denominator == 0.0)
592 		return false;
593 	// Calculate intersection of both linesegments
594 	X = ((m_BB * lijn->m_CC) - (lijn->m_BB * m_CC)) / Denominator;
595 	Y = ((lijn->m_AA * m_CC) - (m_AA * lijn->m_CC)) / Denominator;
596 
597 	crossing->SetX((B_INT)X);
598 	crossing->SetY((B_INT)Y);
599 	return true;
600 }
601 
602 //
603 // test if a point lies in the linesegment. If the point isn't on the line
604 // the function returns a value that indicates on which side of the
605 // line the point is (in linedirection from first point to second point
606 //
607 // returns LEFT_SIDE, when point lies on the left side of the line
608 //         RIGHT_SIDE, when point lies on the right side of the line
609 //         ON_AREA, when point lies on the infinite line within a range
610 //			  IN_AREA, when point lies in the area of the linesegment
611 // 		  the returnvalues are declared in (LINE.H)
PointInLine(Node * a_node,double & Distance,double Marge)612 PointStatus KBoolLine::PointInLine(Node *a_node, double& Distance, double Marge)
613 {
614 	  Distance=0;
615 
616 	  //Punt must exist
617 	  assert(a_node);
618 	  // link must exist to get beginnode and endnode via link
619 	  assert(m_link);
620 
621 	  // get the nodes form the line via the link
622 	  Node *bp, *ep;
623 	  bp = m_link->GetBeginNode();
624 	  ep = m_link->GetEndNode();
625 
626 	  // both node must exist
627 	  assert(bp && ep);
628 	  // node may not be the same
629 	  assert(bp != ep);
630 
631      //quick test if point is begin or endpoint
632      if (a_node == bp || a_node == ep)
633         return IN_AREA;
634 
635 	  int Result_of_BBox=false;
636 	  PointStatus Result_of_Online;
637 
638 	  // Checking if point is in bounding-box with marge
639      B_INT xmin=bmin(bp->GetX(),ep->GetX());
640      B_INT xmax=bmax(bp->GetX(),ep->GetX());
641      B_INT ymin=bmin(bp->GetY(),ep->GetY());
642      B_INT ymax=bmax(bp->GetY(),ep->GetY());
643 
644      if (  a_node->GetX() >= (xmin - Marge) && a_node->GetX() <= (xmax + Marge) &&
645            a_node->GetY() >= (ymin - Marge) && a_node->GetY() <= (ymax + Marge) )
646 		  Result_of_BBox=true;
647 
648 	  // Checking if point is on the infinite line
649 	  Result_of_Online = PointOnLine(a_node, Distance, Marge);
650 
651 	  // point in boundingbox of the line and is on the line then the point is IN_AREA
652 	  if ((Result_of_BBox) && (Result_of_Online == ON_AREA))
653 			return IN_AREA;
654 	  else
655 			return Result_of_Online;
656 }
657 
658 
659 //
660 // test if a point lies on the line. If the point isn't on the line
661 // the function returns a value that indicates on which side of the
662 // line the point is (in linedirection from first point to second point
663 //
664 // returns LEFT_SIDE, when point lies on the left side of the line
665 //         ON_AREA, when point lies on the infinite line within a range
666 //         RIGHT_SIDE, when point lies on the right side of the line
667 // 		  LEFT_SIDE , RIGHT_SIDE , ON_AREA
PointOnLine(Node * a_node,double & Distance,double Marge)668 PointStatus KBoolLine::PointOnLine(Node *a_node, double& Distance, double Marge)
669 {
670    Distance=0;
671 
672 	// a_node must exist
673 	assert(a_node);
674 	// link must exist to get beginnode and endnode
675 	assert(m_link);
676 
677 	// get the nodes from the line via the link
678 	Node *bp, *ep;
679 	bp = m_link->GetBeginNode();
680 	ep = m_link->GetEndNode();
681 
682 	// both node must exist
683 	assert(bp && ep);
684 	// node may not be queal
685 	assert(bp!=ep);
686 
687    //quick test if point is begin or endpoint
688    if (a_node == bp || a_node == ep)
689       return ON_AREA;
690 
691 	CalculateLineParameters();
692 	// calculate the distance of a_node in relation to the line
693 	Distance = (m_AA * a_node->GetX())+(m_BB * a_node->GetY()) + m_CC;
694 
695 	if (Distance < -Marge)
696 		return LEFT_SIDE;
697 	else
698 	{
699 		if (Distance > Marge)
700 			return RIGHT_SIDE;
701 		else
702 		 return ON_AREA;
703 	}
704 }
705 
706 
707 //
708 // Sets lines parameters
709 // usage: a_line.Set(a_pointer_to_a_link);
710 //
Set(KBoolLink * a_link)711 void KBoolLine::Set(KBoolLink *a_link)
712 {
713 	// points must exist
714 	assert(a_link);
715 	// points may not be equal
716 	// must be an if statement because if an assert is used there will
717 	// be a macro expansion error
718 //	if (a_link->GetBeginNode()->Equal(a_link->GetEndNode(),MARGE)) assert(!a_link);
719 
720 	linecrosslist = NULL;
721 	m_link = a_link;
722 	m_valid_parameters = false;
723 }
724 
GetLink()725 KBoolLink* KBoolLine::GetLink()
726 {
727    return m_link;
728 }
729 //
730 // makes a line same as these
731 // usage : line1 = line2;
732 //
operator =(const KBoolLine & a_line)733 KBoolLine& KBoolLine::operator=(const KBoolLine& a_line)
734 {
735 	m_AA = a_line.m_AA;
736 	m_BB = a_line.m_BB;
737 	m_CC = a_line.m_CC;
738 	m_link = a_line.m_link;
739   	linecrosslist = NULL;
740 	m_valid_parameters = a_line.m_valid_parameters;
741 	return *this;
742 }
743 
OffsetContour(KBoolLine * const nextline,Node * _last_ins,double factor,Graph * shape)744 Node* KBoolLine::OffsetContour(KBoolLine* const nextline,Node* _last_ins, double factor,Graph *shape)
745 {
746 	KBoolLink* offs_currentlink;
747 	KBoolLine  offs_currentline(m_GC);
748 	KBoolLink* offs_nextlink;
749 	KBoolLine  offs_nextline(m_GC);
750 	Node* offs_end;
751 
752 	Node* offs_bgn_next;
753 	Node* offs_end_next;
754 
755 	// make a node from this point
756 	offs_end = new Node(GetEndNode(), m_GC);
757 	Virtual_Point(offs_end,factor);
758 	offs_currentlink=new KBoolLink(0, m_link->m_user_data, _last_ins,offs_end, m_GC);
759 	offs_currentline.Set(offs_currentlink);
760 
761 	offs_bgn_next = new Node(nextline->m_link->GetBeginNode(), m_GC);
762 	nextline->Virtual_Point(offs_bgn_next,factor);
763 
764 	offs_end_next = new Node(nextline->m_link->GetEndNode(), m_GC);
765 	nextline->Virtual_Point(offs_end_next,factor);
766 
767 	offs_nextlink=new KBoolLink(0, m_link->m_user_data, offs_bgn_next, offs_end_next, m_GC);
768 	offs_nextline.Set(offs_nextlink);
769 
770 	offs_currentline.CalculateLineParameters();
771 	offs_nextline.CalculateLineParameters();
772 	offs_currentline.Intersect2(offs_end,&offs_nextline);
773 
774 	// make a link between the current and the previous and add this to graph
775 	shape->AddLink(offs_currentlink);
776 
777 	delete offs_nextlink;
778 
779 	return(offs_end);
780 }
781 
782 
OffsetContour_rounded(KBoolLine * const nextline,Node * _last_ins,double factor,Graph * shape)783 Node* KBoolLine::OffsetContour_rounded(KBoolLine* const nextline,Node* _last_ins, double factor,Graph *shape)
784 {
785 	KBoolLink* offs_currentlink;
786 	KBoolLine  offs_currentline(m_GC);
787 	KBoolLink* offs_nextlink;
788 	KBoolLine  offs_nextline(m_GC);
789 	Node* offs_end;
790 	Node* medial_axes_point= new Node(m_GC);
791 	Node* bu_last_ins = new Node(_last_ins, m_GC);
792 
793 	Node* offs_bgn_next;
794 	Node* offs_end_next;
795 
796 	// make a node from this point
797 	offs_end = new Node(GetEndNode(), m_GC);
798 
799 	*_last_ins = *GetBeginNode();
800 	Virtual_Point(_last_ins,factor);
801 	Virtual_Point(offs_end,factor);
802 	offs_currentlink=new KBoolLink(0, m_link->m_user_data, _last_ins,offs_end, m_GC);
803 	offs_currentline.Set(offs_currentlink);
804 
805 	offs_bgn_next = new Node(nextline->m_link->GetBeginNode(), m_GC);
806 	nextline->Virtual_Point(offs_bgn_next,factor);
807 
808 	offs_end_next = new Node(nextline->m_link->GetEndNode(), m_GC);
809 	nextline->Virtual_Point(offs_end_next,factor);
810 
811 	offs_nextlink=new KBoolLink(0, m_link->m_user_data, offs_bgn_next, offs_end_next, m_GC);
812 	offs_nextline.Set(offs_nextlink);
813 
814 	offs_currentline.CalculateLineParameters();
815 	offs_nextline.CalculateLineParameters();
816 	offs_currentline.Intersect2(medial_axes_point,&offs_nextline);
817 
818 	double result_offs=sqrt( pow((double)GetEndNode()->GetY()-medial_axes_point->GetY(),2) +
819 							 pow((double)GetEndNode()->GetX()-medial_axes_point->GetX(),2) );
820 
821 	if ( result_offs < fabs(m_GC->GetRoundfactor()*factor))
822 	{
823 		*_last_ins=*bu_last_ins;
824 		*offs_end=*medial_axes_point;
825 		delete medial_axes_point;
826 		delete bu_last_ins;
827 		// make a link between the current and the previous and add this to graph
828 		delete offs_nextlink;
829 		shape->AddLink(offs_currentlink);
830 		return(offs_end);
831 	}
832 	else
833 	{ //let us create a circle
834 		*_last_ins=*bu_last_ins;
835 		delete medial_axes_point;
836 		delete bu_last_ins;
837 		Node* endarc= new Node(offs_bgn_next, m_GC);
838 		shape->AddLink(offs_currentlink);
839 		delete offs_nextlink;
840 		shape->CreateArc(GetEndNode(), &offs_currentline, endarc,fabs(factor),m_GC->GetInternalCorrectionAber(), m_link->m_user_data);
841 		return(endarc);
842 	}
843 }
844 
845 
OkeForContour(KBoolLine * const nextline,double factor,Node * LastLeft,Node * LastRight,LinkStatus & _outproduct)846 bool KBoolLine::OkeForContour(KBoolLine* const nextline,double factor,Node* LastLeft,Node* LastRight, LinkStatus& _outproduct)
847 {
848 	assert(m_link);
849 	assert(m_valid_parameters);
850 	assert(nextline->m_link);
851 	assert(nextline->m_valid_parameters);
852 
853 	factor = fabs(factor);
854 
855 //	PointStatus status=ON_AREA;
856 	double distance=0;
857 
858 	Node offs_end_next(nextline->m_link->GetEndNode(), m_GC);
859 
860 	_outproduct= m_link->OutProduct(nextline->m_link,m_GC->GetAccur());
861 
862 	switch (_outproduct)
863 	{
864 		// current line lies on  leftside of prev line
865 		case IS_RIGHT :
866 		{
867 			nextline->Virtual_Point(&offs_end_next,-factor);
868 
869 			// status=
870 			nextline->PointOnLine(LastRight, distance, m_GC->GetAccur());
871 			if (distance > factor)
872 			{  PointOnLine(&offs_end_next, distance, m_GC->GetAccur());
873 				if (distance > factor)
874 					 return(true);
875 			}
876 		}
877 		break;
878 		// current line lies on  rightside of prev line
879 		case IS_LEFT :
880 		{
881 			nextline->Virtual_Point(&offs_end_next,factor);
882 
883 			// status=
884 			nextline->PointOnLine(LastLeft, distance, m_GC->GetAccur());
885 			if (distance < -factor)
886 			{  PointOnLine(&offs_end_next, distance, m_GC->GetAccur());
887 				if (distance <-factor)
888 					 return(true);
889 			}
890 		}
891 		break;
892 		// current line  lies on prev line
893 		case IS_ON	 :
894 		{
895 			return(true);
896 		}
897 	}//end switch
898 
899 	return(false);
900 }
901 
902 
Create_Ring_Shape(KBoolLine * nextline,Node ** _last_ins_left,Node ** _last_ins_right,double factor,Graph * shape)903 bool KBoolLine::Create_Ring_Shape(KBoolLine* nextline,Node** _last_ins_left,Node** _last_ins_right,double factor,Graph *shape)
904 {
905 	Node* _current;
906 	LinkStatus _outproduct=IS_ON;
907 
908 	if (OkeForContour(nextline,factor,*_last_ins_left,*_last_ins_right,_outproduct))
909 	{
910 		switch (_outproduct)
911 		{
912 			// Line 2 lies on  leftside of this line
913 			case IS_RIGHT :
914 			{
915 				*_last_ins_left  =OffsetContour_rounded(nextline,*_last_ins_left,factor,shape);
916 				*_last_ins_right =OffsetContour(nextline,*_last_ins_right,-factor,shape);
917 			}
918 			break;
919 			case IS_LEFT :
920 			{
921 				*_last_ins_left  =OffsetContour(nextline,*_last_ins_left,factor,shape);
922 				*_last_ins_right =OffsetContour_rounded(nextline,*_last_ins_right,-factor,shape);
923 
924 			}
925 			break;
926 			// Line 2 lies on this line
927 			case IS_ON	 :
928 			{
929 				// make a node from this point
930 				_current = new Node(m_link->GetEndNode(), m_GC);
931 				Virtual_Point(_current,factor);
932 
933 				// make a link between the current and the previous and add this to graph
934 				shape->AddLink(*_last_ins_left, _current, m_link->m_user_data);
935 				*_last_ins_left=_current;
936 
937 				_current = new Node(m_link->GetEndNode(), m_GC);
938 				Virtual_Point(_current,-factor);
939 
940 				shape->AddLink(*_last_ins_right, _current, m_link->m_user_data);
941 				*_last_ins_right=_current;
942 			}
943 			break;
944 		}//end switch
945 		return(true);
946 	}
947 /*	else
948 	{
949 		switch (_outproduct)
950 		{
951 			// Line 2 lies on  leftside of this line
952 			case IS_RIGHT :
953 			{
954 				*_last_ins_left  =OffsetContour_rounded(nextline,*_last_ins_left,factor,Ishape);
955 				*_last_ins_right =OffsetContour(nextline,*_last_ins_right,-factor,Ishape);
956 			}
957 			break;
958 			case IS_LEFT :
959 			{
960 				*_last_ins_left  =OffsetContour(nextline,*_last_ins_left,factor,Ishape);
961 				*_last_ins_right =OffsetContour_rounded(nextline,*_last_ins_right,-factor,Ishape);
962 
963 			}
964 			break;
965 			// Line 2 lies on this line
966 			case IS_ON	 :
967 			{
968 				// make a node from this point
969 				_current = new Node(m_link->GetEndNode());
970 				Virtual_Point(_current,factor);
971 
972 				// make a link between the current and the previous and add this to graph
973 				Ishape->AddLink(*_last_ins_left, _current);
974 				*_last_ins_left=_current;
975 
976 				_current = new Node(m_link->GetEndNode());
977 				Virtual_Point(_current,-factor);
978 
979 				Ishape->AddLink(*_last_ins_right, _current);
980 				*_last_ins_right=_current;
981 			}
982 			break;
983 		}//end switch
984 		return(true);
985 	}
986 */
987 	return(false);
988 }
989 
990 
Create_Begin_Shape(KBoolLine * nextline,Node ** _last_ins_left,Node ** _last_ins_right,double factor,Graph * shape)991 void KBoolLine::Create_Begin_Shape(KBoolLine* nextline,Node** _last_ins_left,Node** _last_ins_right,double factor,Graph *shape)
992 {
993 	factor = fabs(factor);
994 	LinkStatus _outproduct;
995 	_outproduct= m_link->OutProduct(nextline->m_link,m_GC->GetAccur());
996 
997 	switch (_outproduct)
998 	{
999 		case IS_RIGHT :
1000 		{
1001 			*_last_ins_left = new Node(m_link->GetEndNode(), m_GC);
1002 
1003 			Virtual_Point(*_last_ins_left,factor);
1004 
1005 			*_last_ins_right = new Node(nextline->m_link->GetBeginNode(), m_GC);
1006 			nextline->Virtual_Point(*_last_ins_right,-factor);
1007 
1008 			shape->AddLink(*_last_ins_left, *_last_ins_right, m_link->m_user_data);
1009 
1010 			*_last_ins_left=OffsetContour_rounded(nextline,*_last_ins_left,factor,shape);
1011 		}
1012 		break;
1013 		case IS_LEFT :
1014 		{
1015 			*_last_ins_left = new Node(nextline->m_link->GetBeginNode(), m_GC);
1016 			nextline->Virtual_Point(*_last_ins_left,factor);
1017 
1018 			*_last_ins_right = new Node(m_link->GetEndNode(), m_GC);
1019 			Virtual_Point(*_last_ins_right,-factor);
1020 
1021 			shape->AddLink(*_last_ins_left, *_last_ins_right, m_link->m_user_data);
1022 
1023 			*_last_ins_right=OffsetContour_rounded(nextline,*_last_ins_right,-factor,shape);
1024 		}
1025 		break;
1026 		// Line 2 lies on this line
1027 		case IS_ON	 :
1028 		{
1029 			*_last_ins_left = new Node(nextline->m_link->GetBeginNode(), m_GC);
1030 			Virtual_Point(*_last_ins_left,factor);
1031 
1032 			*_last_ins_right = new Node(nextline->m_link->GetBeginNode(), m_GC);
1033 			Virtual_Point(*_last_ins_right,-factor);
1034 
1035 			shape->AddLink(*_last_ins_left, *_last_ins_right, m_link->m_user_data);
1036 		}
1037 		break;
1038 	}//end switch
1039 
1040 }
1041 
Create_End_Shape(KBoolLine * nextline,Node * _last_ins_left,Node * _last_ins_right,double factor,Graph * shape)1042 void KBoolLine::Create_End_Shape(KBoolLine* nextline,Node* _last_ins_left,Node* _last_ins_right,double factor,Graph *shape)
1043 {
1044 	Node* _current;
1045 	factor = fabs(factor);
1046 	LinkStatus _outproduct;
1047 	_outproduct= m_link->OutProduct(nextline->m_link,m_GC->GetAccur());
1048 
1049 	switch (_outproduct)
1050 	{
1051 		case IS_RIGHT :
1052 		{
1053 			_current = new Node(m_link->GetEndNode(), m_GC);
1054 			Virtual_Point(_current,-factor);
1055 			shape->AddLink(_last_ins_right, _current, m_link->m_user_data);
1056 			_last_ins_right=_current;
1057 
1058 			_last_ins_left=OffsetContour_rounded(nextline,_last_ins_left,factor,shape);
1059 			shape->AddLink(_last_ins_left,_last_ins_right, m_link->m_user_data);
1060 		}
1061 		break;
1062 		case IS_LEFT :
1063 		{
1064 			_current = new Node(m_link->GetEndNode(), m_GC);
1065 			Virtual_Point(_current,factor);
1066 			shape->AddLink(_last_ins_left, _current, m_link->m_user_data);
1067 			_last_ins_left=_current;
1068 
1069 			_last_ins_right=OffsetContour_rounded(nextline,_last_ins_right,-factor,shape);
1070 			shape->AddLink(_last_ins_right, _last_ins_left, m_link->m_user_data);
1071 		}
1072 		break;
1073 		// Line 2 lies on this line
1074 		case IS_ON	 :
1075 		{
1076 			_current = new Node(m_link->GetEndNode(), m_GC);
1077 			Virtual_Point(_current,factor);
1078 			shape->AddLink(_last_ins_left, _current, m_link->m_user_data);
1079 			_last_ins_left=_current;
1080 
1081 			_current = new Node(m_link->GetEndNode(), m_GC);
1082 			Virtual_Point(_current,-factor);
1083 			shape->AddLink(_last_ins_right, _current, m_link->m_user_data);
1084 			_last_ins_right=_current;
1085 
1086 			shape->AddLink(_last_ins_left, _last_ins_right, m_link->m_user_data);
1087 		}
1088 		break;
1089 	}//end switch
1090 
1091 }
1092 
1093 //
1094 // Generate from the found crossings a part of the graph
1095 //
ProcessCrossings(TDLI<KBoolLink> * _LI)1096 bool KBoolLine::ProcessCrossings(TDLI<KBoolLink>* _LI)
1097 {
1098 	Node *last;	KBoolLink *dummy;
1099 //	assert (beginnode && endnode);
1100 
1101 	if (!linecrosslist)	return false;
1102 
1103 	if (linecrosslist->empty())	return false;
1104 	if (linecrosslist->count()>1)	SortLineCrossings();
1105 	m_link->GetEndNode()->RemoveLink(m_link);
1106 	last=m_link->GetEndNode();
1107 	// Make new links :
1108 	while (!linecrosslist->empty())
1109 	{
1110 		dummy=new KBoolLink(m_link->GetGraphNum(), m_link->m_user_data, (Node*) linecrosslist->tailitem(),last, m_GC);
1111       dummy->SetBeenHere();
1112 		dummy->SetGroup(m_link->Group());
1113       _LI->insbegin(dummy);
1114 		last=(Node*)linecrosslist->tailitem();
1115 		linecrosslist->removetail();
1116 	}
1117 	// Recycle this link :
1118 	last->AddLink(m_link);
1119 	m_link->SetEndNode(last);
1120 	delete linecrosslist;
1121 	linecrosslist=NULL;
1122 	return true;
1123 }
1124 
1125 /*
1126 // Sorts the links on the X values
1127 int NodeXYsorter(Node* a, Node* b)
1128 {
1129 	if ( a->GetX() < b->GetX())
1130 		return(1);
1131 	if ( a->GetX() > b->GetX())
1132 		return(-1);
1133    //they are eqaul in x
1134 	if ( a->GetY() < b->GetY())
1135 		return(-1);
1136 	if ( a->GetY() > b->GetY())
1137 		return(1);
1138    //they are eqaul in y
1139 	return(0);
1140 }
1141 
1142 //
1143 // Generate from the found crossings a part of the graph
1144 // this routine is used in combination with the scanbeam class
1145 // the this link most stay at the same place in the sorted graph
1146 // The link is split into peaces wich are inserted sorted into the graph
1147 // on beginnode.
1148 // The mostleft link most become the new link for the beam record
1149 // therefore the mostleft new/old link is returned to become the beam record link
1150 // also the part returned needs to have the bin flag set to the original value it had in the beam
1151 KBoolLink* KBoolLine::ProcessCrossingsSmart(TDLI<KBoolLink>* _LI)
1152 {
1153    Node *lastinserted;
1154    KBoolLink *new_link;
1155    KBoolLink *returnlink;
1156 	assert (beginnode && endnode);
1157 	if (!linecrosslist)	return this;
1158 
1159 	if (linecrosslist->empty())	return this;
1160 	if (linecrosslist->count()>1)
1161    {
1162    	SortLineCrossings();
1163    }
1164 	int inbeam;
1165 
1166    //most left at the beginnode or endnode
1167    if (NodeXYsorter(beginnode,endnode)==1)
1168    {
1169       //re_use this link
1170       endnode->RemoveLink(this);
1171       linecrosslist->insend(endnode); //the last link to create is towards this node
1172       endnode=(Node*) linecrosslist->headitem();
1173       endnode->AddLink(this);
1174       inbeam=NodeXYsorter(_LI->item()->beginnode,beginnode);
1175       switch (inbeam)
1176       {
1177         case -1:
1178         case 0:
1179             bin=true;
1180             break;
1181         case 1:
1182             bin=false;
1183             break;
1184       }
1185       returnlink=this;
1186 
1187       lastinserted=endnode;
1188       linecrosslist->removehead();
1189       // Make new links starting at endnode
1190       while (!linecrosslist->empty())
1191       {
1192          new_link=new KBoolLink(graphnum,lastinserted,(Node*) linecrosslist->headitem());
1193 
1194          new_link->group=group;
1195          int inbeam=NodeXYsorter(_LI->item()->beginnode,lastinserted);
1196          switch (inbeam)
1197          {
1198            case -1:
1199                {
1200                  double x,y,xl,yl;
1201                  char buf[80];
1202                  x=((Node*)(linecrosslist->headitem()))->GetX();
1203                  y=((Node*)(linecrosslist->headitem()))->GetY();
1204 					  xl=_LI->item()->beginnode->GetX();
1205                  yl=_LI->item()->beginnode->GetY();
1206                  sprintf(buf," x=%f , y=%f inserted before %f,%f",x,y,xl,yl);
1207                  _messagehandler->info(buf,"scanbeam");
1208 		           new_link->bin=true;
1209                }
1210                break;
1211            case 0:
1212 	            new_link->bin=true;
1213 	            returnlink=new_link;
1214                break;
1215            case 1:
1216 	            new_link->bin=false;
1217                break;
1218          }
1219 
1220          //insert a link into the graph that is already sorted on beginnodes of the links.
1221          //starting at a given position
1222          // if empty then just insert
1223 
1224          if (_LI->empty())
1225             _LI->insend(new_link);
1226          else
1227          {
1228             // put new item left of the one that is bigger are equal
1229             int i=0;
1230             int insert=0;
1231             while(!_LI->hitroot())
1232             {
1233                if ((insert=linkXYsorter(new_link,_LI->item()))!=-1)
1234                   break;
1235                (*_LI)++;
1236                i++;
1237             }
1238 
1239             _LI->insbefore_unsave(new_link);
1240             if (insert==0 && _LI->item()->beginnode!=new_link->beginnode)
1241              //the begin nodes are equal but not the same merge them into one node
1242             {  Node* todelete=_LI->item()->beginnode;
1243 					new_link->beginnode->Merge(todelete);
1244 					delete todelete;
1245             }
1246 
1247             //set back iter
1248             (*_LI) << (i+1);
1249          }
1250 
1251          lastinserted=(Node*)linecrosslist->headitem();
1252          linecrosslist->removehead();
1253       }
1254    }
1255    else
1256    {
1257       //re_use this link
1258       endnode->RemoveLink(this);
1259       linecrosslist->insend(endnode); //the last link to create is towards this node
1260       endnode=(Node*) linecrosslist->headitem();
1261       endnode->AddLink(this);
1262       inbeam=NodeXYsorter(_LI->item()->beginnode,endnode);
1263       switch (inbeam)
1264       {
1265         case -1:
1266         case 0:
1267             bin=true;
1268             break;
1269         case 1:
1270             bin=false;
1271             break;
1272       }
1273       returnlink=this;
1274 
1275       lastinserted=endnode;
1276       linecrosslist->removehead();
1277 
1278       // Make new links starting at endnode
1279       while (!linecrosslist->empty())
1280       {
1281          new_link=new KBoolLink(graphnum,lastinserted,(Node*) linecrosslist->headitem());
1282          new_link->group=group;
1283 
1284          inbeam=NodeXYsorter(_LI->item()->beginnode,(Node*) linecrosslist->headitem());
1285          switch (inbeam)
1286          {
1287            case -1:
1288            case 0:
1289 	            new_link->bin=true;
1290                break;
1291            case 1:
1292 	            new_link->bin=false;
1293                break;
1294          }
1295          inbeam=NodeXYsorter(_LI->item()->beginnode,lastinserted);
1296          switch (inbeam)
1297          {
1298            case -1:
1299                {
1300                  double x,y,xl,yl;
1301                  char buf[80];
1302                  x=lastinserted->GetX();
1303                  y=lastinserted->GetY();
1304 					  xl=_LI->item()->beginnode->GetX();
1305                  yl=_LI->item()->beginnode->GetY();
1306                  sprintf(buf," x=%f , y=%f inserted before %f,%f",x,y,xl,yl);
1307                  _messagehandler->info(buf,"scanbeam");
1308                }
1309                break;
1310            case 0:
1311                break;
1312            case 1:
1313 	            returnlink=new_link;
1314                break;
1315          }
1316 
1317          //insert a link into the graph that is already sorted on beginnodes of the links.
1318          //starting at a given position
1319          // if empty then just insert
1320 
1321          if (_LI->empty())
1322             _LI->insend(new_link);
1323          else
1324          {
1325             // put new item left of the one that is bigger are equal
1326             int i=0;
1327             int insert=0;
1328             while(!_LI->hitroot())
1329             {
1330                if ((insert=linkXYsorter(new_link,_LI->item()))!=-1)
1331                   break;
1332                (*_LI)++;
1333                i++;
1334             }
1335 
1336             _LI->insbefore_unsave(new_link);
1337             if (insert==0 && _LI->item()->beginnode!=new_link->beginnode)
1338              //the begin nodes are equal but not the same merge them into one node
1339             {  Node* todelete=_LI->item()->beginnode;
1340 					new_link->beginnode->Merge(todelete);
1341 					delete todelete;
1342             }
1343             //set back iter
1344             (*_LI) << (i+1);
1345          }
1346 
1347          lastinserted=(Node*)linecrosslist->headitem();
1348          linecrosslist->removehead();
1349       }
1350    }
1351 	delete linecrosslist;
1352 	linecrosslist=NULL;
1353 
1354   	return returnlink;
1355 }
1356 */
1357 
NODE_X_ASCENDING_L(Node * a,Node * b)1358 static int NODE_X_ASCENDING_L (Node* a, Node* b)
1359 {
1360 	if(b->GetX() > a->GetX()) return(1);
1361 	else
1362 	if(b->GetX() == a->GetX()) return(0);
1363 
1364 	return(-1);
1365 }
1366 
NODE_X_DESCENDING_L(Node * a,Node * b)1367 static int NODE_X_DESCENDING_L(Node* a, Node* b)
1368 {
1369 	if(a->GetX() > b->GetX()) return(1);
1370 	else
1371 	if(a->GetX() == b->GetX()) return(0);
1372 
1373 	return(-1);
1374 }
1375 
NODE_Y_ASCENDING_L(Node * a,Node * b)1376 static int NODE_Y_ASCENDING_L (Node* a, Node* b)
1377 {
1378 	if(b->GetY() > a->GetY()) return(1);
1379 	else
1380 	if(b->GetY() == a->GetY()) return(0);
1381 	return(-1);
1382 }
1383 
NODE_Y_DESCENDING_L(Node * a,Node * b)1384 static int NODE_Y_DESCENDING_L(Node* a, Node* b)
1385 {
1386 	if(a->GetY() > b->GetY()) return(1);
1387 	else
1388 	if(a->GetY() == b->GetY()) return(0);
1389 
1390 	return(-1);
1391 }
1392 
1393 //
1394 // This function finds out which sortfunction to use with sorting
1395 // the crossings.
1396 //
SortLineCrossings()1397 void KBoolLine::SortLineCrossings()
1398 {
1399 	TDLI<Node> I(linecrosslist);
1400 
1401 	B_INT dx, dy;
1402 	dx=babs(m_link->GetEndNode()->GetX() - m_link->GetBeginNode()->GetX());
1403 	dy=babs(m_link->GetEndNode()->GetY() - m_link->GetBeginNode()->GetY());
1404 	if (dx > dy)
1405 	{	// thislink is more horizontal then vertical
1406 		if (m_link->GetEndNode()->GetX() > m_link->GetBeginNode()->GetX())
1407 			I.mergesort(NODE_X_ASCENDING_L);
1408 		else
1409 			I.mergesort(NODE_X_DESCENDING_L);
1410 	}
1411 	else
1412 	{	// this link is more vertical then horizontal
1413 		if (m_link->GetEndNode()->GetY() > m_link->GetBeginNode()->GetY())
1414 			I.mergesort(NODE_Y_ASCENDING_L);
1415 		else
1416 			I.mergesort(NODE_Y_DESCENDING_L);
1417 	}
1418 }
1419 
1420 //
1421 // Adds a cross Node to this. a_node may not be deleted before processing the crossings
1422 //
AddCrossing(Node * a_node)1423 void KBoolLine::AddCrossing(Node *a_node)
1424 {
1425 	if (a_node==m_link->GetBeginNode() || a_node==m_link->GetEndNode())	return;
1426 
1427 
1428 	if (!linecrosslist)
1429 	{
1430 		linecrosslist=new DL_List<void*>();
1431 		linecrosslist->insend(a_node);
1432 	}
1433 	else
1434 	{
1435 		TDLI<Node> I(linecrosslist);
1436 		if (!I.has(a_node))
1437 			I.insend(a_node);
1438 	}
1439 }
1440 
1441 //
1442 // see above
1443 //
AddCrossing(B_INT X,B_INT Y)1444 Node* KBoolLine::AddCrossing(B_INT X, B_INT Y)
1445 {
1446 	Node* result=new Node(X,Y, m_GC);
1447 	AddCrossing(result);
1448 	return result;
1449 }
1450 
GetCrossList()1451 DL_List<void*>* KBoolLine::GetCrossList()
1452 {
1453 	if (linecrosslist)
1454 		return linecrosslist;
1455 	return NULL;
1456 }
1457 
CrossListEmpty()1458 bool KBoolLine::CrossListEmpty()
1459 {
1460 	if (linecrosslist)
1461 		return linecrosslist->empty();
1462 	return true;
1463 }
1464 
1465 /*
1466 bool KBoolLine::HasInCrossList(Node *n)
1467 {
1468 	if(linecrosslist!=NULL)
1469 	{
1470 		TDLI<Node> I(linecrosslist);
1471 		return I.has(n);
1472 	}
1473 	return false;
1474 }
1475 */
1476 
1477