3 Purpose Mainly used for calculating crossings
8 #pragma implementation "liner.cpp"
15 #include "wx/canvas/liner.h"
17 wxLine::wxLine( double x1
, double y1
, double x2
, double y2
)
23 m_a
=wxPoint2DDouble(x1
,y1
);
24 m_b
=wxPoint2DDouble(x2
,y2
);
28 m_valid_parameters
= FALSE
;
35 wxLine::wxLine(const wxPoint2DDouble
& a
,const wxPoint2DDouble
& b
)
42 m_valid_parameters
= FALSE
;
48 // This function decide which action must be taken, after PointInLine
49 // has given the results of two points in relation to a wxLine. See table 1 in the report
51 // input Result_beginPoint:
53 // The results can be R_R_LEFT_SIDE, R_R_RIGHT_SIDE, R_R_ON_AREA, R_R_IN_AREA
55 // return -1: Illegal combination
56 // 0: No action, no crosspoints
57 // 1: Investigate results points in relation to the other wxLine
58 // 2: endPoint is a crosspoint, no further investigation
59 // 3: beginPoint is a crosspoint, no further investigation
60 // 4: beginPoint and endPoint are crosspoints, no further investigation
61 // 5: beginPoint is a crosspoint, need further investigation
62 // 6: endPoint is a crosspoint, need further investigation
63 int wxLine::ActionOnTable1(R_PointStatus Result_beginPoint
, R_PointStatus Result_endPoint
)
65 // beginPoint and endPoint are crosspoints
67 (Result_beginPoint
== R_IN_AREA
)
69 (Result_endPoint
== R_IN_AREA
)
72 // there are no crosspoints, no action
75 (Result_beginPoint
== R_LEFT_SIDE
)
77 (Result_endPoint
== R_LEFT_SIDE
)
81 (Result_beginPoint
== R_RIGHT_SIDE
)
83 (Result_endPoint
== R_RIGHT_SIDE
)
87 // maybe there is a crosspoint, further investigation needed
90 (Result_beginPoint
== R_LEFT_SIDE
)
93 (Result_endPoint
== R_RIGHT_SIDE
)
95 (Result_endPoint
== R_ON_AREA
)
100 (Result_beginPoint
== R_RIGHT_SIDE
)
103 (Result_endPoint
== R_LEFT_SIDE
)
105 (Result_endPoint
== R_ON_AREA
)
110 (Result_beginPoint
== R_ON_AREA
)
113 (Result_endPoint
== R_LEFT_SIDE
)
115 (Result_endPoint
== R_RIGHT_SIDE
)
117 (Result_endPoint
== R_ON_AREA
)
122 //there is a crosspoint
125 (Result_beginPoint
== R_LEFT_SIDE
)
127 (Result_beginPoint
== R_RIGHT_SIDE
)
130 (Result_endPoint
== R_IN_AREA
)
133 // there is a crosspoint
135 (Result_beginPoint
== R_IN_AREA
)
138 (Result_endPoint
== R_LEFT_SIDE
)
140 (Result_endPoint
== R_RIGHT_SIDE
)
144 // beginPoint is a crosspoint, further investigation needed
146 (Result_beginPoint
== R_IN_AREA
)
148 (Result_endPoint
== R_ON_AREA
)
151 // endPoint is a crosspoint, further investigation needed
153 (Result_beginPoint
== R_ON_AREA
)
155 (Result_endPoint
== R_IN_AREA
)
158 // All other combinations are illegal
164 // This function decide which action must be taken, after PointInLine
165 // has given the results of two points in relation to a wxLine. It can only give a
166 // correct decision if first the relation of the points from the wxLine
167 // are investigated in relation to the wxLine wich can be constucted from the points.
169 // input Result_beginPoint:
171 // The results can be R_LEFT_SIDE, R_RIGHT_SIDE, R_ON_AREA, R_IN_AREA
173 // return -1: Illegal combination
174 // 0: No action, no crosspoints
175 // 1: Calculate crosspoint
176 // 2: endPoint is a crosspoint
177 // 3: beginPoint is a crosspoint
178 // 4: beginPoint and endPoint are crosspoints
179 int wxLine::ActionOnTable2(R_PointStatus Result_beginPoint
, R_PointStatus Result_endPoint
)
181 // beginPoint and eindpoint are crosspoints
183 (Result_beginPoint
== R_IN_AREA
)
185 (Result_endPoint
== R_IN_AREA
)
188 // there are no crosspoints
191 (Result_beginPoint
== R_LEFT_SIDE
)
194 (Result_endPoint
== R_LEFT_SIDE
)
196 (Result_endPoint
== R_ON_AREA
)
201 (Result_beginPoint
== R_RIGHT_SIDE
)
204 (Result_endPoint
== R_RIGHT_SIDE
)
206 (Result_endPoint
== R_ON_AREA
)
211 (Result_beginPoint
== R_ON_AREA
)
214 (Result_endPoint
== R_LEFT_SIDE
)
216 (Result_endPoint
== R_RIGHT_SIDE
)
218 (Result_endPoint
== R_ON_AREA
)
223 // there is a real intersection, which must be calculated
226 (Result_beginPoint
== R_LEFT_SIDE
)
228 (Result_endPoint
== R_RIGHT_SIDE
)
232 (Result_beginPoint
== R_RIGHT_SIDE
)
234 (Result_endPoint
== R_LEFT_SIDE
)
238 // endPoint is a crosspoint
241 (Result_beginPoint
== R_LEFT_SIDE
)
243 (Result_beginPoint
== R_RIGHT_SIDE
)
245 (Result_beginPoint
== R_ON_AREA
)
248 (Result_endPoint
== R_IN_AREA
)
251 // beginPoint is a crosspoint
253 (Result_beginPoint
== R_IN_AREA
)
256 (Result_endPoint
== R_LEFT_SIDE
)
258 (Result_endPoint
== R_RIGHT_SIDE
)
260 (Result_endPoint
== R_ON_AREA
)
264 // All other combinations are illegal
268 // Calculate the Y when the X is given
269 double wxLine::Calculate_Y(double X
)
271 CalculateLineParameters();
273 return -(m_AA
* X
+ m_CC
) / m_BB
;
279 void wxLine::Virtual_Point(wxPoint2DDouble
& a_point
,double distance
) const
281 assert(m_valid_parameters
);
283 //calculate the distance using the slope of the wxLine
284 //and rotate 90 degrees
286 a_point
.m_y
=a_point
.m_y
+ (distance
* -m_BB
);
287 a_point
.m_x
=a_point
.m_x
- (distance
* m_AA
);
293 // Calculate the lineparameters for the wxLine if nessecary
295 void wxLine::CalculateLineParameters()
297 // if not valid_parameters calculate the parameters
298 if (!m_valid_parameters
)
302 // bp AND ep may not be the same
306 m_AA
= (m_b
.m_y
- m_a
.m_y
); // A = (Y2-Y1)
307 m_BB
= (m_a
.m_x
- m_b
.m_x
); // B = (X1-X2)
309 // the parameters A end B can now be normalized
310 length
= sqrt(m_AA
*m_AA
+ m_BB
*m_BB
);
314 m_AA
= (m_AA
/ length
);
315 m_BB
= (m_BB
/ length
);
317 m_CC
= -((m_AA
* m_a
.m_x
) + (m_a
.m_y
* m_BB
));
319 m_valid_parameters
= TRUE
;
324 // Checks if a wxLine intersect with another wxLine
325 // inout wxLine : another wxLine
326 // Marge: optional, standard on MARGE (declared in MISC.CPP)
328 // return true : wxLines are crossing
329 // false: wxLines are not crossing
331 bool wxLine::CheckIntersect (wxLine
& lijn
, double Marge
)
335 // bp AND ep may not be the same
339 int Take_Action1
, Take_Action2
;
340 bool Total_Result
=FALSE
;
341 R_PointStatus Result_beginPoint
,Result_endPoint
;
343 Result_beginPoint
= PointInLine(lijn
.m_a
,distance
,Marge
);
344 Result_endPoint
= PointInLine(lijn
.m_b
,distance
,Marge
);
345 Take_Action1
= ActionOnTable1(Result_beginPoint
,Result_endPoint
);
346 switch (Take_Action1
)
348 case 0: Total_Result
= FALSE
; break;
350 Result_beginPoint
= lijn
.PointInLine(m_a
,distance
,Marge
);
351 Result_endPoint
= lijn
.PointInLine(m_b
,distance
,Marge
);
352 Take_Action2
= ActionOnTable2(Result_beginPoint
,Result_endPoint
);
353 switch (Take_Action2
)
355 case 0: Total_Result
= FALSE
; break;
356 case 1: case 2: case 3: case 4: Total_Result
= TRUE
; break;
358 }; break; // This break belongs to the switch(Take_Action1)
359 case 2: case 3: case 4: case 5: case 6: Total_Result
= TRUE
; break;
361 return Total_Result
; //This is the final decision
366 // Get the beginPoint from the wxLine
367 // usage: Point aPoint = a_line.GetBeginPoint()
369 wxPoint2DDouble
wxLine::GetBeginPoint()
376 // Get the endPoint from the wxLine
377 // usage: Point aPoint = a_line.GetEndPoint()
379 wxPoint2DDouble
wxLine::GetEndPoint()
384 // Intersects two wxLines
385 // input wxLine : another wxLine
386 // Marge: optional, standard on MARGE
388 // return 0: If there are no crossings
389 // 1: If there is one crossing
390 // 2: If there are two crossings
391 int wxLine::Intersect(wxLine
& lijn
, wxPoint2DDouble
& c1
,wxPoint2DDouble
& c2
, double Marge
)
395 // bp AND ep may not be the same
399 R_PointStatus Result_beginPoint
,Result_endPoint
;
400 int Take_Action1
, Take_Action2
, Number_of_Crossings
= 0;
402 Result_beginPoint
= PointInLine(lijn
.m_a
,distance
,Marge
);
403 Result_endPoint
= PointInLine(lijn
.m_b
,distance
,Marge
);
405 Take_Action1
= ActionOnTable1(Result_beginPoint
,Result_endPoint
);
406 // 0: No action, no crosspoints
407 // 1: Investigate results points in relation to the other wxLine
408 // 2: endPoint is a crosspoint, no further investigation
409 // 3: beginPoint is a crosspoint, no further investigation
410 // 4: beginPoint and endPoint are crosspoints, no further investigation
411 // 5: beginPoint is a crosspoint, need further investigation
412 // 6: endPoint is a crosspoint, need further investigation
414 // The first switch will insert a crosspoint immediatly
415 switch (Take_Action1
)
417 case 2: case 6: c1
=lijn
.m_b
;
418 Number_of_Crossings
= 1;
420 case 3: case 5: c1
=lijn
.m_a
;
421 Number_of_Crossings
= 1;
425 Number_of_Crossings
= 2;
431 // This switch wil investigate the points of this wxLine in relation to lijn
432 // 1: Investigate results points in relation to the other wxLine
433 // 5: beginPoint is a crosspoint, need further investigation
434 // 6: endPoint is a crosspoint, need further investigation
435 switch (Take_Action1
)
437 case 1: case 5: case 6:
439 Result_beginPoint
= lijn
.PointInLine(m_a
,distance
,Marge
);
440 Result_endPoint
= lijn
.PointInLine(m_b
,distance
,Marge
);
441 Take_Action2
= ActionOnTable2(Result_beginPoint
,Result_endPoint
);
442 // return -1: Illegal combination
443 // 0: No action, no crosspoints
444 // 1: Calculate crosspoint
445 // 2: endPoint is a crosspoint
446 // 3: beginPoint is a crosspoint
447 // 4: beginPoint and endPoint are crosspoints
448 switch (Take_Action2
)
450 // for the cases see the returnvalue of ActionTable2
451 case 1: { // begin of scope to calculate the intersection
452 double X
, Y
, Denominator
;
453 CalculateLineParameters();
454 Denominator
= (m_AA
* lijn
.m_BB
) - (lijn
.m_AA
* m_BB
);
455 // Denominator may not be 0
456 assert(Denominator
!= 0.0);
457 // Calculate intersection of both linesegments
458 X
= ((m_BB
* lijn
.m_CC
) - (lijn
.m_BB
* m_CC
)) / Denominator
;
459 Y
= ((lijn
.m_AA
* m_CC
) - (m_AA
* lijn
.m_CC
)) / Denominator
;
464 Number_of_Crossings
++;
467 Number_of_Crossings
++;
470 Number_of_Crossings
++;
474 Number_of_Crossings
= 2;
482 return Number_of_Crossings
; //This is de final number of crossings
486 // test if a point lies in the linesegment. If the point isn't on the wxLine
487 // the function returns a value that indicates on which side of the
488 // wxLine the point is (in linedirection from first point to second point
490 // returns R_LEFT_SIDE, when point lies on the left side of the wxLine
491 // R_RIGHT_SIDE, when point lies on the right side of the wxLine
492 // R_ON_AREA, when point lies on the infinite wxLine within a range
493 // R_IN_AREA, when point lies in the area of the linesegment
494 // the returnvalues are declared in (wxLine.H)
495 R_PointStatus
wxLine::PointInLine(const wxPoint2DDouble
& a_Point
, double& Distance
,double Marge
)
499 // Point may not be the same
502 int Result_ofm_BBox
=FALSE
;
503 R_PointStatus Result_of_Online
;
505 //quick test if point is begin or endpoint
506 if (a_Point
== m_a
|| a_Point
== m_b
)
509 // Checking if point is in bounding-box with marge
510 double xmin
=wxMin(m_a
.m_x
,m_b
.m_x
);
511 double xmax
=wxMax(m_a
.m_x
,m_b
.m_x
);
512 double ymin
=wxMin(m_a
.m_y
,m_b
.m_y
);
513 double ymax
=wxMax(m_a
.m_y
,m_b
.m_y
);
515 if ( a_Point
.m_x
>= (xmin
- Marge
) && a_Point
.m_x
<= (xmax
+ Marge
) &&
516 a_Point
.m_y
>= (ymin
- Marge
) && a_Point
.m_y
<= (ymax
+ Marge
) )
517 Result_ofm_BBox
=TRUE
;
519 // Checking if point is on the infinite wxLine
520 Result_of_Online
= PointOnLine(a_Point
, Distance
, Marge
);
522 // point in boundingbox of the wxLine and is on the wxLine then the point is R_IN_AREA
523 if ((Result_ofm_BBox
) && (Result_of_Online
== R_ON_AREA
))
526 return Result_of_Online
;
531 // test if a point lies on the wxLine. If the point isn't on the wxLine
532 // the function returns a value that indicates on which side of the
533 // wxLine the point is (in linedirection from first point to second point
535 // returns R_LEFT_SIDE, when point lies on the left side of the wxLine
536 // R_ON_AREA, when point lies on the infinite wxLine within a range
537 // R_RIGHT_SIDE, when point lies on the right side of the wxLine
538 // R_LEFT_SIDE , R_RIGHT_SIDE , R_ON_AREA
539 R_PointStatus
wxLine::PointOnLine(const wxPoint2DDouble
& a_Point
, double& Distance
, double Marge
)
542 // Point may not be queal
545 //quick test if point is begin or endpoint
546 if (a_Point
== m_a
|| a_Point
== m_b
)
549 CalculateLineParameters();
550 // calculate the distance of a_Point in relation to the wxLine
551 Distance
= (m_AA
* a_Point
.m_x
)+(m_BB
* a_Point
.m_y
) + m_CC
;
553 if (Distance
< -Marge
)
557 if (Distance
> Marge
)
564 // makes a wxLine same as these
565 // usage : wxLine1 = wxLine2;
566 wxLine
& wxLine::operator=(const wxLine
& a_line
)
574 m_valid_parameters
= a_line
.m_valid_parameters
;
578 void wxLine::OffsetContour(const wxLine
& nextline
,double factor
,wxPoint2DDouble
& offsetpoint
) const
580 wxPoint2DDouble
offs_begin(m_a
);
581 wxPoint2DDouble
offs_end(m_b
);
583 wxPoint2DDouble
offs_bgn_next(nextline
.m_a
);
584 wxPoint2DDouble
offs_end_next(nextline
.m_b
);
585 // make a wxPoint2DDouble from this point
587 Virtual_Point(offs_begin
,factor
);
588 Virtual_Point(offs_end
,factor
);
589 wxLine
offs_currentline(offs_begin
,offs_end
);
591 nextline
.Virtual_Point(offs_bgn_next
,factor
);
592 nextline
.Virtual_Point(offs_end_next
,factor
);
593 wxLine
offs_nextline(offs_bgn_next
, offs_end_next
);
595 offs_nextline
.CalculateLineParameters();
596 offs_currentline
.CalculateLineParameters();
597 offs_currentline
.Intersect(offs_nextline
,offsetpoint
);
600 // Return the position of the second wxLine compared to this wxLine
601 // Result = IS_ON | IS_LEFT | IS_RIGHT
602 // Here Left and Right is defined as being left or right from
603 // the this wxLine towards the center (common) node
604 // direction of vetors taken as begin to endpoint with end of this at
605 // begin of wxLine two
606 OUTPRODUCT
wxLine::OutProduct(const wxLine
& two
,double accur
)
610 if (two
.m_a
==two
.m_b
)
615 uitp
=PointOnLine(two
.m_b
, distance
, accur
);
618 /*double uitp= (_x - first._x) * (third._y - _y) -
619 (_y - first._y) * (third._x - _x);
620 if (uitp>0) return IS_LEFT;
621 if (uitp<0) return IS_RIGHT;
624 //depending on direction of this link (going to or coming from centre)
625 if (uitp
==R_LEFT_SIDE
)
627 if (uitp
==R_RIGHT_SIDE
)
632 // Intersects two lines if a crossing return TRUE
634 bool wxLine::Intersect(wxLine
& lijn
,wxPoint2DDouble
& crossing
)
637 assert(m_valid_parameters
);
638 assert(lijn
.m_valid_parameters
);
640 double X
, Y
, Denominator
;
641 Denominator
= (m_AA
* lijn
.m_BB
) - (lijn
.m_AA
* m_BB
);
642 // Denominator may not be 0
643 if (Denominator
== 0.0)
645 // Calculate intersection of both linesegments
646 X
= ((m_BB
* lijn
.m_CC
) - (lijn
.m_BB
* m_CC
)) / Denominator
;
647 Y
= ((lijn
.m_AA
* m_CC
) - (m_AA
* lijn
.m_CC
)) / Denominator
;