wxArt2D
liner.cpp
Go to the documentation of this file.
1 /*! \file artbase/src/liner.cpp
2  \brief Mainly used for calculating crossings
3  \author Probably Klaas Holwerda
4 
5  Copyright: 2001-2004 (C) Probably Klaas Holwerda
6 
7  Licence: wxWidgets Licence
8 
9  RCS-ID: $Id: liner.cpp,v 1.23 2009/07/06 21:06:30 titato Exp $
10 */
11 
12 #include "a2dprec.h"
13 
14 #include <math.h>
15 
16 #include <stdlib.h>
17 #include <float.h>
18 
19 #include "wx/artbase/liner.h"
20 
21 a2dLine::a2dLine( double x1, double y1, double x2, double y2 )
22 {
23  m_AA = 0.0;
24  m_BB = 0.0;
25  m_CC = 0.0;
26 
27  m_a = a2dPoint2D( x1, y1 );
28  m_b = a2dPoint2D( x2, y2 );
29 
30  m_valid_parameters = false;
32 }
33 
34 a2dLine::a2dLine( const a2dPoint2D& a, const a2dPoint2D& b )
35 {
36  m_a = a;
37  m_b = b;
38  m_valid_parameters = false;
40 }
41 
42 a2dLine::a2dLine( const a2dLine& other )
43 {
44  m_AA = other.m_AA;
45  m_BB = other.m_BB;
46  m_CC = other.m_CC;
47 
48  m_a = other.m_a;
49  m_b = other.m_b;
50  m_valid_parameters = other.m_valid_parameters;
52 }
53 
55 {}
56 
57 //! makes a a2dLine same as these
58 //! usage : a2dLine1 = a2dLine2;
60 {
61  m_AA = a_line.m_AA;
62  m_BB = a_line.m_BB;
63  m_CC = a_line.m_CC;
64 
65  m_a = a_line.m_a;
66  m_b = a_line.m_b;
67  m_valid_parameters = a_line.m_valid_parameters;
69  return *this;
70 }
71 
72 // ActionOnTable1
73 // This function decide which action must be taken, after PointInLine
74 // has given the results of two points in relation to a a2dLine. See table 1 in the report
75 //
76 // input Result_beginPoint:
77 // Result_endPoint :
78 // The results can be R_R_LEFT_SIDE, R_R_RIGHT_SIDE, R_R_ON_AREA, R_R_IN_AREA
79 //
80 // return -1: Illegal combination
81 // 0: No action, no crosspoints
82 // 1: Investigate results points in relation to the other a2dLine
83 // 2: endPoint is a crosspoint, no further investigation
84 // 3: beginPoint is a crosspoint, no further investigation
85 // 4: beginPoint and endPoint are crosspoints, no further investigation
86 // 5: beginPoint is a crosspoint, need further investigation
87 // 6: endPoint is a crosspoint, need further investigation
88 int a2dLine::ActionOnTable1( R_PointStatus Result_beginPoint, R_PointStatus Result_endPoint ) const
89 {
90  // beginPoint and endPoint are crosspoints
91  if (
92  ( Result_beginPoint == R_IN_AREA )
93  &&
94  ( Result_endPoint == R_IN_AREA )
95  )
96  return 4;
97  // there are no crosspoints, no action
98  if (
99  (
100  ( Result_beginPoint == R_LEFT_SIDE )
101  &&
102  ( Result_endPoint == R_LEFT_SIDE )
103  )
104  ||
105  (
106  ( Result_beginPoint == R_RIGHT_SIDE )
107  &&
108  ( Result_endPoint == R_RIGHT_SIDE )
109  )
110  )
111  return 0;
112  // maybe there is a crosspoint, further investigation needed
113  if (
114  (
115  ( Result_beginPoint == R_LEFT_SIDE )
116  &&
117  (
118  ( Result_endPoint == R_RIGHT_SIDE )
119  ||
120  ( Result_endPoint == R_ON_AREA )
121  )
122  )
123  ||
124  (
125  ( Result_beginPoint == R_RIGHT_SIDE )
126  &&
127  (
128  ( Result_endPoint == R_LEFT_SIDE )
129  ||
130  ( Result_endPoint == R_ON_AREA )
131  )
132  )
133  ||
134  (
135  ( Result_beginPoint == R_ON_AREA )
136  &&
137  (
138  ( Result_endPoint == R_LEFT_SIDE )
139  ||
140  ( Result_endPoint == R_RIGHT_SIDE )
141  ||
142  ( Result_endPoint == R_ON_AREA )
143  )
144  )
145  )
146  return 1;
147  //there is a crosspoint
148  if (
149  (
150  ( Result_beginPoint == R_LEFT_SIDE )
151  ||
152  ( Result_beginPoint == R_RIGHT_SIDE )
153  )
154  &&
155  ( Result_endPoint == R_IN_AREA )
156  )
157  return 2;
158  // there is a crosspoint
159  if (
160  ( Result_beginPoint == R_IN_AREA )
161  &&
162  (
163  ( Result_endPoint == R_LEFT_SIDE )
164  ||
165  ( Result_endPoint == R_RIGHT_SIDE )
166  )
167  )
168  return 3;
169  // beginPoint is a crosspoint, further investigation needed
170  if (
171  ( Result_beginPoint == R_IN_AREA )
172  &&
173  ( Result_endPoint == R_ON_AREA )
174  )
175  return 5;
176  // endPoint is a crosspoint, further investigation needed
177  if (
178  ( Result_beginPoint == R_ON_AREA )
179  &&
180  ( Result_endPoint == R_IN_AREA )
181  )
182  return 6;
183  // All other combinations are illegal
184  return -1;
185 }
186 
187 
188 // ActionOnTable2
189 // This function decide which action must be taken, after PointInLine
190 // has given the results of two points in relation to a a2dLine. It can only give a
191 // correct decision if first the relation of the points from the a2dLine
192 // are investigated in relation to the a2dLine wich can be constucted from the points.
193 //
194 // input Result_beginPoint:
195 // Result_endPoint :
196 // The results can be R_LEFT_SIDE, R_RIGHT_SIDE, R_ON_AREA, R_IN_AREA
197 //
198 // return -1: Illegal combination
199 // 0: No action, no crosspoints
200 // 1: Calculate crosspoint
201 // 2: endPoint is a crosspoint
202 // 3: beginPoint is a crosspoint
203 // 4: beginPoint and endPoint are crosspoints
204 int a2dLine::ActionOnTable2( R_PointStatus Result_beginPoint, R_PointStatus Result_endPoint ) const
205 {
206  // beginPoint and eindpoint are crosspoints
207  if (
208  ( Result_beginPoint == R_IN_AREA )
209  &&
210  ( Result_endPoint == R_IN_AREA )
211  )
212  return 4;
213  // there are no crosspoints
214  if (
215  (
216  ( Result_beginPoint == R_LEFT_SIDE )
217  &&
218  (
219  ( Result_endPoint == R_LEFT_SIDE )
220  ||
221  ( Result_endPoint == R_ON_AREA )
222  )
223  )
224  ||
225  (
226  ( Result_beginPoint == R_RIGHT_SIDE )
227  &&
228  (
229  ( Result_endPoint == R_RIGHT_SIDE )
230  ||
231  ( Result_endPoint == R_ON_AREA )
232  )
233  )
234  ||
235  (
236  ( Result_beginPoint == R_ON_AREA )
237  &&
238  (
239  ( Result_endPoint == R_LEFT_SIDE )
240  ||
241  ( Result_endPoint == R_RIGHT_SIDE )
242  ||
243  ( Result_endPoint == R_ON_AREA )
244  )
245  )
246  )
247  return 0;
248  // there is a real intersection, which must be calculated
249  if (
250  (
251  ( Result_beginPoint == R_LEFT_SIDE )
252  &&
253  ( Result_endPoint == R_RIGHT_SIDE )
254  )
255  ||
256  (
257  ( Result_beginPoint == R_RIGHT_SIDE )
258  &&
259  ( Result_endPoint == R_LEFT_SIDE )
260  )
261  )
262  return 1;
263  // endPoint is a crosspoint
264  if (
265  (
266  ( Result_beginPoint == R_LEFT_SIDE )
267  ||
268  ( Result_beginPoint == R_RIGHT_SIDE )
269  ||
270  ( Result_beginPoint == R_ON_AREA )
271  )
272  &&
273  ( Result_endPoint == R_IN_AREA )
274  )
275  return 2;
276  // beginPoint is a crosspoint
277  if (
278  ( Result_beginPoint == R_IN_AREA )
279  &&
280  (
281  ( Result_endPoint == R_LEFT_SIDE )
282  ||
283  ( Result_endPoint == R_RIGHT_SIDE )
284  ||
285  ( Result_endPoint == R_ON_AREA )
286  )
287  )
288  return 3;
289  // All other combinations are illegal
290  return -1;
291 }
292 
293 //! Calculate the Y when the X is given
294 double a2dLine::Calculate_Y( double X ) const
295 {
296  assert( m_valid_parameters );
297  if ( m_AA != 0 )
298  return -( m_AA * X + m_CC ) / m_BB;
299  else
300  // horizontal a2dLine
301  return m_a.m_y;
302 }
303 
304 void a2dLine::Virtual_Point( a2dPoint2D& a_point, double distance ) const
305 {
306  assert( m_valid_parameters );
307 
308  //calculate the distance using the slope of the a2dLine
309  //and rotate 90 degrees
310 
311  a_point.m_y = a_point.m_y + ( distance * -m_BB );
312  a_point.m_x = a_point.m_x - ( distance * m_AA );
313 }
314 
315 a2dPoint2D a2dLine::DistancePoint( double distance, bool begin ) const
316 {
317  assert( m_valid_parameters );
318  a2dPoint2D a_point;
319 
320  if ( begin )
321  {
322  a_point.m_y = m_a.m_y + ( distance * m_AA );
323  a_point.m_x = m_a.m_x + ( distance * -m_BB );
324  }
325  else
326  {
327  a_point.m_y = m_b.m_y + ( distance * m_AA );
328  a_point.m_x = m_b.m_x + ( distance * -m_BB );
329  }
330  return a_point;
331 }
332 
334 {
335  assert( m_valid_parameters );
336 
337  double distance = GetLength() * 2;
338  a2dPoint2D begin, end;
339 
340  begin.m_y = a_point.m_y + ( distance * -m_BB );
341  begin.m_x = a_point.m_x - ( distance * m_AA );
342 
343  end.m_y = a_point.m_y - ( distance * -m_BB );
344  end.m_x = a_point.m_x + ( distance * m_AA );
345 
346  return new a2dLine( begin, end );
347 }
348 
349 double a2dLine::GetLength() const
350 {
351  return sqrt( wxSqr( m_b.m_y - m_a.m_y ) + wxSqr( m_a.m_x - m_b.m_x ) );
352 }
353 
354 //! Calculate the lineparameters for the a2dLine if nessecary
356 {
357  // if not valid_parameters calculate the parameters
358  if ( !m_valid_parameters )
359  {
360  double length;
361 
362  // bp AND ep may not be the same
363  if ( m_a == m_b )
364  {
365  //assume it is a horizontal segment, but very small
366  m_AA = 0;
367  m_BB = -1e-12;
368  //assert ( 0 );
369  }
370  else
371  {
372  m_AA = ( m_b.m_y - m_a.m_y ); // A = (Y2-Y1)
373  m_BB = ( m_a.m_x - m_b.m_x ); // B = (X1-X2)
374  }
375 
376  // the parameters A end B can now be normalized
377  length = sqrt( m_AA * m_AA + m_BB * m_BB );
378 
379  assert( length != 0 );
380 
381  m_AA = ( m_AA / length );
382  m_BB = ( m_BB / length );
383 
384  m_CC = -( ( m_AA * m_a.m_x ) + ( m_a.m_y * m_BB ) );
385 
386  m_valid_parameters = true;
387  }
388 }
389 
390 
391 //! Checks if a a2dLine intersect with another a2dLine
392 /*!
393  inout a2dLine : another a2dLine
394  Marge: optional, standard on MARGE (declared in MISC.CPP)
395 
396  return true : wxLines are crossing
397  false: wxLines are not crossing
398 */
399 bool a2dLine::CheckIntersect ( a2dLine& lijn, double Marge ) const
400 {
401  double distance = 0;
402 
403  // bp AND ep may not be the same
404  if ( m_a == m_b )
405  assert ( 0 );
406 
407  int Take_Action1, Take_Action2;
408  bool Total_Result = false;
409  R_PointStatus Result_beginPoint, Result_endPoint;
410 
411  Result_beginPoint = PointInLine( lijn.m_a, distance, Marge );
412  Result_endPoint = PointInLine( lijn.m_b, distance, Marge );
413  Take_Action1 = ActionOnTable1( Result_beginPoint, Result_endPoint );
414  switch ( Take_Action1 )
415  {
416  case 0: Total_Result = false ; break;
417  case 1:
418  {
419  Result_beginPoint = lijn.PointInLine( m_a, distance, Marge );
420  Result_endPoint = lijn.PointInLine( m_b, distance, Marge );
421  Take_Action2 = ActionOnTable2( Result_beginPoint, Result_endPoint );
422  switch ( Take_Action2 )
423  {
424  case 0: Total_Result = false; break;
425  case 1: case 2: case 3: case 4: Total_Result = true; break;
426  }
427  }
428  ; break; // This break belongs to the switch(Take_Action1)
429  case 2: case 3: case 4: case 5: case 6: Total_Result = true; break;
430  }
431  return Total_Result; //This is the final decision
432 }
433 
434 
435 //! Get the beginPoint from the a2dLine
436 //! usage: Point aPoint = a_line.GetBeginPoint()
438 {
439  return m_a;
440 }
441 
442 
443 
444 //! Get the endPoint from the a2dLine
445 //! usage: Point aPoint = a_line.GetEndPoint()
447 {
448  return m_b;
449 }
450 
451 int a2dLine::Intersect( a2dLine& lijn, a2dPoint2D& c1 , a2dPoint2D& c2 , double Marge ) const
452 {
453  double distance = 0;
454 
455  // bp AND ep may not be the same
456  if ( m_a == m_b )
457  assert ( 0 );
458 
459  R_PointStatus Result_beginPoint, Result_endPoint;
460  int Take_Action1, Take_Action2, Number_of_Crossings = 0;
461 
462  Result_beginPoint = PointInLine( lijn.m_a, distance, Marge );
463  Result_endPoint = PointInLine( lijn.m_b, distance, Marge );
464 
465  Take_Action1 = ActionOnTable1( Result_beginPoint, Result_endPoint );
466 // 0: No action, no crosspoints
467 // 1: Investigate results points in relation to the other a2dLine
468 // 2: endPoint is a crosspoint, no further investigation
469 // 3: beginPoint is a crosspoint, no further investigation
470 // 4: beginPoint and endPoint are crosspoints, no further investigation
471 // 5: beginPoint is a crosspoint, need further investigation
472 // 6: endPoint is a crosspoint, need further investigation
473 
474  // The first switch will insert a crosspoint immediatly
475  switch ( Take_Action1 )
476  {
477  case 2: case 6: c1 = lijn.m_b;
478  Number_of_Crossings = 1;
479  break;
480  case 3: case 5: c1 = lijn.m_a;
481  Number_of_Crossings = 1;
482  break;
483  case 4: c1 = lijn.m_a;
484  c2 = lijn.m_b;
485  Number_of_Crossings = 2;
486  break;
487  default:
488  break;
489  }
490 
491  // This switch wil investigate the points of this a2dLine in relation to lijn
492  // 1: Investigate results points in relation to the other a2dLine
493  // 5: beginPoint is a crosspoint, need further investigation
494  // 6: endPoint is a crosspoint, need further investigation
495  switch ( Take_Action1 )
496  {
497  case 1: case 5: case 6:
498  {
499  Result_beginPoint = lijn.PointInLine( m_a, distance, Marge );
500  Result_endPoint = lijn.PointInLine( m_b, distance, Marge );
501  Take_Action2 = ActionOnTable2( Result_beginPoint, Result_endPoint );
502  // return -1: Illegal combination
503  // 0: No action, no crosspoints
504  // 1: Calculate crosspoint
505  // 2: endPoint is a crosspoint
506  // 3: beginPoint is a crosspoint
507  // 4: beginPoint and endPoint are crosspoints
508  switch ( Take_Action2 )
509  {
510  // for the cases see the returnvalue of ActionTable2
511  case 1:
512  {
513  // begin of scope to calculate the intersection
514  double X, Y, Denominator;
515  assert( m_valid_parameters );
516  Denominator = ( m_AA * lijn.m_BB ) - ( lijn.m_AA * m_BB );
517  // Denominator may not be 0
518  assert( Denominator != 0.0 );
519  // Calculate intersection of both linesegments
520  X = ( ( m_BB * lijn.m_CC ) - ( lijn.m_BB * m_CC ) ) / Denominator;
521  Y = ( ( lijn.m_AA * m_CC ) - ( m_AA * lijn.m_CC ) ) / Denominator;
522 
523  c1.m_x = X;
524  c1.m_y = Y;
525  }
526  Number_of_Crossings++;
527  break;
528  case 2: c2 = m_a;
529  Number_of_Crossings++;
530  break;
531  case 3: c2 = m_b;
532  Number_of_Crossings++;
533  break;
534  case 4: c1 = m_a;
535  c2 = m_b;
536  Number_of_Crossings = 2;
537  break;
538  }
539  };
540  break;
541  default:
542  break;
543  }
544  return Number_of_Crossings; //This is de final number of crossings
545 }
546 
547 
548 //! test if a point lies in the linesegment.
549 /*!
550 If the point isn't on the a2dLine
551 the function returns a value that indicates on which side of the
552 a2dLine the point is (in linedirection from first point to second point
553 
554  returns R_LEFT_SIDE, when point lies on the left side of the a2dLine
555  R_RIGHT_SIDE, when point lies on the right side of the a2dLine
556  R_ON_AREA, when point lies on the infinite a2dLine within a range
557  R_IN_AREA, when point lies in the area of the linesegment
558  the returnvalues are declared in (a2dLine.H)
559 */
560 R_PointStatus a2dLine::PointInLine( const a2dPoint2D& a_Point, double& Distance, double Marge ) const
561 {
562  Distance = 0;
563 
564  int Result_ofm_BBox = false;
565  R_PointStatus Result_of_Online;
566 
567  //quick test if point is begin or endpoint
568  if ( a_Point == m_a || a_Point == m_b )
569  return R_IN_AREA;
570 
571  // Handle degenerate lines
572  if( m_a == m_b )
573  {
574  if (
575  a_Point.m_x >= ( m_a.m_x - Marge ) && a_Point.m_x <= ( m_a.m_x + Marge ) &&
576  a_Point.m_y >= ( m_a.m_y - Marge ) && a_Point.m_y <= ( m_a.m_y + Marge )
577  )
578  return R_IN_AREA;
579  else
580  return R_LEFT_SIDE;
581  }
582 
583  // Checking if point is in bounding-box with marge
584  double xmin = wxMin( m_a.m_x, m_b.m_x );
585  double xmax = wxMax( m_a.m_x, m_b.m_x );
586  double ymin = wxMin( m_a.m_y, m_b.m_y );
587  double ymax = wxMax( m_a.m_y, m_b.m_y );
588 
589  if ( a_Point.m_x >= ( xmin - Marge ) && a_Point.m_x <= ( xmax + Marge ) &&
590  a_Point.m_y >= ( ymin - Marge ) && a_Point.m_y <= ( ymax + Marge ) )
591  Result_ofm_BBox = true;
592 
593  // Checking if point is on the infinite a2dLine
594  Result_of_Online = PointOnLine( a_Point, Distance, Marge );
595 
596  // point in boundingbox of the a2dLine and is on the a2dLine then the point is R_IN_AREA
597  if ( ( Result_ofm_BBox ) && ( Result_of_Online == R_ON_AREA ) )
598  return R_IN_AREA;
599  else
600  return Result_of_Online;
601 }
602 
603 
604 //! test if a point lies on the a2dLine.
605 /*!If the point isn't on the a2dLine
606  the function returns a value that indicates on which side of the
607  a2dLine the point is (in linedirection from first point to second point
608 
609  returns R_LEFT_SIDE, when point lies on the left side of the a2dLine
610  R_ON_AREA, when point lies on the infinite a2dLine within a range
611  R_RIGHT_SIDE, when point lies on the right side of the a2dLine
612  R_LEFT_SIDE , R_RIGHT_SIDE , R_ON_AREA
613 */
614 R_PointStatus a2dLine::PointOnLine( const a2dPoint2D& a_Point, double& Distance, double Marge ) const
615 {
616  Distance = 0;
617  // Point may not be queal
618  assert( m_a != m_b );
619 
620  //quick test if point is begin or endpoint
621  if ( a_Point == m_a || a_Point == m_b )
622  return R_ON_AREA;
623 
624  assert( m_valid_parameters );
625  // calculate the distance of a_Point in relation to the a2dLine
626  Distance = ( m_AA * a_Point.m_x ) + ( m_BB * a_Point.m_y ) + m_CC;
627 
628  if ( Distance < -Marge )
629  return R_LEFT_SIDE;
630  else
631  {
632  if ( Distance > Marge )
633  return R_RIGHT_SIDE;
634  else
635  return R_ON_AREA;
636  }
637 }
638 
640 {
641  double dx12 = double( m_b.m_x ) - double( m_a.m_x );
642  double dy12 = double( m_b.m_y ) - double( m_a.m_y );
643 
644  double dx1p = double( p.m_x ) - double( m_a.m_x );
645  double dy1p = double( p.m_y ) - double( m_a.m_y );
646 
647  double length = dx12 * dx12 + dy12 * dy12;
648  double projection = dx12 * dx1p + dy12 * dy1p;
649 
650  // Note: we don't want the projection length, but the projection fraction
651  // between 0..1. As projection is the projection length * length, we must devide
652  // by length^2 here
653  projection /= length;
654  return a2dPoint2D( m_a.m_x + projection * dx12, m_a.m_y + projection * dy12 );
655 }
656 
657 double a2dLine::PointDistance( const a2dPoint2D& p, a2dPoint2D* nearest ) const
658 {
659  double dx12 = double( m_b.m_x ) - double( m_a.m_x );
660  double dy12 = double( m_b.m_y ) - double( m_a.m_y );
661 
662  double dx1p = double( p.m_x ) - double( m_a.m_x );
663  double dy1p = double( p.m_y ) - double( m_a.m_y );
664 
665  double length = dx12 * dx12 + dy12 * dy12;
666  double projection = dx12 * dx1p + dy12 * dy1p;
667 
668  if( projection <= 0 || length == 0 )
669  {
670  // The point is beyond m_a
671  if( nearest ) * nearest = m_a;
672  return sqrt( dx1p * dx1p + dy1p * dy1p );
673  }
674  else if( projection >= length )
675  {
676  // The point is beyond m_b
677  if( nearest ) * nearest = m_b;
678  double dx2p = double( p.m_x ) - double( m_b.m_x );
679  double dy2p = double( p.m_y ) - double( m_b.m_y );
680  return sqrt( dx2p * dx2p + dy2p * dy2p );
681  }
682  else
683  {
684  // The point is between m_a und m_b
685 
686  // First check vertical and horizontal lines before doing sqrt and / operations
687  if( !nearest )
688  {
689  if( dx12 == 0 )
690  return fabs( dx1p );
691  if( dy12 == 0 )
692  return fabs( dy1p );
693  }
694 
695  // Note: we don't want the projection length, but the projection fraction
696  // between 0..1. As projection is the projection length * length, we must devide
697  // by length^2 here
698  projection /= length;
699  if( nearest ) * nearest = a2dPoint2D( m_a.m_x + projection * dx12, m_a.m_y + projection * dy12 );
700  // orthogonal vector from point to line
701  dx1p -= projection * dx12;
702  dy1p -= projection * dy12;
703  return sqrt( dx1p * dx1p + dy1p * dy1p );
704  }
705 }
706 
707 double a2dLine::PointDistanceOrhto( const a2dPoint2D& p, a2dPoint2D* nearest ) const
708 {
709  double dx12 = double( m_b.m_x ) - double( m_a.m_x );
710  double dy12 = double( m_b.m_y ) - double( m_a.m_y );
711 
712  double dx1p = double( p.m_x ) - double( m_a.m_x );
713  double dy1p = double( p.m_y ) - double( m_a.m_y );
714 
715  if( dx12 == 0 && dy12 == 0 )
716  {
717  if( nearest )
718  * nearest = m_a;
719  return DBL_MAX;
720  }
721  else if( fabs( dx12 ) < fabs( dy12 ) )
722  {
723  // line is more vertical => user horizontal distance
724  if( p.m_y < wxMin( m_a.m_y, m_b.m_y ) || p.m_y > wxMax( m_a.m_y, m_b.m_y ) )
725  {
726  if( nearest )
727  * nearest = p;
728  return DBL_MAX;
729  }
730  else
731  {
732  double y = p.m_y;
733  double x = dy1p * dx12 / dy12 + m_a.m_x;
734  if( nearest )
735  {
736  nearest->m_x = x;
737  nearest->m_y = y;
738  }
739  return fabs( p.m_x - x );
740  }
741  }
742  else
743  {
744  // line is more horizontal => user vertical distance
745  if( p.m_x < wxMin( m_a.m_x, m_b.m_x ) || p.m_x > wxMax( m_a.m_x, m_b.m_x ) )
746  {
747  if( nearest )
748  * nearest = p;
749  return DBL_MAX;
750  }
751  else
752  {
753  double x = p.m_x;
754  double y = dx1p * dy12 / dx12 + m_a.m_y;
755  if( nearest )
756  {
757  nearest->m_x = x;
758  nearest->m_y = y;
759  }
760  return fabs( p.m_y - y );
761  }
762  }
763 }
764 
765 void a2dLine::OffsetContour( const a2dLine& nextline, double factor, a2dPoint2D& offsetpoint ) const
766 {
767  a2dPoint2D offs_begin( m_a );
768  a2dPoint2D offs_end( m_b );
769 
770  a2dPoint2D offs_bgn_next( nextline.m_a );
771  a2dPoint2D offs_end_next( nextline.m_b );
772  // make a a2dPoint2D from this point
773 
774  Virtual_Point( offs_begin, factor );
775  Virtual_Point( offs_end, factor );
776  a2dLine offs_currentline( offs_begin, offs_end );
777 
778  nextline.Virtual_Point( offs_bgn_next, factor );
779  nextline.Virtual_Point( offs_end_next, factor );
780  a2dLine offs_nextline( offs_bgn_next, offs_end_next );
781 
782  offs_nextline.CalculateLineParameters();
783  offs_currentline.CalculateLineParameters();
784  offs_currentline.Intersect( offs_nextline, offsetpoint );
785 }
786 
787 //! Return the position of the second a2dLine compared to this a2dLine
788 /*!
789  Result = IS_ON | IS_LEFT | IS_RIGHT
790  Here Left and Right is defined as being left or right from
791  the this a2dLine towards the center (common) node
792  direction of vetors taken as begin to endpoint with end of this at
793  begin of a2dLine two
794 */
795 OUTPRODUCT a2dLine::OutProduct( const a2dLine& two, double accur ) const
796 {
797  R_PointStatus uitp;
798  double distance;
799  if ( two.m_a == two.m_b )
800  assert( 0 );
801  if ( m_a == m_b )
802  assert( 0 );
803 
804  uitp = PointOnLine( two.m_b, distance, accur );
805 
806 
807  /*double uitp= (_x - first._x) * (third._y - _y) -
808  (_y - first._y) * (third._x - _x);
809  if (uitp>0) return IS_LEFT;
810  if (uitp<0) return IS_RIGHT;
811  return IS_ON;*/
812 
813  //depending on direction of this link (going to or coming from centre)
814  if ( uitp == R_LEFT_SIDE )
815  return R_IS_LEFT;
816  if ( uitp == R_RIGHT_SIDE )
817  return R_IS_RIGHT;
818  return R_IS_ON;
819 }
820 
821 //! Intersects two lines if a crossing return true
822 //! else false
823 bool a2dLine::Intersect( a2dLine& lijn, a2dPoint2D& crossing ) const
824 {
825  // lijn must exist
826  assert( m_valid_parameters );
827  assert( lijn.m_valid_parameters );
828 
829  double X, Y, Denominator;
830  Denominator = ( m_AA * lijn.m_BB ) - ( lijn.m_AA * m_BB );
831  // Denominator may not be 0
832  if ( Denominator == 0.0 )
833  return false;
834  // Calculate intersection of both linesegments
835  X = ( ( m_BB * lijn.m_CC ) - ( lijn.m_BB * m_CC ) ) / Denominator;
836  Y = ( ( lijn.m_AA * m_CC ) - ( m_AA * lijn.m_CC ) ) / Denominator;
837 
838  crossing.m_x = X;
839  crossing.m_y = Y;
840  return true;
841 }
842 
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
Definition: artglob.h:47
a2dPoint2D DistancePoint(double distance, bool begin) const
calculate point on line at distance from the begin or end of line
Definition: liner.cpp:315
double PointDistance(const a2dPoint2D &p, a2dPoint2D *nearest) const
Calculate the distance of a point from the line. Works even if l==0.
Definition: liner.cpp:657
a2dPoint2D GetEndPoint() const
Get the endpoint from a a2dLine.
Definition: liner.cpp:446
double Calculate_Y(double X) const
Caclulate Y if X is known.
Definition: liner.cpp:294
R_PointStatus PointInLine(const a2dPoint2D &a_Point, double &Distance, double Marge) const
For a non-infinite a2dLine.
Definition: liner.cpp:560
a2dLine * CreatePerpendicularLineAt(const a2dPoint2D &a_point) const
create a line through a_point and which is pperpendicular to this
Definition: liner.cpp:333
R_PointStatus PointOnLine(const a2dPoint2D &a_Point, double &Distance, double Marge) const
For an infinite a2dLine.
Definition: liner.cpp:614
OUTPRODUCT OutProduct(const a2dLine &two, double accur) const
outproduct of two wxLines
Definition: liner.cpp:795
void Virtual_Point(a2dPoint2D &a_point, double distance) const
calculate point Perpendicula at distance from the line, through given point
Definition: liner.cpp:304
a2dLine & operator=(const a2dLine &other)
Definition: liner.cpp:59
void CalculateLineParameters()
Calculate the parameters if invalid.
Definition: liner.cpp:355
double wxSqr(double x)
good replacement for pow(x,2)
Definition: artglob.h:66
a2dPoint2D ProjectedPoint(const a2dPoint2D &p) const
return point after projecting p to this line.
Definition: liner.cpp:639
double PointDistanceOrhto(const a2dPoint2D &p, a2dPoint2D *nearest) const
Calculate the orthogonal distance of a point from the line. Works even if l==0.
Definition: liner.cpp:707
Line calculations.
Definition: liner.h:36
a2dPoint2D GetBeginPoint() const
Get the beginpoint from a a2dLine.
Definition: liner.cpp:437
void OffsetContour(const a2dLine &nextline, double factor, a2dPoint2D &offsetpoint) const
Calculate point for a contour at a given distance.
Definition: liner.cpp:765
double GetLength() const
return length of vector
Definition: liner.cpp:349
~a2dLine()
destructor
Definition: liner.cpp:54
bool CheckIntersect(a2dLine &line, double Marge) const
Check if two wxLines intersects.
Definition: liner.cpp:399
a2dLine(double x1=0, double y1=0, double x2=0, double y2=0)
create a line with given end and begin point
Definition: liner.cpp:21
basic 2 point line class for intersection and contouring routines.
int Intersect(a2dLine &line, a2dPoint2D &bp, a2dPoint2D &ep, double Marge) const
Intersects two wxLines.
Definition: liner.cpp:451
liner.cpp Source File -- Sun Oct 12 2014 17:04:22 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation