wxArt2D
vpath.cpp
Go to the documentation of this file.
1 /*! \file canvas/src/vpath.cpp
2  \author Klaas Holwerda
3 
4  Copyright: 2000-2004 (c) Klaas Holwerda
5 
6  Licence: wxWidgets Licence
7 
8  RCS-ID: $Id: vpath.cpp,v 1.66 2009/05/06 21:33:23 titato Exp $
9 */
10 
11 #include "a2dprec.h"
12 
13 #ifdef __BORLANDC__
14 #pragma hdrstop
15 #endif
16 
17 #ifndef WX_PRECOMP
18 #include "wx/wx.h"
19 #endif
20 
21 #include "wx/canvas/vpath.h"
22 #include "wx/canvas/drawer.h"
23 
24 IMPLEMENT_DYNAMIC_CLASS( a2dVectorPath, a2dCanvasObject )
25 
26 //----------------------------------------------------------------------------
27 // a2dVectorPath
28 //----------------------------------------------------------------------------
30  : a2dCanvasObject()
31 {
32  m_contourwidth = 0;
33  m_datatype = 0;
34  m_pathtype = a2dPATH_END_SQAURE;
35  m_segments = new a2dVpath();
36 }
37 
39  : a2dCanvasObject()
40 {
41  m_contourwidth = 0;
42  m_datatype = 0;
43  m_pathtype = a2dPATH_END_SQAURE;
44  m_segments = path;
45 }
46 
47 a2dVectorPath::~a2dVectorPath()
48 {
49  delete m_segments;
50 }
51 
53  : a2dCanvasObject( other, options, refs )
54 {
55  m_segments = new a2dVpath();
56  *m_segments = *other.m_segments;
58  m_datatype = other.m_datatype;
59  m_pathtype = other.m_pathtype;
60 }
61 
63 {
64  return new a2dVectorPath( *this, options, refs );
65 };
66 
68 {
69  a2dAffineMatrix pworld;
70  if ( transform )
71  pworld = m_lworld;
72 
73  a2dCanvasObjectList* canpathlist = new a2dCanvasObjectList();
74  a2dVectorPath* copy = wxStaticCast( this->Clone( clone_deep ), a2dVectorPath );
75  copy->m_segments->Transform( pworld );
76 
77  canpathlist->push_back( copy );
78 
79  return canpathlist;
80 }
81 
82 bool a2dVectorPath::RestrictToObject( a2dIterC& ic, const a2dPoint2D& pointToSnapTo, a2dPoint2D& bestPointSofar, a2dSnapToWhatMask snapToWhat, double thresHoldWorld )
83 {
84  bool res = false;
85  if ( m_segments && snapToWhat & a2dRestrictionEngine::snapToObjectVertexes )
86  {
87  unsigned int i;
88  for ( i = 0; i < m_segments->size(); i++ )
89  {
90  a2dVpathSegmentPtr seg = m_segments->Item( i );
91  switch ( seg->GetType() )
92  {
93  case a2dPATHSEG_MOVETO:
94  case a2dPATHSEG_LINETO:
101  case a2dPATHSEG_ARCTO:
102  {
103  //if within the threshold, do snap to vertex position.
104  res |= SetPointIfCloser( pointToSnapTo, a2dPoint2D( seg->m_x1, seg->m_y1 ), bestPointSofar, thresHoldWorld );
105  }
106  break;
107  }
108  }
109  }
110 
111  snapToWhat = snapToWhat & ( a2dRestrictionEngine::snapToAll ^ a2dRestrictionEngine::snapToObjectVertexes ); //disable this for base now.
112 
113  return res || a2dCanvasObject::RestrictToObject( ic, pointToSnapTo, bestPointSofar, snapToWhat, thresHoldWorld );
114 }
115 
117 {
119 
120  double tstep = 1 / ( double ) SPLINE_STEP;
121  unsigned int i;
122  double x, y, xm, ym;
123  bool move = false;
124  int count = 0;
125  bool nostrokeparts = false;
126 
127  if ( m_lworld.IsTranslate() && m_segments->IsPolygon( true ) )
128  {
129  a2dVertexListPtr lpoints = new a2dVertexList();
130 
131  for ( i = 0; i < m_segments->size(); i++ )
132  {
133  a2dVpathSegment* seg = Item( i );
134  switch ( seg->GetType() )
135  {
136  case a2dPATHSEG_MOVETO:
137  m_lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
138  lpoints->push_back( new a2dLineSegment( x, y ) );
139  break;
140  case a2dPATHSEG_LINETO:
141  m_lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
142  lpoints->push_back( new a2dLineSegment( x, y ) );
143  break;
144  case a2dPATHSEG_ARCTO:
145  a2dVpathArcSegment* cseg = ( a2dVpathArcSegment* ) seg;
146  m_lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
147  m_lworld.TransformPoint( cseg->m_x2, cseg->m_y2, xm, ym );
148  lpoints->push_back( new a2dArcSegment( x, y, xm, ym ) );
149  break;
150  }
151  if ( seg->GetClose() == a2dPATHSEG_END_CLOSED )
152  {
153  lpoints->push_back( new a2dLineSegment( Item( 0 )->m_x1, Item( 0 )->m_y1 ) );
154  }
155  }
156 
157  a2dPolygonL* poly = new a2dPolygonL( lpoints );
159  ret->push_back( poly );
160  return ret;
161  }
162 
163  if ( m_lworld.IsTranslate() && m_segments->IsPolyline( true ) )
164  {
165  a2dVertexListPtr lpoints = new a2dVertexList();
166 
167  for ( i = 0; i < m_segments->size(); i++ )
168  {
169  a2dVpathSegmentPtr seg = Item( i );
170  switch ( seg->GetType() )
171  {
172  case a2dPATHSEG_MOVETO:
173  m_lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
174  lpoints->push_back( new a2dLineSegment( x, y ) );
175  break;
176  case a2dPATHSEG_LINETO:
177  m_lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
178  lpoints->push_back( new a2dLineSegment( x, y ) );
179  break;
180  case a2dPATHSEG_ARCTO:
181  a2dVpathArcSegment* cseg = ( a2dVpathArcSegment* ) seg.Get();
182  m_lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
183  m_lworld.TransformPoint( cseg->m_x2, cseg->m_y2, xm, ym );
184  lpoints->push_back( new a2dArcSegment( x, y, xm, ym ) );
185  break;
186  }
187  if ( seg->GetClose() == a2dPATHSEG_END_CLOSED )
188  {
189  lpoints->push_back( new a2dLineSegment( Item( 0 )->m_x1, Item( 0 )->m_y1 ) );
190  }
191  }
192 
193  a2dPolylineL* polyl = new a2dPolylineL( lpoints );
195  polyl->SetPathType( m_pathtype );
196  ret->push_back( new a2dPolylineL( lpoints ) );
197  return ret;
198  }
199 
200  a2dVertexListPtr lpoints = new a2dVertexList();
201  //first draw as much as possible ( nostroke parts may stop this first round )
202  for ( i = 0; i < m_segments->size(); i++ )
203  {
204  a2dVpathSegmentPtr seg = m_segments->Item( i );
205  switch ( seg->GetType() )
206  {
207  case a2dPATHSEG_MOVETO:
208  if ( count == 0 )
209  {
210  m_lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
211  lpoints->push_back( new a2dLineSegment( x, y ) );
212  count++;
213  }
214  else
215  {
216  i--;
217  move = true;
218  }
219  break;
220 
222  nostrokeparts = true;
223  break;
224  case a2dPATHSEG_LINETO:
225  m_lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
226  lpoints->push_back( new a2dLineSegment( x, y ) );
227  count++;
228  break;
229 
231  nostrokeparts = true;
233  {
234  double xw, yw;
235 
236  double xwl = m_segments->Item( i ? i - 1 : 0 )->m_x1;
237  double ywl = m_segments->Item( i ? i - 1 : 0 )->m_y1;
238  a2dVpathCBCurveSegment* cseg = ( a2dVpathCBCurveSegment* ) seg.Get();
239 
240  int step;
241  double t = 0;
242  for ( step = 0; step <= SPLINE_STEP; step++ )
243  {
244  xw = xwl * pow( 1 - t, 3 ) + cseg->m_x2 * pow( 1 - t, 2 ) * t * 3 + cseg->m_x3 * ( 1 - t ) * t * t * 3 + cseg->m_x1 * pow( t, 3 );
245  yw = ywl * pow( 1 - t, 3 ) + cseg->m_y2 * pow( 1 - t, 2 ) * t * 3 + cseg->m_y3 * ( 1 - t ) * t * t * 3 + cseg->m_y1 * pow( t, 3 );
246  m_lworld.TransformPoint( xw, yw, x, y );
247  lpoints->push_back( new a2dLineSegment( x, y ) );
248  count++;
249  t = t + tstep;
250  }
251  }
252  break;
253 
255  nostrokeparts = true;
257  {
258  double xw, yw;
259 
260  double xwl = m_segments->Item( i ? i - 1 : 0 )->m_x1;
261  double ywl = m_segments->Item( i ? i - 1 : 0 )->m_y1;
262  a2dVpathQBCurveSegment* cseg = ( a2dVpathQBCurveSegment* ) seg.Get();
263 
264  int step;
265  double t = 0;
266  for ( step = 0; step <= SPLINE_STEP; step++ )
267  {
268  xw = xwl * pow( 1 - t, 2 ) + cseg->m_x2 * ( 1 - t ) * t * 2 + cseg->m_x1 * pow( t, 2 );
269  yw = ywl * pow( 1 - t, 2 ) + cseg->m_y2 * ( 1 - t ) * t * 2 + cseg->m_y1 * pow( t, 2 );
270  m_lworld.TransformPoint( xw, yw, x, y );
271  lpoints->push_back( new a2dLineSegment( x, y ) );
272  count++;
273  t = t + tstep;
274  }
275  }
276  break;
277 
279  nostrokeparts = true;
280  case a2dPATHSEG_ARCTO:
281  {
282  a2dVpathArcSegment* cseg = ( a2dVpathArcSegment* ) seg.Get();
283 
284  double radius, center_x, center_y, beginrad, midrad, endrad, phit;
285 
286  if ( cseg->CalcR( m_segments->Item( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
287  {
288  double dphi;
289  unsigned int segments;
290  a2dGlobals->Aberration( phit, radius , dphi, segments );
291 
292  double theta = beginrad;
293  unsigned int step;
294 
295  double x, y;
296  for ( step = 0; step < segments + 1; step++ )
297  {
298  m_lworld.TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
299  lpoints->push_back( new a2dLineSegment( x, y ) );
300  count++;
301  theta = theta + dphi;
302  }
303  }
304  else
305  {
306  double x, y;
307  m_lworld.TransformPoint( cseg->m_x1, cseg->m_y1, x, y );
308  lpoints->push_back( new a2dLineSegment( x, y ) );
309  count++;
310  }
311  }
312  break;
313  }
314 
315  if ( move )
316  {
317  a2dPolylineL* polyl = new a2dPolylineL( lpoints );
319  polyl->SetPathType( m_pathtype );
320  ret->push_back( polyl );
321  move = false;
322  lpoints = new a2dVertexList;
323  count = 0;
324  }
325  else if ( seg->GetClose() != a2dPATHSEG_END_OPEN )
326  {
327  if ( nostrokeparts || seg->GetClose() == a2dPATHSEG_END_CLOSED_NOSTROKE )
328  {
329  a2dPolygonL* poly = new a2dPolygonL( lpoints );
331  ret->push_back( poly );
332  nostrokeparts = true;
333  }
334  else
335  {
336  a2dPolygonL* poly = new a2dPolygonL( lpoints );
338  ret->push_back( poly );
339  }
340 
341  move = false;
342  lpoints = new a2dVertexList;
343  count = 0;
344  }
345  else if ( i == m_segments->size() - 1 ) //last segment?
346  {
347  a2dPolylineL* polyl = new a2dPolylineL( lpoints );
349  polyl->SetPathType( m_pathtype );
350  ret->push_back( polyl );
351  }
352  }
353 
354  if ( nostrokeparts )
355  {
356  move = false;
357  count = 0;
358  a2dVertexList* lpoints = new a2dVertexList();
359 
360  nostrokeparts = false;
361 
362  double lastmovex = 0;
363  double lastmovey = 0;
364 
365  for ( i = 0; i < m_segments->size(); i++ )
366  {
367  a2dVpathSegmentPtr seg = m_segments->Item( i );
368  switch ( seg->GetType() )
369  {
370  case a2dPATHSEG_MOVETO:
371  if ( count == 0 )
372  {
373  m_lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
374  lpoints->push_back( new a2dLineSegment( x, y ) );
375  lastmovex = x;
376  lastmovey = y;
377  count++;
378  }
379  else
380  {
381  i--;
382  move = true;
383  }
384  break;
385 
386  case a2dPATHSEG_LINETO:
387  m_lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
388  lpoints->push_back( new a2dLineSegment( x, y ) );
389  count++;
390  break;
391 
396  if ( count == 0 )
397  {
398  m_lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
399  lpoints->push_back( new a2dLineSegment( x, y ) );
400  count++;
401  }
402  else
403  {
404  i--;
405  nostrokeparts = true;
406  }
407  break;
408 
410  {
411  double xw, yw;
412 
413  double xwl = m_segments->Item( i ? i - 1 : 0 )->m_x1;
414  double ywl = m_segments->Item( i ? i - 1 : 0 )->m_y1;
415  a2dVpathCBCurveSegment* cseg = ( a2dVpathCBCurveSegment* ) seg.Get();
416 
417  int step;
418  double t = 0;
419  for ( step = 0; step <= SPLINE_STEP; step++ )
420  {
421  xw = xwl * pow( 1 - t, 3 ) + cseg->m_x2 * pow( 1 - t, 2 ) * t * 3 + cseg->m_x3 * ( 1 - t ) * t * t * 3 + cseg->m_x1 * pow( t, 3 );
422  yw = ywl * pow( 1 - t, 3 ) + cseg->m_y2 * pow( 1 - t, 2 ) * t * 3 + cseg->m_y3 * ( 1 - t ) * t * t * 3 + cseg->m_y1 * pow( t, 3 );
423  m_lworld.TransformPoint( xw, yw, x, y );
424  lpoints->push_back( new a2dLineSegment( x, y ) );
425  count++;
426  t = t + tstep;
427  }
428  }
429  break;
430 
432  {
433  double xw, yw;
434 
435  double xwl = m_segments->Item( i ? i - 1 : 0 )->m_x1;
436  double ywl = m_segments->Item( i ? i - 1 : 0 )->m_y1;
437  a2dVpathQBCurveSegment* cseg = ( a2dVpathQBCurveSegment* ) seg.Get();
438 
439  int step;
440  double t = 0;
441  for ( step = 0; step <= SPLINE_STEP; step++ )
442  {
443  xw = xwl * pow( 1 - t, 2 ) + cseg->m_x2 * ( 1 - t ) * t * 2 + cseg->m_x1 * pow( t, 2 );
444  yw = ywl * pow( 1 - t, 2 ) + cseg->m_y2 * ( 1 - t ) * t * 2 + cseg->m_y1 * pow( t, 2 );
445  m_lworld.TransformPoint( xw, yw, x, y );
446  lpoints->push_back( new a2dLineSegment( x, y ) );
447  count++;
448  t = t + tstep;
449  }
450  }
451  break;
452 
453  case a2dPATHSEG_ARCTO:
454  {
455  a2dVpathArcSegment* cseg = ( a2dVpathArcSegment* ) seg.Get();
456 
457  double radius, center_x, center_y, beginrad, midrad, endrad, phit;
458 
459  if ( cseg->CalcR( m_segments->Item( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
460  {
461  double dphi;
462  unsigned int segments;
463  a2dGlobals->Aberration( phit, radius , dphi, segments );
464 
465  double theta = beginrad;
466  unsigned int step;
467 
468  double x, y;
469  for ( step = 0; step < segments + 1; step++ )
470  {
471  m_lworld.TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
472  lpoints->push_back( new a2dLineSegment( x, y ) );
473  count++;
474  theta = theta + dphi;
475  }
476  }
477  else
478  {
479  double x, y;
480  m_lworld.TransformPoint( cseg->m_x1, cseg->m_y1, x, y );
481  lpoints->push_back( new a2dLineSegment( x, y ) );
482  count++;
483  }
484  }
485  break;
486  }
487 
488  if ( move || nostrokeparts )
489  {
490  a2dPolylineL* polyl = new a2dPolylineL( lpoints );
492  polyl->SetPathType( m_pathtype );
493  ret->push_back( polyl );
494  move = false;
495  nostrokeparts = false;
496  lpoints = new a2dVertexList();
497  count = 0;
498  }
499  else if ( seg->GetClose() != a2dPATHSEG_END_OPEN )
500  {
501  if ( seg->GetClose() == a2dPATHSEG_END_CLOSED )
502  {
503  lpoints->push_back( new a2dLineSegment( lastmovex, lastmovey ) );
504  count++;
505  }
506  a2dPolylineL* polyl = new a2dPolylineL( lpoints );
508  polyl->SetPathType( m_pathtype );
509  ret->push_back( polyl );
510  nostrokeparts = false;
511  move = false;
512  lpoints = new a2dVertexList;
513  count = 0;
514  }
515  else if ( i == m_segments->size() )
516  {
517  a2dPolylineL* polyl = new a2dPolylineL( lpoints );
519  polyl->SetPathType( m_pathtype );
520  ret->push_back( polyl );
521  }
522  }
523  }
524  return ret;
525 }
526 
528 {
529  m_segments->ConvertToLines();
530 }
531 
533 {
534  if ( !m_lworld.IsIdentity() )
535  {
536  m_segments->ConvertToLines();
537  unsigned int i;
538  for ( i = 0; i < m_segments->size() ; i++ )
539  {
540  m_lworld.TransformPoint( m_segments->Item( i )->m_x1, m_segments->Item( i )->m_y1,
541  m_segments->Item( i )->m_x1, m_segments->Item( i )->m_y1 );
542  }
543 
544  }
546 }
547 
548 a2dBoundingBox a2dVectorPath::DoGetUnTransformedBbox( a2dBboxFlags WXUNUSED( flags ) ) const
549 {
550  a2dBoundingBox bbox;
551  unsigned int i;
552  for ( i = 0; i < m_segments->size(); i++ )
553  {
554  a2dVpathSegmentPtr seg = m_segments->Item( i );
555  switch ( seg->GetType() )
556  {
559  {
560  a2dVpathCBCurveSegment* cseg = ( a2dVpathCBCurveSegment* ) seg.Get();
561  bbox.Expand( cseg->m_x2, cseg->m_y2 );
562  bbox.Expand( cseg->m_x3, cseg->m_y3 );
563  }
564  break;
565 
568  {
569  a2dVpathQBCurveSegment* cseg = ( a2dVpathQBCurveSegment* ) seg.Get();
570  bbox.Expand( cseg->m_x2, cseg->m_y2 );
571  }
572  break;
573 
574  case a2dPATHSEG_ARCTO:
576  {
577  a2dVpathArcSegment* cseg = ( a2dVpathArcSegment* ) seg.Get();
578 
579  double radius, center_x, center_y, beginrad, midrad, endrad, phit;
580 
581  //TODO soemthing to get the actual boundingbox of the arc
582  if ( cseg->CalcR( m_segments->Item( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
583  {
584  bbox.Expand( center_x + radius , center_y + radius );
585  bbox.Expand( center_x + radius , center_y - radius );
586  bbox.Expand( center_x - radius , center_y + radius );
587  bbox.Expand( center_x - radius , center_y - radius );
588  }
589 
590  bbox.Expand( cseg->m_x1, cseg->m_y1 );
591  bbox.Expand( cseg->m_x2, cseg->m_y2 );
592  }
593  break;
594  default:
595  break;
596  }
597  bbox.Expand( m_segments->Item( i )->m_x1, m_segments->Item( i )->m_y1 );
598  }
599  bbox.Enlarge( m_contourwidth );
600  return bbox;
601 }
602 
603 bool a2dVectorPath::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
604 {
605  //bezier curves stays within convex hull of polygon formed by control points
606  if ( !m_bbox.GetValid() )
607  {
610  return true;
611  }
612  return false;
613 
614 }
615 
616 void a2dVectorPath::DoRender( a2dIterC& ic, OVERLAP WXUNUSED( clipparent ) )
617 {
618  /* conversion test
619  a2dVpath* segments = new a2dVpath();
620  *segments = *m_segments;
621  segments->ConvertToLines();
622  DRAWER->DrawVpath( segments );
623  delete segments;
624  */
625 
626  //a2dBoundingBox bbox = DoGetUnTransformedBbox();
627  //DRAWER->DrawRoundedRectangle( bbox.GetMinX(), bbox.GetMinY(), bbox.GetWidth() ,bbox.GetHeight(), 0);
628 
629  if ( m_contourwidth )
630  {
631  a2dVpath* segments = new a2dVpath();
632  *segments = *m_segments;
633  segments->Contour( m_contourwidth / 2, m_pathtype );
634  ic.GetDrawer2D()->DrawVpath( segments );
635  delete segments;
636  }
637  else
638  ic.GetDrawer2D()->DrawVpath( m_segments );
639 }
640 
641 #if wxART2D_USE_CVGIO
642 
643 void a2dVectorPath::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
644 {
645  a2dCanvasObject::DoSave( parent, out, xmlparts, towrite );
646  if ( xmlparts == a2dXmlSer_attrib )
647  {
648  out.WriteAttribute( wxT( "segments" ), m_segments->size() );
649  }
650  else
651  {
652 
653  unsigned int i;
654  for ( i = 0; i < m_segments->size(); i++ )
655  {
656  if ( i % 2 == 0 )
657  out.WriteNewLine();
658  a2dVpathSegmentPtr seg = m_segments->Item( i );
659 
660  out.WriteStartElementAttributes( wxT( "seg" ) );
661  switch ( seg->m_type )
662  {
663  case a2dPATHSEG_MOVETO:
664  {
665  out.WriteAttribute( wxT( "type" ), wxT( "moveto" ) );
666  out.WriteAttribute( wxT( "x1" ), seg->m_x1 );
667  out.WriteAttribute( wxT( "y1" ), seg->m_y1 );
668  break;
669  }
670  case a2dPATHSEG_LINETO:
671  {
672  out.WriteAttribute( wxT( "type" ), wxT( "lineto" ) );
673  out.WriteAttribute( wxT( "x1" ), seg->m_x1 );
674  out.WriteAttribute( wxT( "y1" ), seg->m_y1 );
675  break;
676  }
678  {
679  out.WriteAttribute( wxT( "type" ), wxT( "lineto_nostroke" ) );
680  out.WriteAttribute( wxT( "x1" ), seg->m_x1 );
681  out.WriteAttribute( wxT( "y1" ), seg->m_y1 );
682  break;
683  }
684 
686  {
687  out.WriteAttribute( wxT( "type" ), wxT( "cb_curveto" ) );
688  out.WriteAttribute( wxT( "x1" ), seg->m_x1 );
689  out.WriteAttribute( wxT( "y1" ), seg->m_y1 );
690  a2dVpathCBCurveSegment* cseg = ( a2dVpathCBCurveSegment* ) seg.Get();
691  out.WriteAttribute( wxT( "x2" ), cseg->m_x2 );
692  out.WriteAttribute( wxT( "y2" ), cseg->m_y2 );
693  out.WriteAttribute( wxT( "x3" ), cseg->m_x3 );
694  out.WriteAttribute( wxT( "y3" ), cseg->m_y3 );
695  break;
696  }
698  {
699  out.WriteAttribute( wxT( "type" ), wxT( "cb_curveto_nostroke" ) );
700  out.WriteAttribute( wxT( "x1" ), seg->m_x1 );
701  out.WriteAttribute( wxT( "y1" ), seg->m_y1 );
702  a2dVpathCBCurveSegment* cseg = ( a2dVpathCBCurveSegment* ) seg.Get();
703  out.WriteAttribute( wxT( "x2" ), cseg->m_x2 );
704  out.WriteAttribute( wxT( "y2" ), cseg->m_y2 );
705  out.WriteAttribute( wxT( "x3" ), cseg->m_x3 );
706  out.WriteAttribute( wxT( "y3" ), cseg->m_y3 );
707  break;
708  }
709 
711  {
712  out.WriteAttribute( wxT( "type" ), wxT( "qb_curveto" ) );
713  out.WriteAttribute( wxT( "x1" ), seg->m_x1 );
714  out.WriteAttribute( wxT( "y1" ), seg->m_y1 );
715  a2dVpathQBCurveSegment* cseg = ( a2dVpathQBCurveSegment* ) seg.Get();
716  out.WriteAttribute( wxT( "x2" ), cseg->m_x2 );
717  out.WriteAttribute( wxT( "y2" ), cseg->m_y2 );
718  break;
719  }
721  {
722  out.WriteAttribute( wxT( "type" ), wxT( "qb_curveto_nostroke" ) );
723  out.WriteAttribute( wxT( "x1" ), seg->m_x1 );
724  out.WriteAttribute( wxT( "y1" ), seg->m_y1 );
725  a2dVpathQBCurveSegment* cseg = ( a2dVpathQBCurveSegment* ) seg.Get();
726  out.WriteAttribute( wxT( "x2" ), cseg->m_x2 );
727  out.WriteAttribute( wxT( "y2" ), cseg->m_y2 );
728  break;
729  }
730 
731  case a2dPATHSEG_ARCTO:
732  {
733  out.WriteAttribute( wxT( "type" ), wxT( "arcto" ) );
734  out.WriteAttribute( wxT( "x1" ), seg->m_x1 );
735  out.WriteAttribute( wxT( "y1" ), seg->m_y1 );
736  a2dVpathArcSegment* cseg = ( a2dVpathArcSegment* ) seg.Get();
737  out.WriteAttribute( wxT( "x2" ), cseg->m_x2 );
738  out.WriteAttribute( wxT( "y2" ), cseg->m_y2 );
739  break;
740  }
742  {
743  out.WriteAttribute( wxT( "type" ), wxT( "arcto_nostroke" ) );
744  out.WriteAttribute( wxT( "x1" ), seg->m_x1 );
745  out.WriteAttribute( wxT( "y1" ), seg->m_y1 );
746  a2dVpathArcSegment* cseg = ( a2dVpathArcSegment* ) seg.Get();
747  out.WriteAttribute( wxT( "x2" ), cseg->m_x2 );
748  out.WriteAttribute( wxT( "y2" ), cseg->m_y2 );
749  break;
750  }
751  default:
752  break;
753  }
754 
755  switch ( seg->m_close )
756  {
757  case a2dPATHSEG_END_OPEN:
758  {
759  out.WriteAttribute( wxT( "end" ), wxT( "open" ) );
760  break;
761  }
763  {
764  out.WriteAttribute( wxT( "end" ), wxT( "closed" ) );
765  break;
766  }
768  {
769  out.WriteAttribute( wxT( "end" ), wxT( "closed_nostroke" ) );
770  break;
771  }
772  }
773  out.WriteEndAttributes( true );
774  }
775  }
776 }
777 
778 void a2dVectorPath::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
779 {
780  a2dCanvasObject::DoLoad( parent, parser, xmlparts );
781  if ( xmlparts == a2dXmlSer_attrib )
782  {
783  }
784  else
785  {
786  while( parser.GetTagName() == wxT( "seg" ) )
787  {
788 
789  a2dVpathSegment* seg = NULL;
790 
791  wxString s1, s2;
792  double x1 = parser.GetAttributeValueDouble( wxT( "x1" ) );
793  double y1 = parser.GetAttributeValueDouble( wxT( "y1" ) );
794  double x2 = parser.GetAttributeValueDouble( wxT( "x2" ) ); //used when available
795  double y2 = parser.GetAttributeValueDouble( wxT( "y2" ) ); //used when available
796  double x3 = parser.GetAttributeValueDouble( wxT( "x3" ) ); //used when available
797  double y3 = parser.GetAttributeValueDouble( wxT( "y3" ) ); //used when available
798 
800  wxString send = parser.GetAttributeValue( wxT( "end" ) );
801  if ( send == wxT( "open" ) )
802  end = a2dPATHSEG_END_OPEN;
803  else if ( send == wxT( "closed" ) )
804  end = a2dPATHSEG_END_CLOSED;
805  else if ( send == wxT( "closed_nostroke" ) )
807 
808  wxString type = parser.GetAttributeValue( wxT( "type" ) );
809 
810  if ( type == wxT( "moveto" ) )
811  {
812  seg = new a2dVpathSegment( x1, y1 , a2dPATHSEG_MOVETO, end );
813  }
814  else if ( type == wxT( "lineto" ) )
815  {
816  seg = new a2dVpathSegment( x1, y1 , a2dPATHSEG_LINETO, end );
817  }
818  else if ( type == wxT( "lineto_nostroke" ) )
819  {
820  seg = new a2dVpathSegment( x1, y1 , a2dPATHSEG_LINETO_NOSTROKE, end );
821  }
822 
823  else if ( type == wxT( "cb_curveto" ) )
824  {
825  seg = new a2dVpathCBCurveSegment( x1, y1 , x2, y2, x3, y3, a2dPATHSEG_CBCURVETO, end );
826  }
827  else if ( type == wxT( "cb_curveto_nostroke" ) )
828  {
829  seg = new a2dVpathCBCurveSegment( x1, y1 , x2, y2, x3, y3, a2dPATHSEG_CBCURVETO_NOSTROKE, end );
830  }
831 
832  else if ( type == wxT( "qb_curveto" ) )
833  {
834  seg = new a2dVpathQBCurveSegment( x1, y1 , x2, y2, a2dPATHSEG_QBCURVETO, end );
835  }
836  else if ( type == wxT( "qb_curveto_nostroke" ) )
837  {
838  seg = new a2dVpathQBCurveSegment( x1, y1 , x2, y2, a2dPATHSEG_QBCURVETO_NOSTROKE, end );
839  }
840 
841  else if ( type == wxT( "arcto" ) )
842  {
843  seg = new a2dVpathArcSegment( x1, y1 , x2, y2, a2dPATHSEG_ARCTO, end );
844  }
845  else if ( type == wxT( "arcto_nostroke" ) )
846  {
847  seg = new a2dVpathArcSegment( x1, y1 , x2, y2, a2dPATHSEG_ARCTO_NOSTROKE, end );
848  }
849 
850  m_segments->push_back( seg );
851 
852  parser.Next();
853  parser.Require( END_TAG, wxT( "seg" ) );
854  parser.Next();
855  }
856  }
857 }
858 #endif //wxART2D_USE_CVGIO
859 
860 
862 {
863  a2dPoint2D P = a2dPoint2D( hitEvent.m_relx, hitEvent.m_rely );
864 
865  //TODO
866  //double pw = ic.GetTransformedHitMargin();
867  //how = PointInPolygon(P, pw/2+margin);
868 
869  hitEvent.m_how = a2dHit::stock_fill;
870  return hitEvent.m_how.IsHit();
871 }
872 
873 
874 
a2dHit m_how
return in which way the object was hit (stroke, fill, ...)
Definition: canobj.h:301
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
Definition: artglob.h:47
double m_relx
(world coordinates) hit point x relative to the canvas object its parent object(s) ...
Definition: canobj.h:289
bool IsPolygon(bool allowArc=true)
test if closed polygon ( a2dPATHSEG_MOVETO, a2dPATHSEG_LINETO, a2dPATHSEG_ARCTO ) ...
Definition: polyver.cpp:4025
virtual bool RestrictToObject(a2dIterC &ic, const a2dPoint2D &pointToSnapTo, a2dPoint2D &bestPointSofar, a2dSnapToWhatMask snapToWhat, double thresHoldWorld)
called from an a2dRestrictionEngine, to restrict vertexes, lines, object to this object.
Definition: vpath.cpp:82
bool DoUpdate(UpdateMode mode, const a2dBoundingBox &childbox, const a2dBoundingBox &clipbox, const a2dBoundingBox &propbox)
Update derived Object specific things ( mainly boundingbox)
Definition: vpath.cpp:603
void DoRender(a2dIterC &ic, OVERLAP clipparent)
render derived object
Definition: vpath.cpp:616
Quadratic Bezier curve.
Definition: polyver.h:984
void ConvertToLines()
Convert complex segments to line segments.
Definition: polyver.cpp:4184
double m_x2
control point
Definition: polyver.h:1025
XMLeventType Next()
Walks to next element and returns event type.
Definition: genxmlpars.cpp:422
class to map references to objects stored in XML, in order to make the connection later on...
Definition: gen.h:3462
const int SPLINE_STEP
number of steps when converting a spline to lines.
Definition: artglob.h:334
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
Clone this object and return a pointer to the new object.
Definition: vpath.cpp:62
Cubic Bezier curve.
Definition: polyver.h:1045
void Transform(const a2dAffineMatrix &world)
transform all segments with given matrix
Definition: polyver.cpp:4075
void WriteStartElementAttributes(const wxString &name, bool newLine=true)
Writes start tag which has attributes.
Definition: genxmlpars.cpp:757
polygon defined with list of points.
Definition: polygon.h:45
virtual void DrawVpath(const a2dVpath *path)
Draw vector path in world coordinates.
Definition: drawer2d.cpp:1568
bool EliminateMatrix()
reduce matrix to identity without replacing object
Definition: vpath.cpp:532
Ref Counted base object.
Definition: gen.h:1045
a2dCanvasObjectList * GetAsPolygons()
convert to a list of a2dPolygonL and a2dPolylineL
Definition: vpath.cpp:116
void Enlarge(const double Marge)
enlarge with the given amount
Definition: bbox.cpp:162
a2dCanvasObjectList * GetAsCanvasVpaths(bool transform=true) const
when implemented the object without its children, is converted to
Definition: vpath.cpp:67
a2dObject * Clone(CloneOptions options, a2dRefMap *refs=NULL) const
create an exact copy of this property
Definition: gen.cpp:1199
double m_y2
control point
Definition: polyver.h:1027
bool IsHit() const
true if this is a hit
Definition: polyver.h:107
double m_y3
control point 2
Definition: polyver.h:1100
Arc Segment.
Definition: polyver.h:1112
bool IsIdentity(void) const
Is the matrix the identity matrix?
Definition: afmatrix.h:147
double m_x3
control point 2
Definition: polyver.h:1098
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:819
bool DoIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
Does hit test on the object (exclusif child objects)
Definition: vpath.cpp:861
UpdateMode
Various mode flags for Update.
Definition: canobj.h:1091
OVERLAP
Result of a a2dBoundingBox intersection or hittest.
Definition: bbox.h:24
a2dGlobal * a2dGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: artglob.cpp:34
Arc Segment in a2dVertexList.
Definition: polyver.h:371
a2dVectorPath()
construct with empty array of segments
Definition: vpath.cpp:29
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: canobj.cpp:5728
a2dCanvasObject is the base class for Canvas Objects.
Definition: canobj.h:371
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: vpath.cpp:778
double m_y2
control point 1
Definition: polyver.h:1095
a2dPATHSEG_END GetClose() const
is this segment the closing a part since the last move
Definition: polyver.h:910
bool SetPointIfCloser(const a2dPoint2D &pointToSnapTo, const a2dPoint2D &pointToSnap, a2dPoint2D &bestPointSofar, double thresHoldWorld)
Definition: canobj.cpp:4189
vertex list of line and arc segments.
Definition: polyver.h:600
void TransformPoint(double x, double y, double &tx, double &ty) const
Transform a point.
Definition: afmatrix.cpp:559
virtual bool RestrictToObject(a2dIterC &ic, const a2dPoint2D &pointToSnapTo, a2dPoint2D &bestPointSofar, a2dSnapToWhatMask snapToWhat, double thresHoldWorld)
called from an a2dRestrictionEngine, to restrict vertexes, lines, object to this object.
Definition: canobj.cpp:4209
void SetContourWidth(double width)
set the Contour width of the shape
Definition: polygon.h:237
vector path a2dVectorPath derived from a2dCanvasObject
a2dAffineMatrix m_lworld
used for positioning the object (x,y,ang,scale etc.)
Definition: canobj.h:2559
snap to other objects its vertexes, which are decided in a2dCanvasObject::RestrictToObject() ...
Definition: restrict.h:116
void WriteNewLine()
Writes a new line and takes care of indentation.
Definition: genxmlpars.cpp:890
void SetPathType(a2dPATH_END_TYPE pathtype)
Set when m_contourwidth != 0 what is the end of the line should be.
Definition: polygon.h:401
double m_y2
second control point
Definition: polyver.h:1188
bool GetValid() const
returns true if boundingbox is calculated properly and therefore its valid flag is set...
Definition: bbox.cpp:299
void Expand(const a2dPoint2D &, const a2dPoint2D &)
expand boundingbox width two points
Definition: bbox.cpp:155
bool IsTranslate(void) const
Is the matrix only a translation?
Definition: afmatrix.h:359
a2dBoundingBox DoGetUnTransformedBbox(a2dBboxFlags flags=a2dCANOBJ_BBOX_NON) const
In derived object this should be overriden to calculate the boundingbox of the object without its chi...
Definition: vpath.cpp:548
polyline defined with list of points.
Definition: polygon.h:332
a2dDrawer2D * GetDrawer2D() const
get current a2dDrawer2D
Definition: canobj.cpp:636
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
a2dPATH_END_TYPE m_pathtype
when m_contourwidth != 0 what is the end of the line looking like.
Definition: vpath.h:201
Normal straight line segment in a2dVertexList and a2dVertexArray.
Definition: polyver.h:163
bool CalcR(a2dVpathSegmentPtr prev, double &radius, double &center_x, double &center_y, double &beginrad, double &midrad, double &endrad, double &phit)
Calculation of center for the Arc.
Definition: polyver.cpp:3820
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: canobj.cpp:5569
int m_datatype
GDSII compatible to sub identify this object.
Definition: vpath.h:198
void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: vpath.cpp:643
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:862
wxUint32 a2dSnapToWhatMask
mask for a2dSnapToWhat flags
Definition: restrict.h:26
void WriteEndAttributes(bool close=false)
&quot;Closes&quot; the start tag after writing all attributes (writes the &quot;&gt;&quot; or &quot;/&gt;&quot; bracket).
Definition: genxmlpars.cpp:837
double m_x2
control point 1
Definition: polyver.h:1093
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
double GetAttributeValueDouble(const wxString &attrib, double defaultv=0)
Returns the double value of an attribute.
Definition: genxmlpars.cpp:474
void Aberration(double angle, double radius, double &dphi, unsigned int &segments)
based on angle and radius and m_displayaberration calculate a proper delta phi and number of segments...
Definition: artglob.cpp:154
while iterating a a2dCanvasDocument, this holds the context.
Definition: canobj.h:3212
void MapBbox(const a2dAffineMatrix &matrix)
Definition: bbox.cpp:445
a2dPATHSEG GetType() const
easy way to test type of segment
Definition: polyver.h:901
wxString GetAttributeValue(const wxString &attrib, const wxString &defaultv=wxT(""))
Returns the value of an attribute.
Definition: genxmlpars.cpp:450
double m_y1
y endpoint of line
Definition: polyver.h:922
void Require(const XMLeventType &type, wxString name)
Forces a special tag.
Definition: genxmlpars.cpp:390
wxString GetTagName()
Returns name of the current XML tag.
Definition: genxmlpars.cpp:565
virtual bool EliminateMatrix()
reduce matrix to identity
Definition: canobj.cpp:6191
double m_contourwidth
if != 0 the continues path parts are contoured at distance m_contourwidth/2
Definition: vpath.h:195
bool IsPolyline(bool allowArc=true)
test if polyline ( a2dPATHSEG_MOVETO, a2dPATHSEG_LINETO, a2dPATHSEG_ARCTO )
Definition: polyver.cpp:4050
a2dPATHSEG_END
end of a segment type
Definition: polyver.h:863
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
Definition: bbox.h:39
void Contour(double distance, a2dPATH_END_TYPE pathtype)
create an offset contour at distance
Definition: polyver.cpp:4429
static a2dHit stock_fill
Stock object for a fill hit.
Definition: polyver.h:137
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
a2dCanvasObject for a Vector Path
Definition: vpath.h:55
a2dVpathSegmentPtr Item(size_t index) const
Definition: vpath.h:145
a2dBoundingBox m_bbox
boundingbox in world coordinates
Definition: canobj.h:2539
Vector Path.
Definition: polyver.h:1211
list of a2dObject&#39;s
Definition: gen.h:3157
double m_rely
(world coordinates) hit point y relative to the canvas object its parent object(s) ...
Definition: canobj.h:291
A pointer class, that automatically calls SmrtPtrOwn/SmrtPtrRelease.
Definition: a2dlist.h:20
CloneOptions
options for cloning
Definition: gen.h:1200
double m_x2
second control point
Definition: polyver.h:1186
structure to give as parameter to member functions of a2dCanvasObject
Definition: canobj.h:252
void ConvertToLines()
Convert complex segments to line segments.
Definition: vpath.cpp:527
vpath.cpp Source File -- Sun Oct 12 2014 17:04:26 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation