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 intersection, 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