wxArt2D
restrict.cpp
Go to the documentation of this file.
1 /*! \file canvas/src/restrict.cpp
2  \author Michael S�trop
3  \date Created 10/27/2003
4  Copyright: 2003-2004 (c) Michael S�trop
5 
6 
7  Licence: wxWidgets Licence
8 
9  RCS-ID: $Id: restrict.cpp,v 1.39 2008/07/30 21:54:00 titato Exp $
10 */
11 
12 #include "a2dprec.h"
13 
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17 
18 #ifndef WX_PRECOMP
19 #include "wx/wx.h"
20 #endif
21 
22 #include <float.h>
23 #include "wx/artbase/afmatrix.h"
24 #include "wx/general/gen.h"
25 #include "wx/canvas/restrict.h"
26 #include "wx/canvas/canobj.h"
27 #include "wx/canvas/objlist.h"
28 #include "wx/canvas/drawer.h"
29 #include "wx/artbase/drawer2d.h"
30 
31 static inline double sqr( double val ) {return val * val;}
32 
33 #if 0
34 //EW: remains of something, or to be used in the future?
35 static int CmprDbl( double* val1, double* val2 )
36 {
37  if( *val1 < *val2 )
38  return -1;
39  else if( *val1 > *val2 )
40  return 1;
41  else
42  return 0;
43 }
44 #endif
45 
46 a2dPropertyIdUint32* a2dRestrictionEngine::PROPID_SnapSourceFeaturesMem;
47 a2dPropertyIdUint32* a2dRestrictionEngine::PROPID_SnapSourceFeatures;
48 a2dPropertyIdUint32* a2dRestrictionEngine::PROPID_SnapTargetFeatures;
49 a2dPropertyIdDouble* a2dRestrictionEngine::PROPID_RotationAngle;
50 a2dPropertyIdUint32* a2dRestrictionEngine::PROPID_RotationRationalNom;
51 a2dPropertyIdUint32* a2dRestrictionEngine::PROPID_RotationRationalDen;
52 a2dPropertyIdInt32* a2dRestrictionEngine::PROPID_SnapThresHold;
53 a2dPropertyIdPoint2D* a2dRestrictionEngine::PROPID_PointToSnap;
54 a2dPropertyIdPoint2D* a2dRestrictionEngine::PROPID_PointToRestrictTo;
55 a2dPropertyIdBool* a2dRestrictionEngine::PROPID_SnapOnlyVisbleObjects;
56 a2dPropertyIdBool* a2dRestrictionEngine::PROPID_Snap;
57 a2dPropertyIdBool* a2dRestrictionEngine::PROPID_SnapGetSet;
58 a2dPropertyIdBool* a2dRestrictionEngine::PROPID_AltDown;
59 a2dPropertyIdBool* a2dRestrictionEngine::PROPID_ShiftDown;
60 
61 INITIALIZE_PROPERTIES( a2dRestrictionEngine, a2dObject )
62 {
63  A2D_PROPID_GS( a2dPropertyIdBool, a2dRestrictionEngine, SnapGetSet, false, GetSnap, SetSnap );
64  A2D_PROPID_GSI( a2dPropertyIdUint32, a2dRestrictionEngine, SnapSourceFeatures, 0 );
65  A2D_PROPID_GSI( a2dPropertyIdUint32, a2dRestrictionEngine, SnapTargetFeatures, 0 );
67  A2D_PROPID_M( a2dPropertyIdUint32, a2dRestrictionEngine, RotationRationalNom, 0, m_rotationRationalNom );
68  A2D_PROPID_M( a2dPropertyIdUint32, a2dRestrictionEngine, RotationRationalDen, 0, m_rotationRationalDen );
69  A2D_PROPID_M( a2dPropertyIdInt32, a2dRestrictionEngine, SnapThresHold, 0, m_snapThresHold );
70  A2D_PROPID_M( a2dPropertyIdPoint2D, a2dRestrictionEngine, PointToSnap, a2dPoint2D( 0, 0 ), m_pointToSnap );
71  A2D_PROPID_M( a2dPropertyIdPoint2D, a2dRestrictionEngine, PointToRestrictTo, a2dPoint2D( 0, 0 ), m_pointToRestrictTo );
72  A2D_PROPID_M( a2dPropertyIdBool, a2dRestrictionEngine, SnapOnlyVisbleObjects, false, m_snapOnlyVisbleObjects );
73  A2D_PROPID_M( a2dPropertyIdBool, a2dRestrictionEngine, Snap, false, m_snap );
74  A2D_PROPID_M( a2dPropertyIdBool, a2dRestrictionEngine, AltDown, false, m_releaseSnap );
75  A2D_PROPID_M( a2dPropertyIdBool, a2dRestrictionEngine, ShiftDown, false, m_shiftDown );
76  A2D_PROPID_M( a2dPropertyIdUint32, a2dRestrictionEngine, SnapSourceFeaturesMem, 0, m_snapSourceFeatures );
77  return true;
78 }
79 
80 const a2dSignal a2dRestrictionEngine::sig_changed = wxNewId();
81 
82 BEGIN_EVENT_TABLE( a2dRestrictionEngine, a2dObject )
83 END_EVENT_TABLE()
84 
85 void a2dRestrictionEngine::SignalChange()
86 {
87  a2dComEvent changed( this, sig_changed );
88  ProcessEvent( changed );
89 }
90 
92 {
94  {
96  }
97  return 0;
98 }
99 
100 void a2dRestrictionEngine::SetInternal()
101 {
102  m_docSnapDistX = m_snapDistX;
103  m_docSnapDistY = m_snapDistY;
104  m_docOriginX = m_originX;
105  m_docOriginY = m_originY;
107  {
109  m_docSnapDistX /= drawing->GetUnitsScale();
110  m_docSnapDistY /= drawing->GetUnitsScale();
111  m_docOriginX /= drawing->GetUnitsScale();
112  m_docOriginY /= drawing->GetUnitsScale();
113  }
114 }
115 
117  : m_lineToSnap( 0, 0, 1, 1 )
118 {
119  m_snapDistX = 1.0;
120  m_snapDistY = 1.0;
121  m_originX = 0.0;
122  m_originY = 0.0;
123  m_rotationAngle = 10;
124  m_rotationRationalNom = 0x0000003f; // set first 6 bits allow 0..5
125  m_rotationRationalDen = 0x00000024; // set bits 3 and 6 allow n/2 and n/5
126  m_angleList = 0;
127  m_nAngleList = 0;
128 
129  m_snapThresHold = 6;
130 
132 
133  m_snapTargetFeatures = snapToGridPos | snapToObjectPos | snapToPinsUnconnected | snapToObjectVertexes;
134 
135  //m_snapTargetFeatures = snapToGridPos | snapToObjectPos | snapToPinsUnconnected | snapToObjectVertexes | snapToPointAngleMod;
137 
138  m_snap = true;
139  m_releaseSnap = false;
140  m_shiftDown = false;
142 
143  SetInternal();
144 
145  //PROPID_SnapGetSet->SetPropertyToObject( this, true );
146  //bool val = PROPID_SnapGetSet->GetPropertyValue( this );
147 
148  //PROPID_SnapSourceFeaturesMem->SetPropertyToObject( this, snapToBoundingBox );
149  //wxUint32 mask = PROPID_SnapSourceFeaturesMem.GetPropertyValue( this );
150 }
151 
153 {
154  if( m_angleList )
155  delete [] m_angleList;
156 }
157 
158 /* !!!! not used
159 static double mod1(double x)
160 {
161  return x-floor(x);
162 }
163 */
164 
165 /* !!!! not used
166 static bool IsOddMultiple(double val, double grid)
167 {
168  // If val is an odd multiple of grid, mod is 0
169  double mod=mod1(val/(2*grid))-0.5;
170 
171  return fabs(mod)<1e-10*fabs(val);
172 }
173 */
174 
175 /*! If the distance between val and the closest grid point,
176  * as sepcified by grid and origin,
177  * is smaller than *best, *best is set to this distance
178  */
179 static void SnapIfBetterPos( double val, double grid, double origin, double* best )
180 {
181  assert( grid );
182  double
183  newVal = floor( ( val - origin ) / grid + 0.5 ) * grid + origin,
184  dist = newVal - val;
185  if( fabs( dist ) < fabs( *best ) )
186  {
187  *best = dist;
188  }
189 }
190 
191 /*! If the distance between oldval and newval
192  * is smaller than *best, *best is set to this distance
193  */
194 static void SnapIfBetterSize( double oldVal, double newVal, double* best )
195 {
196  double
197  dist = newVal - oldVal;
198  if( fabs( dist ) < fabs( *best ) )
199  {
200  *best = dist;
201  }
202 }
203 
204 /*! return the closest grid point of val
205  */
206 static double SnapGrid( double val, double grid )
207 {
208  assert( grid );
209  return floor( ( val ) / grid + 0.5 ) * grid;
210 }
211 
213 {
214  m_snappedPoint = p;
215 }
216 
218 {
219  double dx = p.m_x - m_pointToSnap.m_x;
220  double dy = p.m_y - m_pointToSnap.m_y;
221 
222  double thres = GetSnapThresHoldWorld();
223 
224  return ( fabs( dx ) < thres && fabs( dy ) < thres );
225 }
226 
227 bool a2dRestrictionEngine::RestrictPoint( double& x, double& y, wxUint32 sourceRequired, bool ignoreEngine )
228 {
229  SetInternal();
230  a2dCanvasObject* parentObject = m_parentObject;
231  if ( !m_parentObject )
233 
234  bool res = false;
235  if ( !m_snap || m_releaseSnap )
236  return res;
237 
238  if ( !ignoreEngine )
239  sourceRequired = sourceRequired & m_snapTargetFeatures;
240 
241  m_pointToSnap = a2dPoint2D( x, y );
242  //FAR AWAY
243  SetPointSnapResult( a2dPoint2D( DBL_MAX, DBL_MAX ) );
244 
245  double thresWorld = GetSnapThresHoldWorld();
246 
247  // for object find the clossest snap vertex in a neighbour objects and snap to that
248  if ( sourceRequired & snapToPins ||
249  sourceRequired & snapToPinsUnconnected ||
250  sourceRequired & snapToObjectPos ||
251  sourceRequired & snapToObjectVertexes ||
252  sourceRequired & snapToObjectSegmentsMiddle ||
253  sourceRequired & snapToObjectSegments ||
254  sourceRequired & snapToObjectIntersection
255  )
256  {
257  //iterate over objects in document as seen from the showObject in a a2dCanvasView,
258  //and snap to vertexes returned from the snap vector path in those objects.
259  a2dCanvasObjectList::iterator iter = parentObject->GetChildObjectList()->begin();
260  while( iter != parentObject->GetChildObjectList()->end() )
261  {
262  a2dCanvasObjectList::value_type objchild = *iter;
263  if ( !objchild->GetRelease() &&
264  objchild->GetSnapTo() &&
265  ( !m_snapOnlyVisbleObjects || objchild->GetVisible() ) //todo &&
266  //( !a2dCanvasGlobals->GetActiveDrawingPart()->GetLayerRenderArray()[ objchild->GetLayer() ].DoRenderLayer() )
267  )
268  {
269  if ( objchild->GetBbox().PointInBox( x, y, thresWorld ) )
270  {
271  // m_pointToSnap is restricted ( e.g. the clossest points is returned in m_snappedPoint )
273  if ( objchild->RestrictToObject( ic, m_pointToSnap, m_snappedPoint, sourceRequired, thresWorld ) )
274  {
275  // RESULT IN m_snappedPoint
276  // the end result of the x,y snapped
277  x = m_snappedPoint.m_x;
278  y = m_snappedPoint.m_y;
279  //wxLogDebug( "res %f %f", x, y );
280  res = true;
281  }
282  }
283  }
284  iter++;
285  }
286  if ( res )
287  return res;
288  }
289 
290 
291  if ( sourceRequired & snapToPointAngleMod && !m_shiftDown )
292  {
293  double rad2deg = 180 / wxPI;
294  double dx = x - m_pointToRestrictTo.m_x;
295  double dy = y - m_pointToRestrictTo.m_y;
296  double radius = sqrt( dx * dx + dy * dy );
297 
298  double ang;
299  if ( !dx && !dy )
300  ang = 0;
301  else
302  ang = atan2( dy, dx );
303 
304  double angn = AngleRestrict( ang );
305 
306  dx = cos( angn ) * radius;
307  dy = sin( angn ) * radius;
308  x = m_pointToRestrictTo.m_x + dx;
309  y = m_pointToRestrictTo.m_y + dy;
310  return true;
311  }
312 
313  if ( sourceRequired & snapToPointAngleRational && !m_shiftDown )
314  {
315  double rad2deg = 180 / wxPI;
316  double dx = x - m_pointToRestrictTo.m_x;
317  double dy = y - m_pointToRestrictTo.m_y;
318  double radius = sqrt( dx * dx + dy * dy );
319 
320  double ang;
321  if ( !dx && !dy )
322  ang = 0;
323  else
324  ang = atan2( dy, dx );
325 
326  ang = RationalRestrict( ang );
327 
328  dx = cos( ang ) * radius;
329  dy = sin( ang ) * radius;
330  x = m_pointToRestrictTo.m_x + dx;
331  y = m_pointToRestrictTo.m_y + dy;
332  return true;
333  }
334 
335  if ( sourceRequired & snapToPointPos ||
336  sourceRequired & snapToPointPosX ||
337  sourceRequired & snapToPointPosY ||
338  sourceRequired & snapToPointPosXorY ||
339  sourceRequired & snapToPointPosXorYForce ||
341  )
342  {
343  if( sourceRequired & snapToPointPos )
344  {
345  if ( fabs( x - m_pointToRestrictTo.m_x ) < thresWorld &&
346  fabs( y - m_pointToRestrictTo.m_y ) < thresWorld
347  )
348  {
349  x = m_pointToRestrictTo.m_x;
350  y = m_pointToRestrictTo.m_y;
351  res = true;
352  return res;
353  }
354  }
355  if( sourceRequired & snapToPointPosX )
356  {
357  if ( fabs( x - m_pointToRestrictTo.m_x ) < thresWorld )
358  {
359  x = m_pointToRestrictTo.m_x;
360  res = true;
361  return res;
362  }
363  }
364  if( sourceRequired & snapToPointPosY )
365  {
366  if ( fabs( y - m_pointToRestrictTo.m_y ) < thresWorld )
367  {
368  y = m_pointToRestrictTo.m_y;
369  res = true;
370  return res;
371  }
372  }
373  if( sourceRequired & snapToPointPosXorYForce || m_shiftDown )
374  {
375  if ( fabs( x - m_pointToRestrictTo.m_x ) < fabs( y - m_pointToRestrictTo.m_y ) )
376  {
377  x = m_pointToRestrictTo.m_x;
378  res = true;
379  }
380  else
381  {
382  y = m_pointToRestrictTo.m_y;
383  res = true;
384  }
385  res = true;
386  return res;
387  }
388  }
389 
390  // for m_pointToSnap find the clossest snap vertex in a neighbour object, and snap to that
391  if ( sourceRequired & snapToObjectSnapVPath )
392  {
393  double dx = DBL_MAX;
394  double dy = DBL_MAX;
395 
396  //iterate over object in document as seen from the showObject in a a2dCanvasView,
397  //and snap to vertexes returned from the snap vector path in those objects.
398  a2dCanvasObjectList::iterator iter = parentObject->GetChildObjectList()->begin();
399  while( iter != parentObject->GetChildObjectList()->end() )
400  {
401  a2dCanvasObjectList::value_type objchild = *iter;
402  if ( !objchild->GetRelease() &&
403  objchild->GetSnapTo() &&
404  ( !m_snapOnlyVisbleObjects || objchild->GetVisible() ) //todo &&
405  //( !a2dCanvasGlobals->GetActiveDrawingPart()->GetLayerRenderArray()[ objchild->GetLayer() ].DoRenderLayer() )
406  )
407  {
408  if ( objchild->GetBbox().PointInBox( x, y, thresWorld ) )
409  {
410  a2dCanvasObjectList* vectorpaths = objchild->GetSnapVpath( sourceRequired );
411  if ( vectorpaths != wxNullCanvasObjectList )
412  {
413  forEachIn( a2dCanvasObjectList, vectorpaths )
414  {
415  a2dVectorPath* obj = wxStaticCast( ( *iter ).Get(), a2dVectorPath );
416  unsigned int i;
417  for ( i = 0; i < obj->GetSegments()->size(); i++ )
418  {
419  a2dVpathSegment* seg = obj->GetSegments()->Item( i );
420  switch ( seg->GetType() )
421  {
422  case a2dPATHSEG_MOVETO:
423  case a2dPATHSEG_LINETO:
430  case a2dPATHSEG_ARCTO:
431  {
432  if ( SetPointIfCloser( m_pointToSnap, a2dPoint2D( seg->m_x1 ,seg->m_x1 ), m_snappedPoint, thresWorld ) )
433  {
434  x = seg->m_x1;
435  y = seg->m_y1;
436  res = true;
437  }
438  }
439  break;
440  }
441  }
442  }
443  delete vectorpaths;
444  }
445  }
446  }
447  iter++;
448  }
449  }
450 
451  if ( sourceRequired & snapToGridPos || sourceRequired & snapToGridPosForced )
452  {
453  double sx, sy;
454  sx = x;
455  sy = y;
456  // Restrict x-Position
457  if( sourceRequired & snapToGridPosX && m_snapDistX )
458  {
459  sx = floor( ( x - m_docOriginX ) / m_docSnapDistX + 0.5 ) * m_docSnapDistX + m_docOriginX;
460  }
461  // Restrict y-Position
462  if( sourceRequired & snapToGridPosY && m_snapDistY )
463  {
464  sy = floor( ( y - m_docOriginY ) / m_docSnapDistY + 0.5 ) * m_docSnapDistY + m_docOriginY;
465  }
466 
467  // make sure that the point can always be snapped to a grid point in this mode
468  if (sourceRequired & snapToGridPosForced )
469  thresWorld = wxMax( m_docSnapDistX*0.51, m_docSnapDistY*0.51 );
470 
471  if ( SetPointIfCloser( a2dPoint2D( sx ,sy ), m_pointToSnap, m_snappedPoint, thresWorld ) )
472  {
473  x = sx; y = sy;
474  res = true;
475  }
476  }
477  return res;
478 }
479 
480 bool a2dRestrictionEngine::RestrictLine( a2dLine& line, wxUint32 sourceRequired, bool ignoreEngine )
481 {
482  return false;
483 }
484 
485 bool a2dRestrictionEngine::RestrictAngle( double* ang, wxUint32 sourceRequired, bool ignoreEngine )
486 {
487  if ( !ignoreEngine )
488  sourceRequired = sourceRequired & m_snapTargetFeatures;
489 
490  if ( sourceRequired & snapToPointAngleMod )
491  {
492  *ang = AngleRestrict( *ang );
493  return true;
494  }
495 
496  if ( sourceRequired & snapToPointAngleRational )
497  {
498  *ang = RationalRestrict( *ang );
499  return true;
500  }
501  return false;
502 }
503 
504 static int CmprDbl( const void* val1, const void* val2 )
505 {
506  if( *( double* )val1 < * ( double* )val2 )
507  return -1;
508  else if( *( double* )val1 > *( double* )val2 )
509  return 1;
510  else
511  return 0;
512 }
513 
515 {
516  double
517  angleSnapRad = m_rotationAngle / 180 * wxPI;
518  return floor( angle / angleSnapRad + 0.5 ) * angleSnapRad;
519 }
520 
521 void a2dRestrictionEngine::AngleRestrictVectorRot( double* vecx, double* vecy )
522 {
523  double
524  angle = atan2( *vecy, *vecx ),
525  len = sqrt( sqr( *vecx ) + sqr( *vecy ) );
526  angle = AngleRestrict( angle );
527  *vecx = cos( angle ) * len;
528  *vecy = sin( angle ) * len;
529 }
530 
531 void a2dRestrictionEngine::AngleRestrictVectorSkew( double* vecx, double* vecy, double otherx, double othery )
532 {
533  double
534  angleOld = atan2( *vecy, *vecx ),
535  angleNew = AngleRestrict( angleOld ),
536  angleOther = atan2( othery, otherx ),
537  proj = *vecx * othery - *vecy * otherx;
538 
539  if( fabs( angleNew - angleOther ) < 1e-5 )
540  {
541  // If the new angle is very close to the other vectors angle
542  // the transformation will become singular.
543  // To avoid this, use the closest other snap angle
544  double
545  angleSnapRad = m_rotationAngle / 180 * wxPI,
546  angleNew1 = angleNew - angleSnapRad,
547  angleNew2 = angleNew + angleSnapRad;
548  if( fabs( angleOld - angleNew1 ) < fabs( angleOld - angleNew2 ) )
549  angleNew = angleNew1;
550  else
551  angleNew = angleNew2;
552  }
553 
554  double
555  newx = cos( angleNew ),
556  newy = sin( angleNew ),
557  newpro = newx * othery - newy * otherx;
558 
559  if( !newpro )
560  return;
561 
562  *vecx = newx * ( proj / newpro );
563  *vecy = newy * ( proj / newpro );
564 }
565 
567 {
568  // map angle to first quadrant 0..45 deg
569  int
570  quad = 0;
571  bool
572  mirr = false;
573 
574  if( angle < 0 )
575  angle += 2 * wxPI;
576 
577  if( angle > wxPI )
578  {
579  quad += 2;
580  angle -= wxPI;
581  }
582  if( angle > wxPI / 2 )
583  {
584  quad += 1;
585  angle -= wxPI / 2;
586  }
587  if( angle > wxPI / 4 )
588  {
589  mirr = true;
590  angle = wxPI / 2 - angle;
591  }
592 
593  if( !m_angleList )
594  {
595  // create the list of valid angles
596  const int
597  mAngles = 31 * 30 / 2 + 1;
598  int
599  nAngles = 0;
600  double
601  angles[mAngles];
602 
603  angles[nAngles++] = 0;
604  int i;
605  for( i = 1; i <= 31; i++ )
606  {
607  if( m_rotationRationalNom & ( 1 << i ) )
608  {
609  for( int j = i; j <= 31; j++ )
610  {
611  if( m_rotationRationalDen & ( j << i ) )
612  {
613  assert( nAngles < mAngles );
614  angles[nAngles++] = atan( double( i ) / double( j ) );
615  }
616  }
617  }
618  }
619 
620  // sort the list
621  qsort( angles, nAngles, sizeof( *angles ), CmprDbl );
622 
623  // remove multiple equal values
624  m_nAngleList = 1;
625  for( i = 1; i < nAngles; i++ )
626  {
627  if( angles[i] - angles[m_nAngleList - 1] > 1e-13 )
628  {
629  angles[m_nAngleList++] = angles[i];
630  }
631  }
632 
633  // copy the temporary list
634  m_angleList = new double[m_nAngleList];
635  memcpy( m_angleList, angles, sizeof( *m_angleList )*m_nAngleList );
636  }
637 
638  // find nearest angle in list
639  if( m_nAngleList <= 1 )
640  {
641  angle = 0;
642  }
643  else
644  {
645  int
646  low = 0,
647  high = m_nAngleList - 1,
648  mid;
649 
650  while( high - low > 1 )
651  {
652  mid = ( low + high ) >> 1;
653  if( m_angleList[mid] < angle )
654  low = mid;
655  else
656  high = mid;
657  }
658 
659  // angle is between m_angleList[low] and m_angleList[high]
660  // One of these two values must be the closest value
661  if( angle - m_angleList[low] < m_angleList[high] - angle )
662  angle = m_angleList[low];
663  else
664  angle = m_angleList[high];
665  }
666 
667  // put the angle back to its original quadrant
668  if( mirr )
669  angle = wxPI / 2 - angle;
670  angle += quad * wxPI / 2;
671 
672  return angle;
673 }
674 
675 void a2dRestrictionEngine::RationalRestrictVector( double* vecx, double* vecy )
676 {
677  double
678  angle = atan2( *vecy, *vecx ),
679  len = sqrt( sqr( *vecx ) + sqr( *vecy ) );
680  angle = RationalRestrict( angle );
681  *vecx = cos( angle ) * len;
682  *vecy = sin( angle ) * len;
683 }
684 
685 bool a2dRestrictionEngine::RestrictCanvasObjectAtVertexes( a2dCanvasObject* object, a2dPoint2D& point, double& dx, double& dy, wxUint32 sourceRequired, bool ignoreEngine )
686 {
687  bool res = false;
688  dx = DBL_MAX;
689  dy = DBL_MAX;
690 
691  if ( !m_snap || m_releaseSnap )
692  return res;
693 
694  if ( !ignoreEngine )
695  sourceRequired = sourceRequired & m_snapTargetFeatures;
696 
697  // object has enabled snap?
698  if ( object->GetSnap() )
699  {
700  a2dCanvasObjectList* vectorpaths = object->GetSnapVpath( m_snapSourceFeatures );
701  if ( vectorpaths != wxNullCanvasObjectList )
702  {
703  forEachIn( a2dCanvasObjectList, vectorpaths )
704  {
705  a2dVectorPath* obj = wxStaticCast( ( *iter ).Get(), a2dVectorPath );
706  unsigned int i;
707  for ( i = 0; i < obj->GetSegments()->size(); i++ )
708  {
709  a2dVpathSegment* seg = obj->GetSegments()->Item( i );
710  switch ( seg->GetType() )
711  {
712  case a2dPATHSEG_MOVETO:
713  case a2dPATHSEG_LINETO:
720  case a2dPATHSEG_ARCTO:
721  {
722  //point to snap
723  double x = seg->m_x1;
724  double y = seg->m_y1;
725  if ( RestrictPoint( x, y, sourceRequired, ignoreEngine ) )
726  {
727  //if closser, take it
728  if ( fabs( x - seg->m_x1 ) < fabs( dx ) && fabs( y - seg->m_y1 ) < fabs( dy ) )
729  {
730  dx = x - seg->m_x1;
731  dy = y - seg->m_y1;
732  point = a2dPoint2D( seg->m_x1, seg->m_y1 );
733  res = true;
734  }
735  }
736  }
737  break;
738  }
739  }
740  }
741  delete vectorpaths;
742  }
743  }
744  return res;
745 }
746 
747 bool a2dRestrictionEngine::RestrictVertexes( a2dVertexArray* segments, a2dPoint2D& point, double& dx, double& dy, wxUint32 sourceRequired, bool ignoreEngine )
748 {
749  dx = DBL_MAX;
750  dy = DBL_MAX;
751 
752  bool res = false;
753  int i = 0;
754  for ( i = 0; i < segments->size(); i++ )
755  {
756  a2dLineSegmentPtr seg = segments->Item( i );
757  double x = seg->m_x;
758  double y = seg->m_y;
759  if ( RestrictPoint( x, y, sourceRequired, ignoreEngine ) )
760  {
761  //if closser, take it
762  if ( fabs( x - seg->m_x ) < dx && fabs( y - seg->m_y ) < dy )
763  {
764  dx = fabs( x - seg->m_x );
765  dy = fabs( y - seg->m_y );
766  point = a2dPoint2D( seg->m_x, seg->m_y );
767  res = true;
768  }
769  }
770  }
771  return res;
772 }
773 
774 bool a2dRestrictionEngine::RestrictVertexes( a2dVertexList* lsegments, a2dPoint2D& point, double& dx, double& dy, wxUint32 sourceRequired, bool ignoreEngine )
775 {
776  dx = DBL_MAX;
777  dy = DBL_MAX;
778  bool res = false;
779 
780  int i = 0;
781  for( a2dVertexList::iterator iter = lsegments->begin(); iter != lsegments->end(); ++iter, i++ )
782  {
783  a2dLineSegment* seg = *iter;
784  double x = seg->m_x;
785  double y = seg->m_y;
786  if ( RestrictPoint( x, y, sourceRequired, ignoreEngine ) )
787  {
788  //if closser, take it
789  if ( fabs( x - seg->m_x ) < dx && fabs( y - seg->m_y ) < dy )
790  {
791  dx = fabs( x - seg->m_x );
792  dy = fabs( y - seg->m_y );
793  point = a2dPoint2D( seg->m_x, seg->m_y );
794  res = true;
795  }
796  }
797  }
798  return res;
799 }
800 
801 
802 
803 
804 
805 
806 
807 
808 
809 
810 
812 {
818  m_snapDistX = 1;
819  m_snapDistY = 1;
820  m_originX = 0;
821  m_originY = 0;
822  m_sizeX = 1;
823  m_sizeY = 1;
824  m_rotationAngle = 2;
825  m_rotationRationalNom = 0x0000003f; // allow 0..5
826  m_rotationRationalDen = 0x00000024; // allow n/2 and n/5
827  m_angleList = 0;
828  m_nAngleList = 0;
829  m_minSizeX = 1;
830  m_minSizeY = 1;
831  m_maxSizeX = DBL_MAX;
832  m_maxSizeY = DBL_MAX;
833 }
834 
836 {
837  if( m_angleList )
838  delete [] m_angleList;
839 }
840 
841 //! Relative tolerance for detecting vertical and horizontal lines
842 static const double Eps = 1e-10;
843 
844 void a2dRestrictionEngineOld::RestrictAffine( a2dAffineMatrix* mNew, const a2dAffineMatrix* mOld, ESnapWhat snapWhat, SnapObjectInfo* info, double* w, double* h )
845 {
846  // mNew->DebugDump(wxT("PreRestrict"),w ? *w : 0, h ? *h : 0);
847 
848  // If this is called with an empty restriction engine, do nothing
849  if( !this )
850  return;
851 
852  double
853  wfa = w ? fabs( *w ) : 1,
854  hfa = h ? fabs( *h ) : 1,
855  a00 = mNew->m_matrix[0][0],
856  a01 = mNew->m_matrix[0][1],
857  a10 = mNew->m_matrix[1][0],
858  a11 = mNew->m_matrix[1][1],
859  a20 = mNew->m_matrix[2][0],
860  a21 = mNew->m_matrix[2][1];
861 
862  //------------------------------------------------------------------------
863  // Calculate the fixpoints between old and new transformation
864  //------------------------------------------------------------------------
865  double
866  fixX = 0.0,
867  fixY = 0.0;
868  bool
869  hasFix = false,
870  linearZero = false,
871  shiftZero = false;
872  if( mOld )
873  {
875  diff = *mNew - *mOld;
876  double
877  maxNew = mNew->GetMaximum(),
878  maxOld = mOld->GetMaximum(),
879  maxDiff = diff.GetMaximum(),
880  detDiff = diff.GetDeterminant();
881 
882  linearZero = maxDiff <= wxMax( maxNew, maxOld ) * Eps ;
883 
884  shiftZero =
885  fabs( diff.m_matrix[2][0] ) <= wxMax( fabs( mNew->m_matrix[2][0] ), fabs( mOld->m_matrix[2][0] ) ) * Eps &&
886  fabs( diff.m_matrix[2][1] ) <= wxMax( fabs( mNew->m_matrix[2][1] ), fabs( mOld->m_matrix[2][1] ) ) * Eps ;
887 
888  if( linearZero && shiftZero )
889  {
890  // both matrices are identical => nothing to do
891  return;
892  }
893  else if( shiftZero )
894  {
895  // If the shifts are identical (differential shift 0) x=0, y=0 is a fixpoint
896  // There may be more fixpoints, but this is a good choice
897  hasFix = true;
898  }
899  else if( linearZero )
900  {
901  // diff is a zero matrix, but shift is non zero => no fixpoint
902  }
903  else if( fabs( detDiff ) < sqr( maxDiff ) * Eps )
904  {
905  // the matrix is irregular, but not zero
906  // A fixpointline exists, if D1==0 and D2==0
907  double
908  det1 = diff.GetDeterminant1(),
909  det2 = diff.GetDeterminant2(),
910  max1 = diff.GetMaximum1(),
911  max2 = diff.GetMaximum2();
912  if( fabs( det1 ) <= max1 * Eps && fabs( det2 ) <= max2 * Eps )
913  {
914  // Both transformed coordinate axis vectors are parallel to the shift vector
915  // => a fixpoint line exists
916  hasFix = true;
917 
918  // select a pivot row in the matrix
919  if( fabs( diff.m_matrix[0][0] ) + fabs( diff.m_matrix[1][0] ) > fabs( diff.m_matrix[0][1] ) + fabs( diff.m_matrix[1][1] ) )
920  {
921  // Take the first row equation a00*x + a10*y + a20 = 0
922  // select a pivot element
923  if( fabs( diff.m_matrix[0][0] ) > fabs( diff.m_matrix[1][0] ) )
924  {
925  fixX = -diff.m_matrix[2][0] / diff.m_matrix[0][0];
926  }
927  else
928  {
929  fixY = -diff.m_matrix[2][0] / diff.m_matrix[1][0];
930  }
931  }
932  else
933  {
934  // Take the second row equation a01*x + a11*y + a21 = 0
935  // select a pivot element
936  if( fabs( diff.m_matrix[0][1] ) > fabs( diff.m_matrix[1][1] ) )
937  {
938  fixX = -diff.m_matrix[2][1] / diff.m_matrix[0][1];
939  }
940  else
941  {
942  fixY = -diff.m_matrix[2][1] / diff.m_matrix[1][1];
943  }
944  }
945  }
946  // else there is no fixpoint, e.g. a shift with a perpendicular scaling
947  }
948  else
949  {
950  // the matrix is regular => there is a single fixpoint
951  fixX = - diff.GetDeterminant1() / detDiff;
952  fixY = - diff.GetDeterminant2() / detDiff;
953  hasFix = true;
954  }
955  /*
956  #ifdef _DEBUG
957  if( hasFix )
958  {
959  double
960  dxn,dyn,
961  dxo,dyo;
962 
963  mNew->TransformPoint(fixX, fixY, dxn, dyn);
964  mOld->TransformPoint(fixX, fixY, dxo, dyo);
965 
966  assert(fabs(dxn-dxo) <= Eps * wxMax(fabs(dxn),fabs(dxo)));
967  assert(fabs(dyn-dyo) <= Eps * wxMax(fabs(dyn),fabs(dyo)));
968  }
969  #endif
970  */
971  }
972 
973  //------------------------------------------------------------------------
974  // shift the affine transformation, so that the fixpoint is at 0
975  // The operations below assume, that the transformation is centered
976  //------------------------------------------------------------------------
977  if( hasFix )
978  {
979  a20 += a00 * fixX + a10 * fixY;
980  a21 += a01 * fixX + a11 * fixY;
981  }
982 
983  //------------------------------------------------------------------------
984  // restrict rotatition
985  //------------------------------------------------------------------------
986  if( ( snapWhat & snapRot ) && ( m_rotModes & info->m_rotModes ) )
987  {
988  int
989  modes = m_rotModes & info->m_rotModes;
990 
991  // Check angle rotations
992  if( m_rotationAngle )
993  {
994  if( modes & rotVectorAngleX )
995  {
996  // restrict angle of X-axis of target coordinate system
997  AngleRestrictVectorRot( &a00, &a01 );
998  }
999  if( modes & rotVectorAngleY )
1000  {
1001  // restrict angle of Y-axis of target coordinate system
1002  AngleRestrictVectorRot( &a10, &a11 );
1003  }
1004  }
1005 
1006  // Check rational rotations
1008  {
1009  if( modes & rotVectorRationalX )
1010  {
1011  // restrict angle of X-axis of target coordinate system
1012  RationalRestrictVector( &a00, &a01 );
1013  }
1014  if( modes & rotVectorRationalY )
1015  {
1016  // restrict angle of Y-axis of target coordinate system
1017  RationalRestrictVector( &a10, &a11 );
1018  }
1019  }
1020 
1021  // Restrict angle of Y-axis of target coordinate system to X-axis +/- 90 deg
1022  if( modes & rotPureRotations )
1023  {
1024  double
1025  lenY = sqrt( sqr( a11 ) + sqr( a10 ) ),
1026  lenX = sqrt( sqr( a01 ) + sqr( a00 ) );
1027  if( lenX )
1028  {
1029  if( a00* a11 - a01* a10 >= 0 )
1030  {
1031  // right handed purely rotated (and scaled) coordinate system
1032  a10 = -a01 * lenY / lenX;
1033  a11 = a11 * lenY / lenX;
1034  }
1035  else
1036  {
1037  // left handed purely rotated (and scaled) coordinate system
1038  a10 = a01 * lenY / lenX;
1039  a11 = -a00 * lenY / lenX;
1040  }
1041  }
1042  }
1043  }
1044 
1045  //------------------------------------------------------------------------
1046  // restrict skews
1047  //------------------------------------------------------------------------
1048  if( ( snapWhat & snapSkew ) && ( m_rotModes & info->m_rotModes ) )
1049  {
1050  int
1051  modes = m_rotModes & info->m_rotModes;
1052 
1053  // Check angle rotations
1054  if( m_rotationAngle )
1055  {
1056  if( modes & rotVectorAngleX )
1057  {
1058  // restrict angle of X-axis of target coordinate system
1059  AngleRestrictVectorSkew( &a00, &a01, a10, a11 );
1060  }
1061  if( modes & rotVectorAngleY )
1062  {
1063  // restrict angle of Y-axis of target coordinate system
1064  AngleRestrictVectorSkew( &a10, &a11, a00, a01 );
1065  }
1066  }
1067 
1068  // If the X-Axis is rotated, the Y-Axis must not be rotated
1069  if( modes & rotPureSlanting )
1070  {
1071 
1072  if( a01 )
1073  {
1074  double
1075  lenY = sqrt( sqr( a11 ) + sqr( a10 ) );
1076  a11 = lenY;
1077  a10 = 0;
1078  }
1079  }
1080  }
1081 
1082  //------------------------------------------------------------------------
1083  // Restrict X-size
1084  //------------------------------------------------------------------------
1085  if( ( snapWhat & snapSize ) && ( m_sizeModesX & info->m_sizeModesX ) )
1086  {
1087  // This operation scales the a00/a01 axis vector
1088  // Various snapping methods are tried, and the one best
1089  // fitting the current length is chosen.
1090  int
1091  modes = m_sizeModesX & info->m_sizeModesX;
1092  double
1093  oldLen = wfa * sqrt( sqr( a00 ) + sqr( a01 ) ),
1094  newLen = oldLen;
1095 
1096  if( ( modes & sizeMin ) && oldLen < m_minSizeX )
1097  {
1098  newLen = m_minSizeX;
1099  }
1100  else if( ( modes & sizeMax ) && oldLen > m_maxSizeX )
1101  {
1102  newLen = m_maxSizeX;
1103  }
1104  else if( m_sizeX )
1105  {
1106  double
1107  best = DBL_MAX;
1108 
1109  if( modes & sizeLength )
1110  {
1111  SnapIfBetterSize( oldLen, SnapGrid( wfa * sqrt( sqr( a00 ) + sqr( a01 ) ), m_sizeX ), &best );
1112  }
1113  if( modes & sizeProject )
1114  {
1115  // axis vector is (a00,a01)
1116  // other vector is (a10,a11);
1117  // orthogonal of other vector is (-a11,a10)
1118  double
1119  otherLen = sqrt( sqr( a10 ) + sqr( a11 ) );
1120  if( otherLen )
1121  {
1122  double
1123  prjc = wfa * ( - a00 * a11 + a01 * a10 ) / otherLen;
1124  if( prjc )
1125  {
1126  double
1127  newLen = oldLen * SnapGrid( prjc, m_sizeX ) / prjc;
1128  SnapIfBetterSize( oldLen, newLen, &best );
1129  }
1130  }
1131  }
1132  if( modes & sizeMajor )
1133  {
1134  double
1135  major = wfa * wxMax( a00, a01 );
1136  if( major )
1137  {
1138  double
1139  newLen = oldLen * SnapGrid( major, m_sizeX ) / major;
1140  SnapIfBetterSize( oldLen, newLen, &best );
1141  }
1142  }
1143  if( modes & sizeAxis )
1144  {
1145  double
1146  axis = wfa * a00;
1147  if( axis )
1148  {
1149  double
1150  newLen = oldLen * SnapGrid( axis, m_sizeX ) / axis;
1151  SnapIfBetterSize( oldLen, newLen, &best );
1152  }
1153  }
1154 
1155  if( best != DBL_MAX )
1156  {
1157  newLen = oldLen + best;
1158  if( ( modes & sizeMin ) && newLen < m_minSizeX )
1159  newLen = m_minSizeX;
1160  else if( ( modes & sizeMax ) && newLen > m_maxSizeX )
1161  newLen = m_maxSizeX;
1162  }
1163  }
1164  if( newLen != oldLen )
1165  {
1166  if( oldLen )
1167  {
1168  if( w && ( snapWhat & snapWH ) )
1169  {
1170  *w *= newLen / oldLen;
1171  }
1172  else
1173  {
1174  a00 *= newLen / oldLen;
1175  a01 *= newLen / oldLen;
1176  }
1177  }
1178  /*
1179  else {
1180  // a00/a01 vector is degenerated (0), so restore it
1181  double
1182  aLen = sqrt( sqr(a00)+sqr(a01) );
1183  if(!aLen)
1184  {
1185  double
1186  oLen = sqrt( sqr(a10)+sqr(a11) );
1187  if(oLen)
1188  {
1189  // restore perpendicular to y-vector
1190  a00=a11/oLen;
1191  a01=-a10/oLen;
1192  }
1193  else {
1194  // restore standard x vector
1195  a00=1;
1196  a01=0;
1197  }
1198  aLen=1;
1199  }
1200  if(w && (snapWhat & snapWH))
1201  {
1202  *w = newLen/aLen;
1203  }
1204  else {
1205  a00 *= newLen/aLen;
1206  a01 *= newLen/aLen;
1207  }
1208  }
1209  */
1210  }
1211  }
1212 
1213  //------------------------------------------------------------------------
1214  // Restrict Y-size
1215  //------------------------------------------------------------------------
1216  if(
1217  ( snapWhat & snapSize ) && ( m_sizeModesY & info->m_sizeModesY ) &&
1218  // If w==h, only one needs to be restricted
1219  !( ( snapWhat & snapWH ) && w && h == w )
1220 
1221  )
1222  {
1223  // This operation scales the a10/a11 axis vector
1224  // Various snapping methods are tried, and the one best
1225  // fitting the current length is chosen.
1226  int
1227  modes = m_sizeModesY & info->m_sizeModesY;
1228  double
1229  oldLen = hfa * sqrt( sqr( a10 ) + sqr( a11 ) ),
1230  newLen = oldLen;
1231 
1232  if( ( modes & sizeMin ) && oldLen < m_minSizeY )
1233  {
1234  newLen = m_minSizeY;
1235  }
1236  else if( ( modes & sizeMax ) && oldLen > m_maxSizeY )
1237  {
1238  newLen = m_maxSizeY;
1239  }
1240  else if( m_sizeY )
1241  {
1242  double
1243  best = DBL_MAX;
1244 
1245  if( modes & sizeLength )
1246  {
1247  SnapIfBetterSize( oldLen, SnapGrid( hfa * sqrt( sqr( a10 ) + sqr( a11 ) ), m_sizeY ), &best );
1248  }
1249  if( modes & sizeProject )
1250  {
1251  // axis vector is (a10,a11)
1252  // other vector is (a00,a01);
1253  // orthogonal of other vector is (-a01,a00)
1254  double
1255  otherLen = sqrt( sqr( a00 ) + sqr( a01 ) );
1256  if( otherLen )
1257  {
1258  double
1259  prjc = hfa * ( - a10 * a01 + a11 * a00 ) / otherLen;
1260  if( prjc )
1261  {
1262  double
1263  newLen = oldLen * SnapGrid( prjc, m_sizeY ) / prjc;
1264  SnapIfBetterSize( oldLen, newLen, &best );
1265  }
1266  }
1267  }
1268  if( modes & sizeMajor )
1269  {
1270  double
1271  major = hfa * wxMax( a10, a11 );
1272  if( major )
1273  {
1274  double
1275  newLen = oldLen * SnapGrid( major, m_sizeY ) / major;
1276  SnapIfBetterSize( oldLen, newLen, &best );
1277  }
1278  }
1279  if( modes & sizeAxis )
1280  {
1281  double
1282  axis = hfa * a11;
1283  if( axis )
1284  {
1285  double
1286  newLen = oldLen * SnapGrid( axis, m_sizeY ) / axis;
1287  SnapIfBetterSize( oldLen, newLen, &best );
1288  }
1289  }
1290 
1291  if( best != DBL_MAX )
1292  {
1293  newLen = oldLen + best;
1294  if( ( modes & sizeMin ) && newLen < m_minSizeY )
1295  newLen = m_minSizeY;
1296  else if( ( modes & sizeMax ) && newLen > m_maxSizeY )
1297  newLen = m_maxSizeY;
1298  }
1299  }
1300  if( newLen != oldLen )
1301  {
1302  if( oldLen )
1303  {
1304  if( h && ( snapWhat & snapWH ) )
1305  {
1306  *h *= newLen / oldLen;
1307  }
1308  else
1309  {
1310  a10 *= newLen / oldLen;
1311  a11 *= newLen / oldLen;
1312  }
1313  }
1314  /*
1315  else {
1316  // a10/a11 vector is degenerated (0), so restore it
1317  double
1318  aLen = sqrt( sqr(a10)+sqr(a11) );
1319  if(!aLen)
1320  {
1321  double
1322  oLen = sqrt( sqr(a00)+sqr(a01) );
1323  if(oLen)
1324  {
1325  // restore perpendicular to x-vector
1326  a10=-a01/oLen;
1327  a11=a00/oLen;
1328  }
1329  else {
1330  // restore standard y vector
1331  a10=0;
1332  a11=1;
1333  }
1334  aLen=1;
1335  }
1336  if(h && (snapWhat & snapWH))
1337  {
1338  *h = newLen/aLen;
1339  }
1340  else {
1341  a10 *= newLen/aLen;
1342  a11 *= newLen/aLen;
1343  }
1344  }
1345  */
1346  }
1347  }
1348 
1349  //------------------------------------------------------------------------
1350  // Shift the transformation back
1351  //------------------------------------------------------------------------
1352  if( hasFix )
1353  {
1354  a20 -= a00 * fixX + a10 * fixY;
1355  a21 -= a01 * fixX + a11 * fixY;
1356  }
1357 
1358  mNew->m_matrix[0][0] = a00;
1359  mNew->m_matrix[0][1] = a01;
1360  mNew->m_matrix[1][0] = a10;
1361  mNew->m_matrix[1][1] = a11;
1362 
1363  //------------------------------------------------------------------------
1364  // Mutlitply wf/hf into mNew
1365  //------------------------------------------------------------------------
1366  {
1367  double
1368  wf = w ? *w : 1,
1369  hf = h ? *h : 1;
1370  a00 *= wf;
1371  a01 *= wf;
1372  a10 *= hf;
1373  a11 *= hf;
1374  }
1375 
1376  //------------------------------------------------------------------------
1377  // Restrict x-Position
1378  //------------------------------------------------------------------------
1379  if( ( snapWhat & snapPosX ) && ( m_posModesX & info->m_posModesX ) && m_docSnapDistX )
1380  {
1381  int
1382  modes = m_posModesX & info->m_posModesX;
1383  double
1384  bestShift = DBL_MAX;
1385  if( modes & posCenter )
1386  SnapIfBetterPos( a00 * info->m_centerX + a10 * info->m_centerY + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1387  if( modes & posTopLeft )
1388  SnapIfBetterPos( a00 * info->m_left + a10 * info->m_top + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1389  if( modes & posTop )
1390  SnapIfBetterPos( a00 * info->m_centerX + a10 * info->m_top + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1391  if( modes & posTopRight )
1392  SnapIfBetterPos( a00 * info->m_right + a10 * info->m_top + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1393  if( modes & posRight )
1394  SnapIfBetterPos( a00 * info->m_right + a10 * info->m_centerY + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1395  if( modes & posBottomRight )
1396  SnapIfBetterPos( a00 * info->m_right + a10 * info->m_bottom + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1397  if( modes & posBottom )
1398  SnapIfBetterPos( a00 * info->m_centerX + a10 * info->m_bottom + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1399  if( modes & posBottomLeft )
1400  SnapIfBetterPos( a00 * info->m_left + a10 * info->m_bottom + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1401  if( modes & posLeft )
1402  SnapIfBetterPos( a00 * info->m_left + a10 * info->m_centerY + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1403  if( ( modes & posOther ) && info->m_other )
1404  {
1405  forEachIn( a2dVertexList, info->m_other )
1406  {
1407  a2dPoint2D point = ( *iter )->GetPoint();
1408  SnapIfBetterPos( a00 * point.m_x + a10 * point.m_y + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1409  }
1410  }
1411  if( modes & pos6L )
1412  {
1413  // check if transformed x-axis is vertical
1414  if( fabs( a00 ) < Eps * fabs( a01 ) )
1415  {
1416  if( modes & posLineTop )
1417  SnapIfBetterPos( a00 * info->m_centerX + a10 * info->m_top + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1418  if( modes & posLineHCenter )
1419  SnapIfBetterPos( a00 * info->m_centerX + a10 * info->m_centerY + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1420  if( modes & posLineBottom )
1421  SnapIfBetterPos( a00 * info->m_centerX + a10 * info->m_bottom + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1422  }
1423  // check if transformed y-axis is vertical
1424  if( fabs( a10 ) < Eps * fabs( a11 ) )
1425  {
1426  if( modes & posLineLeft )
1427  SnapIfBetterPos( a00 * info->m_left + a10 * info->m_centerY + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1428  if( modes & posLineVCenter )
1429  SnapIfBetterPos( a00 * info->m_centerX + a10 * info->m_centerY + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1430  if( modes & posLineRight )
1431  SnapIfBetterPos( a00 * info->m_right + a10 * info->m_centerY + a20, m_docSnapDistX, m_docOriginX, &bestShift );
1432  }
1433  }
1434  assert( fabs( bestShift ) <= 0.50001 * m_docSnapDistX );
1435  a20 += bestShift;
1436  }
1437 
1438  //------------------------------------------------------------------------
1439  // Restrict y-Position
1440  //------------------------------------------------------------------------
1441  if( ( snapWhat & snapPosY ) && ( m_posModesY & info->m_posModesY ) && m_docSnapDistY )
1442  {
1443  int
1444  modes = m_posModesY & info->m_posModesY;
1445  double
1446  bestShift = DBL_MAX;
1447  if( modes & posCenter )
1448  SnapIfBetterPos( a01 * info->m_centerX + a11 * info->m_centerY + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1449  if( modes & posTopLeft )
1450  SnapIfBetterPos( a01 * info->m_left + a11 * info->m_top + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1451  if( modes & posTop )
1452  SnapIfBetterPos( a01 * info->m_centerX + a11 * info->m_top + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1453  if( modes & posTopRight )
1454  SnapIfBetterPos( a01 * info->m_right + a11 * info->m_top + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1455  if( modes & posRight )
1456  SnapIfBetterPos( a01 * info->m_right + a11 * info->m_centerY + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1457  if( modes & posBottomRight )
1458  SnapIfBetterPos( a01 * info->m_right + a11 * info->m_bottom + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1459  if( modes & posBottom )
1460  SnapIfBetterPos( a01 * info->m_centerX + a11 * info->m_bottom + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1461  if( modes & posBottomLeft )
1462  SnapIfBetterPos( a01 * info->m_left + a11 * info->m_bottom + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1463  if( modes & posLeft )
1464  SnapIfBetterPos( a01 * info->m_left + a11 * info->m_centerY + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1465  if( ( modes & posOther ) && info->m_other )
1466  {
1467  forEachIn( a2dVertexList, info->m_other )
1468  {
1469  a2dPoint2D point = ( *iter )->GetPoint();
1470  SnapIfBetterPos( a01 * point.m_x + a11 * point.m_y + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1471  }
1472  }
1473  if( modes & pos6L )
1474  {
1475  // check if transformed x-axis is vertical
1476  if( fabs( a01 ) < Eps * fabs( a11 ) )
1477  {
1478  if( modes & posLineTop )
1479  SnapIfBetterPos( a01 * info->m_centerX + a11 * info->m_top + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1480  if( modes & posLineHCenter )
1481  SnapIfBetterPos( a01 * info->m_centerX + a11 * info->m_centerY + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1482  if( modes & posLineBottom )
1483  SnapIfBetterPos( a01 * info->m_centerX + a11 * info->m_bottom + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1484  }
1485  // check if transformed y-axis is vertical
1486  if( fabs( a01 ) < Eps * fabs( a11 ) )
1487  {
1488  if( modes & posLineLeft )
1489  SnapIfBetterPos( a01 * info->m_left + a11 * info->m_centerY + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1490  if( modes & posLineVCenter )
1491  SnapIfBetterPos( a01 * info->m_centerX + a11 * info->m_centerY + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1492  if( modes & posLineRight )
1493  SnapIfBetterPos( a01 * info->m_right + a11 * info->m_centerY + a21, m_docSnapDistY, m_docOriginY, &bestShift );
1494  }
1495  }
1496  assert( fabs( bestShift ) <= 0.50001 * m_docSnapDistY );
1497  a21 += bestShift;
1498  }
1499 
1500  //------------------------------------------------------------------------
1501  // write back shift
1502  //------------------------------------------------------------------------
1503  mNew->m_matrix[2][0] = a20;
1504  mNew->m_matrix[2][1] = a21;
1505 
1506  // mNew->DebugDump(wxT("PostRestrict"), w ? *w : 0, h ? *h : 0);
1507 }
1508 
1509 void a2dRestrictionEngineOld::RestrictEndpointAngle( double* angle, const a2dAffineMatrix& WXUNUSED( matrix ), ESnapWhat snapWhat )
1510 {
1511  if( snapWhat & snapEndAngle )
1512  {
1513  double
1514  deg2rad = wxPI / 180,
1515  rad2deg = 180 / wxPI;
1517  {
1518  *angle = AngleRestrict( *angle * deg2rad ) * rad2deg;
1519  }
1520  else if( m_rotModes & rotEndpointRational )
1521  {
1522  *angle = RationalRestrict( *angle * deg2rad ) * rad2deg;
1523  }
1524  }
1525  // TODO !!!!! untransformed restriction
1526 }
1527 
1528 void a2dRestrictionEngineOld::RestrictPoint( double* x, double* y )
1529 {
1530  // Restrict x-Position
1531  if( ( m_posModesX & posSngl ) && m_docSnapDistX )
1532  {
1533  *x = floor( ( *x - m_docOriginX ) / m_docSnapDistX + 0.5 ) * m_docSnapDistX + m_docOriginX;
1534  }
1535  // Restrict y-Position
1536  if( ( m_posModesY & posSngl ) && m_docSnapDistY )
1537  {
1538  *y = floor( ( *y - m_docOriginY ) / m_docSnapDistY + 0.5 ) * m_docSnapDistY + m_docOriginY;
1539  }
1540 }
1541 
1543 {
1544  double
1545  angleSnapRad = m_rotationAngle / 180 * wxPI;
1546  return floor( angle / angleSnapRad + 0.5 ) * angleSnapRad;
1547 }
1548 
1549 void a2dRestrictionEngineOld::AngleRestrictVectorRot( double* vecx, double* vecy )
1550 {
1551  double
1552  angle = atan2( *vecy, *vecx ),
1553  len = sqrt( sqr( *vecx ) + sqr( *vecy ) );
1554  angle = AngleRestrict( angle );
1555  *vecx = cos( angle ) * len;
1556  *vecy = sin( angle ) * len;
1557 }
1558 
1559 void a2dRestrictionEngineOld::AngleRestrictVectorSkew( double* vecx, double* vecy, double otherx, double othery )
1560 {
1561  double
1562  angleOld = atan2( *vecy, *vecx ),
1563  angleNew = AngleRestrict( angleOld ),
1564  angleOther = atan2( othery, otherx ),
1565  proj = *vecx * othery - *vecy * otherx;
1566 
1567  if( fabs( angleNew - angleOther ) < 1e-5 )
1568  {
1569  // If the new angle is very close to the other vectors angle
1570  // the transformation will become singular.
1571  // To avoid this, use the closest other snap angle
1572  double
1573  angleSnapRad = m_rotationAngle / 180 * wxPI,
1574  angleNew1 = angleNew - angleSnapRad,
1575  angleNew2 = angleNew + angleSnapRad;
1576  if( fabs( angleOld - angleNew1 ) < fabs( angleOld - angleNew2 ) )
1577  angleNew = angleNew1;
1578  else
1579  angleNew = angleNew2;
1580  }
1581 
1582  double
1583  newx = cos( angleNew ),
1584  newy = sin( angleNew ),
1585  newpro = newx * othery - newy * otherx;
1586 
1587  if( !newpro )
1588  return;
1589 
1590  *vecx = newx * ( proj / newpro );
1591  *vecy = newy * ( proj / newpro );
1592 }
1593 
1595 {
1596  // map angle to first quadrant 0..45 deg
1597  int
1598  quad = 0;
1599  bool
1600  mirr = false;
1601 
1602  if( angle < 0 )
1603  angle += 2 * wxPI;
1604 
1605  if( angle > wxPI )
1606  {
1607  quad += 2;
1608  angle -= wxPI;
1609  }
1610  if( angle > wxPI / 2 )
1611  {
1612  quad += 1;
1613  angle -= wxPI / 2;
1614  }
1615  if( angle > wxPI / 4 )
1616  {
1617  mirr = true;
1618  angle = wxPI / 2 - angle;
1619  }
1620 
1621  if( !m_angleList )
1622  {
1623  // create the list of valid angles
1624  const int
1625  mAngles = 31 * 30 / 2 + 1;
1626  int
1627  nAngles = 0;
1628  double
1629  angles[mAngles];
1630 
1631  angles[nAngles++] = 0;
1632  int i;
1633  for( i = 1; i <= 31; i++ )
1634  {
1635  if( m_rotationRationalNom & ( 1 << i ) )
1636  {
1637  for( int j = i; j <= 31; j++ )
1638  {
1639  if( m_rotationRationalDen & ( j << i ) )
1640  {
1641  assert( nAngles < mAngles );
1642  angles[nAngles++] = atan( double( i ) / double( j ) );
1643  }
1644  }
1645  }
1646  }
1647 
1648  // sort the list
1649  qsort( angles, nAngles, sizeof( *angles ), CmprDbl );
1650 
1651  // remove multiple equal values
1652  m_nAngleList = 1;
1653  for( i = 1; i < nAngles; i++ )
1654  {
1655  if( angles[i] - angles[m_nAngleList - 1] > 1e-13 )
1656  {
1657  angles[m_nAngleList++] = angles[i];
1658  }
1659  }
1660 
1661  // copy the temporary list
1662  m_angleList = new double[m_nAngleList];
1663  memcpy( m_angleList, angles, sizeof( *m_angleList )*m_nAngleList );
1664  }
1665 
1666  // find nearest angle in list
1667  if( m_nAngleList <= 1 )
1668  {
1669  angle = 0;
1670  }
1671  else
1672  {
1673  int
1674  low = 0,
1675  high = m_nAngleList - 1,
1676  mid;
1677 
1678  while( high - low > 1 )
1679  {
1680  mid = ( low + high ) >> 1;
1681  if( m_angleList[mid] < angle )
1682  low = mid;
1683  else
1684  high = mid;
1685  }
1686 
1687  // angle is between m_angleList[low] and m_angleList[high]
1688  // One of these two values must be the closest value
1689  if( angle - m_angleList[low] < m_angleList[high] - angle )
1690  angle = m_angleList[low];
1691  else
1692  angle = m_angleList[high];
1693  }
1694 
1695  // put the angle back to its original quadrant
1696  if( mirr )
1697  angle = wxPI / 2 - angle;
1698  angle += quad * wxPI / 2;
1699 
1700  return angle;
1701 }
1702 
1703 void a2dRestrictionEngineOld::RationalRestrictVector( double* vecx, double* vecy )
1704 {
1705  double
1706  angle = atan2( *vecy, *vecx ),
1707  len = sqrt( sqr( *vecx ) + sqr( *vecy ) );
1708  angle = RationalRestrict( angle );
1709  *vecx = cos( angle ) * len;
1710  *vecy = sin( angle ) * len;
1711 }
enable position snapping of object top line to grid, if x axis parallel to main axis ...
Definition: restrict.h:604
perform x position snapping to a specific point
Definition: restrict.h:127
allow only pure one axis slanting
Definition: restrict.h:660
perform snapping to boundingbox of objects
Definition: restrict.h:137
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
Definition: artglob.h:47
double m_rotationAngle
angle snapping angle in degrees
Definition: restrict.h:441
perform y position snapping to a specific point
Definition: restrict.h:128
bool GetSnap() const
is snap flag set?
Definition: canobj.h:1686
enable position snapping of object right to grid
Definition: restrict.h:599
a2dPoint2D m_snappedPoint
set to point that is snapped to m_pointToSnap
Definition: restrict.h:454
double m_matrix[3][2]
array store the six double for the affine matrix
Definition: afmatrix.h:335
EPositionSnapModes m_posModesX
anded with m_posModesX of wxRetrictionEngine
Definition: restrict.h:704
EPositionSnapModes m_posModesX
ored EPositionSnapModes of enabled modes for x
Definition: restrict.h:794
disable all rotation restriction modes
Definition: restrict.h:667
allow only pure rotations, no slanting
Definition: restrict.h:659
enable position snapping of object bottom left to grid
Definition: restrict.h:602
ESizeSnapModes m_sizeModesX
ored ESizeSnapModes of enabled modes for x
Definition: restrict.h:796
fundamental classes used by all other modules.
enable minimum size restriction
Definition: restrict.h:643
enable maximum size restriction
Definition: restrict.h:644
a2dRestrictionEngine()
Constructor.
Definition: restrict.cpp:116
void AngleRestrictVectorRot(double *vecx, double *vecy)
Restrict the angle of a vector, keeping the vectors length.
Definition: restrict.cpp:521
int m_nAngleList
number of allowed rational angles
Definition: restrict.h:813
double m_sizeX
horizontal size snapping grid distance
Definition: restrict.h:803
void RationalRestrictVector(double *vecx, double *vecy)
Rational restrict the angle of a vector.
Definition: restrict.cpp:675
void RestrictEndpointAngle(double *angle, const a2dAffineMatrix &matrix, ESnapWhat snapWhat)
Definition: restrict.cpp:1509
Ref Counted base object.
Definition: gen.h:1045
void AngleRestrictVectorSkew(double *vecx, double *vecy, double otherx, double othery)
Restrict the angle of a vector, keeping the vectors projection on the orthogonal of another vector...
Definition: restrict.cpp:1559
snap segments of other objects in a2dCanvasObject::RestrictToObject()
Definition: restrict.h:120
double RationalRestrict(double angle)
Rational restrict an angle.
Definition: restrict.cpp:1594
virtual bool RestrictCanvasObjectAtVertexes(a2dCanvasObject *object, a2dPoint2D &point, double &dx, double &dy, wxUint32 sourceRequired=snapToAll, bool ignoreEngine=false)
return the clossest vertex which can be snapped if any.
Definition: restrict.cpp:685
~a2dRestrictionEngine()
Destructor.
Definition: restrict.cpp:152
a2dPoint2D m_pointToSnap
set to point that is currently being snapped.
Definition: restrict.h:451
double RationalRestrict(double angle)
Rational restrict an angle.
Definition: restrict.cpp:566
double m_snapDistY
vertical position snapping grid distance
Definition: restrict.h:800
double m_rotationAngle
angle snapping angle in degrees
Definition: restrict.h:809
perform x position snapping
Definition: restrict.h:677
double m_left
minimum x coordinate (e.g. 0), transformed via affine transform and w
Definition: restrict.h:698
snap to pins in other objects when not connected
Definition: restrict.h:112
The base class for all drawable objects in a a2dCanvasDocument.
double m_snapDistX
horizontal position snapping grid distance
Definition: restrict.h:799
snapping engine, for snapping while editing a drawing
wxUint32 m_rotationRationalNom
bit map of possible nominators (bit1-&gt;0.. bit32-&gt;31) for rational angle snapping
Definition: restrict.h:442
snap angle of endpoints or arcs
Definition: restrict.h:684
a2dRestrictionEngineOld()
Constructor.
Definition: restrict.cpp:811
disable all size restriction modes
Definition: restrict.h:646
vertex array of line and arc segments.
Definition: polyver.h:494
a2dCanvasObject is the base class for Canvas Objects.
Definition: canobj.h:371
EPositionSnapModes m_posModesY
ored EPositionSnapModes of enabled modes for y
Definition: restrict.h:795
virtual bool RestrictLine(a2dLine &line, wxUint32 sourceRequired=snapToAll, bool ignoreEngine=false)
Restrict a single line.
Definition: restrict.cpp:480
#define A2D_PROPID_M(type, classname, propname, defaultval, mptr)
to define a get set property more easily
Definition: id.h:730
bool SetPointIfCloser(const a2dPoint2D &pointToSnapTo, const a2dPoint2D &pointToSnap, a2dPoint2D &bestPointSofar, double thresHoldWorld)
Definition: canobj.cpp:4189
a2dSnapToWhatMask m_snapSourceFeatures
set to the a2dSnapToWhat features enabled by the engine for the source object
Definition: restrict.h:432
enable position snapping of object top right to grid
Definition: restrict.h:598
double GetDeterminant2() const
Calculate the determinat of the transformed x-axis vector and the shift vector.
Definition: afmatrix.cpp:835
a2dCanvasObjectList * GetChildObjectList()
get the list where the child objects are stored in.
Definition: canobj.cpp:2551
vertex list of line and arc segments.
Definition: polyver.h:600
wxUint32 m_rotationRationalDen
bit map of possible denominators (bit1-&gt;0.. bit32-&gt;31) for rational angle snapping ...
Definition: restrict.h:443
a2dDrawingPart * GetActiveDrawingPart()
return the currently/last active drawing part.
Definition: canglob.h:1262
double m_top
minimum y coordinate (e.g. 0), transformed via affine transform and h
Definition: restrict.h:699
a2dDoMu m_snapDistX
horizontal position snapping grid distance
Definition: restrict.h:437
void SetPointSnapResult(const a2dPoint2D &p)
set the point that was snapped to a a2dCanvasObject vertex
Definition: restrict.cpp:212
a2dDoMu m_originX
horizontal grid snapping origin vs. coordinate origin
Definition: restrict.h:439
class a2dVertexList * m_other
other snapping points (enabled by bits in m_posModesX/m_posModesY, NOT owned or deleted by this objec...
Definition: restrict.h:709
a2dDoMu m_originY
vertical grid snapping origins vs. coordinate origin
Definition: restrict.h:440
enable position snapping of object top to grid
Definition: restrict.h:597
enable position snapping of object v-center line to grid, if y axis parallel to main axis ...
Definition: restrict.h:608
enable position snapping of object center to grid
Definition: restrict.h:595
enable position snapping of object bottom line to grid, if x axis parallel to main axis ...
Definition: restrict.h:606
If no other snap point was closer, force to grid, even if not within threshold.
Definition: restrict.h:141
snap to other objects its vertexes, which are decided in a2dCanvasObject::RestrictToObject() ...
Definition: restrict.h:116
enable all 6 line snapping modes
Definition: restrict.h:617
a2dCanvasObjectList * wxNullCanvasObjectList
define a NON a2dCanvasObjectList
Definition: objlist.cpp:53
int m_nAngleList
number of allowed rational angles
Definition: restrict.h:445
ESizeSnapModes m_sizeModesY
ored ESizeSnapModes of enabled modes for y
Definition: restrict.h:797
double * m_angleList
sorted list of allowed rational angles
Definition: restrict.h:444
double GetMaximum2() const
Calculate the maximum absolute of the elemnts entering GetDeterminant2.
Definition: afmatrix.cpp:858
enable position snapping of object left to grid
Definition: restrict.h:603
#define forEachIn(listtype, list)
easy iteration for a2dlist
Definition: a2dlist.h:111
wxUint32 m_rotationRationalDen
bit map of possible denominators (0..31) for rational angle snapping
Definition: restrict.h:811
double m_centerY
center y coordinate (e.g. 0.5), transformed via affine transform and h
Definition: restrict.h:703
Normal straight line segment in a2dVpath.
Definition: polyver.h:878
#define wxStaticCast(obj, className)
The wxWindows 2.4.2 wxStaticCast is buggy. It evaluates its argument twice.
Definition: gen.h:123
virtual bool RestrictVertexes(a2dVertexArray *segments, a2dPoint2D &point, double &dx, double &dy, wxUint32 sourceRequired=snapToAll, bool ignoreEngine=false)
return the clossest vertex which can be snapped if any.
Definition: restrict.cpp:747
snap to intersections in other objects
Definition: restrict.h:114
perform skew snapping
Definition: restrict.h:682
ESnapWhat
Flags for what to touch during a restriction.
Definition: restrict.h:675
a2dCanvasObject * GetShowObject() const
return pointer of then currently shown object on the drawer.
Definition: drawer.h:680
double m_originY
vertical grid snapping origins vs. coordinate origin
Definition: restrict.h:802
Normal straight line segment in a2dVertexList and a2dVertexArray.
Definition: polyver.h:163
ESizeSnapModes m_sizeModesX
anded with m_sizeModesX of wxRetrictionEngine
Definition: restrict.h:706
enable snapping of arc endpoint angles (rational)
Definition: restrict.h:664
enable position snapping of object right line to grid, if y axis parallel to main axis ...
Definition: restrict.h:609
double m_minSizeY
minimal vertical size
Definition: restrict.h:806
enable snapping of projection of transformed axis vector length to orthogonal of other axis vector ...
Definition: restrict.h:639
a2dSnapToWhatMask m_snapTargetFeatures
set to the a2dSnapToWhat target features enabled by the engine and/or snap source object ...
Definition: restrict.h:435
bool m_releaseSnap
to not snap inside snapping engine.
Definition: restrict.h:462
Restriction engine for editing restrictions like snapping.
Definition: restrict.h:88
a2dDrawer2D * GetDrawer2D()
get the internal m_drawer2D that is used for rendering the document
Definition: drawer.h:1125
double m_sizeY
vertical size snapping grid distance
Definition: restrict.h:804
enable position snapping of object bottom right to grid
Definition: restrict.h:600
double AngleRestrict(double angle)
Restrict an angle.
Definition: restrict.cpp:1542
enable snapping of arc endpoint angles
Definition: restrict.h:663
enable position snapping of object other points to grid (e.g. triangle corner)
Definition: restrict.h:610
bool m_snap
if true snapping modes are enabled, else non.
Definition: restrict.h:461
during size snapping, change w/h rather than transform
Definition: restrict.h:683
Structure to descripe snapping properties of an object.
Definition: restrict.h:696
perform snapping to X or Y of a specific point
Definition: restrict.h:129
perform rotation snapping
Definition: restrict.h:681
enable rational snapping for rotations of second coordinate vektor
Definition: restrict.h:658
enable size snapping of transformed axis vector length
Definition: restrict.h:638
enable position snapping of object top left to grid
Definition: restrict.h:596
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
double m_originX
horizontal grid snapping origin vs. coordinate origin
Definition: restrict.h:801
disable all posizion restriction modes
Definition: restrict.h:614
enable position snapping of object bottom to grid
Definition: restrict.h:601
double GetMaximum() const
Calculate the maximum absolute of the elemnts entering GetDeterminant.
Definition: afmatrix.cpp:840
double GetDeterminant1() const
Calculate the determinat of the shift vector and the transformed y-axis vector.
Definition: afmatrix.cpp:830
double m_maxSizeX
maximal horiontal size
Definition: restrict.h:807
while iterating a a2dCanvasDocument, this holds the context.
Definition: canobj.h:3212
snap segments middle of other objects in a2dCanvasObject::RestrictToObject()
Definition: restrict.h:118
ERotationSnapModes m_rotModes
ored ERotationSnapModes of enabled modes
Definition: restrict.h:798
Contains graphical drawing context specific classes. a2dDrawer2D and derived classes are used for dra...
double m_x
x endpoint of line
Definition: polyver.h:232
enable angle snapping for rotations of second coordinate vektor
Definition: restrict.h:657
double GetMaximum1() const
Calculate the maximum absolute of the elemnts entering GetDeterminant1.
Definition: afmatrix.cpp:849
double m_right
maximum x coordinate (e.g. 1), transformed via affine transform and w
Definition: restrict.h:700
double m_bottom
maximum y coordinate (e.g. 1), transformed via affine transform and h
Definition: restrict.h:701
double m_y
y endpoint of line
Definition: polyver.h:235
a2dPATHSEG GetType() const
easy way to test type of segment
Definition: polyver.h:901
#define A2D_PROPID_GS(type, classname, propname, defaultval, fget, fset)
to define a get set property more easily
Definition: id.h:710
Line calculations.
Definition: liner.h:36
void RestrictPoint(double *x, double *y)
Restrict a single point of a line or polyline.
Definition: restrict.cpp:1528
void AngleRestrictVectorSkew(double *vecx, double *vecy, double otherx, double othery)
Restrict the angle of a vector, keeping the vectors projection on the orthogonal of another vector...
Definition: restrict.cpp:531
perform y position snapping
Definition: restrict.h:678
~a2dRestrictionEngineOld()
Destructor.
Definition: restrict.cpp:835
double GetUnitsScale()
this is the number that defines the physical dimension in meters / inch/ etc.
Definition: drawing.h:676
enable angle snapping for rotation of first coordinate vektor
Definition: restrict.h:655
int m_snapThresHold
threshold in pixels towards the snapping point.
Definition: restrict.h:448
double m_y1
y endpoint of line
Definition: polyver.h:922
bool IsWithInThresHold(const a2dPoint2D &p)
check if point is within threshold to m_pointToSnap
Definition: restrict.cpp:217
double * m_angleList
sorted list of allowed rational angles
Definition: restrict.h:812
list for a2dCanvasObject
double m_centerX
center x coordinate (e.g. 0.5), transformed via affine transform and w
Definition: restrict.h:702
perform rational angle snapping to a specific point
Definition: restrict.h:134
enable size snapping of transformed axis major component
Definition: restrict.h:640
perform snapping to snapping vector path returned by a2dCanvasObject::GetSnapVpath() ...
Definition: restrict.h:139
see a2dComEvent
Definition: gen.h:371
perform x grid snapping
Definition: restrict.h:123
double AngleRestrict(double angle)
Restrict an angle.
Definition: restrict.cpp:514
enable restriction of single points (e.g. of polylines)
Definition: restrict.h:611
virtual bool RestrictAngle(double *ang, wxUint32 sourceRequired=snapToAll, bool ignoreEngine=false)
Restrict angle.
Definition: restrict.cpp:485
a2dCanvasObject * m_parentObject
parent canvas object in a2dCanvasDocument on which snapping needs to be done.
Definition: restrict.h:466
enable position snapping of object left line to grid, if y axis parallel to main axis ...
Definition: restrict.h:607
enable rational snapping for rotations of first coordinate vektor
Definition: restrict.h:656
EPositionSnapModes m_posModesY
anded with m_posModesY of wxRetrictionEngine
Definition: restrict.h:705
double m_maxSizeY
maximal vertical size
Definition: restrict.h:808
double GetDeterminant() const
Calculate the determinat of the linear transformation.
Definition: afmatrix.cpp:825
bool m_snapOnlyVisbleObjects
if true snapping modes for object is only on visible object.
Definition: restrict.h:460
void RestrictAffine(a2dAffineMatrix *mNew, const a2dAffineMatrix *mOld, ESnapWhat snapWhat, SnapObjectInfo *info, double *w=0, double *h=0)
Restrict an affine transformation.
Definition: restrict.cpp:844
enable position snapping of object h-center line to grid, if x axis parallel to main axis ...
Definition: restrict.h:605
void AngleRestrictVectorRot(double *vecx, double *vecy)
Restrict the angle of a vector, keeping the vectors length.
Definition: restrict.cpp:1549
affine matrix class
void RationalRestrictVector(double *vecx, double *vecy)
Rational restrict the angle of a vector.
Definition: restrict.cpp:1703
a2dDrawing * GetDrawing() const
get drawing via top object
Definition: drawer.cpp:726
the a2dDrawingPart is a a2dView specially designed for displaying parts of a a2dDrawing. It uses a a2dDrawer2D to actually redraw things from the document, by giving that a2dDrawer2D as drawing context to the document, and telling the document to redraw a certain rectangular area. At that last is what this class is for. It optimizes the areas to be redrawn after object in the document were changed. To do that it combines redraw areas to a minimal set of redrawing areas. All the administration for this and the way things will be redrawn is from this view.
double m_x1
x endpoint of line
Definition: polyver.h:919
ERotationSnapModes m_rotModes
anded with m_rotModes of wxRetrictionEngine
Definition: restrict.h:708
double m_minSizeX
minimal horiontal size
Definition: restrict.h:805
a2dVpath * GetSegments()
modify point at index to x,y
Definition: vpath.h:117
a2dCanvasGlobal * a2dCanvasGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: canglob.cpp:1234
a2dCanvasObject for a Vector Path
Definition: vpath.h:55
perform angle snapping to multiples of m_rotationAngle to a specific point
Definition: restrict.h:133
This template class is for property ids with a known data type.
Definition: id.h:477
wxUint32 m_rotationRationalNom
bit map of possible nominators (0..31) for rational angle snapping
Definition: restrict.h:810
double GetSnapThresHoldWorld() const
used to snap vertexes to a pin or point, for snapping features in objects.
Definition: restrict.cpp:91
perform y grid snapping
Definition: restrict.h:124
a2dDoMu m_snapDistY
vertical position snapping grid distance
Definition: restrict.h:438
double DeviceToWorldXRel(double x) const
convert x relative from device to world coordinates
Definition: drawer2d.h:444
bool m_shiftDown
snapping modifier when shift key is pressed
Definition: restrict.h:463
Contain one drawing as hierarchical tree of a2dCanvasObject&#39;s.
Definition: drawing.h:434
enable size snapping of projection to untronsformed axis
Definition: restrict.h:641
virtual bool RestrictPoint(double &x, double &y, wxUint32 sourceRequired=snapToAll, bool ignoreEngine=false)
Restrict a single point of a line or polyline.
Definition: restrict.cpp:227
const double wxPI
defines PI
Definition: artglob.cpp:28
snap to pins in other objects
Definition: restrict.h:111
perform alligning to X or Y of a specific point
Definition: restrict.h:130
#define A2D_PROPID_GSI(type, classname, propname, defaultval)
to define a get set property more easily
Definition: id.h:698
ESizeSnapModes m_sizeModesY
anded with m_sizeModesY of wxRetrictionEngine
Definition: restrict.h:707
restrict.cpp Source File -- Sun Oct 12 2014 17:04:23 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation