wxArt2D
curve.cpp
Go to the documentation of this file.
1 /*! \file curves/src/curve.cpp
2  \author Klaas Holwerda
3 
4  Copyright: 2000-2004 (c) Klaas Holwerda
5 
6  Licence: wxWidgets Licence
7 
8  RCS-ID: $Id: curve.cpp,v 1.42 2009/10/01 19:22:35 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/wfstream.h>
22 #include <math.h>
23 
24 #include "wx/canvas/eval.h"
25 
26 #include "wx/curves/meta.h"
27 
28 #include "wx/canvas/canglob.h"
29 #include "wx/canvas/canobj.h"
30 #include "wx/canvas/drawer.h"
31 #include "wx/canvas/canvas.h"
32 
33 #if wxART2D_USE_EDITOR
34 #include "wx/canvas/edit.h"
35 #endif //wxART2D_USE_EDITOR
36 
37 //----------------------------------------------------------------------------
38 // globals
39 //----------------------------------------------------------------------------
40 
41 IMPLEMENT_CLASS( a2dCurveObject, a2dCanvasObject )
42 IMPLEMENT_CLASS( a2dCurve, a2dCurveObject )
43 IMPLEMENT_DYNAMIC_CLASS( a2dFunctionCurve, a2dCurve )
44 IMPLEMENT_DYNAMIC_CLASS( a2dVertexCurve, a2dCurve )
45 IMPLEMENT_DYNAMIC_CLASS( a2dSweepCurve, a2dCurve )
46 IMPLEMENT_DYNAMIC_CLASS( a2dBandCurve, a2dCurve )
47 IMPLEMENT_DYNAMIC_CLASS( a2dBarCurve, a2dVertexCurve )
48 IMPLEMENT_DYNAMIC_CLASS( a2dVertexListCurve, a2dCurve )
49 IMPLEMENT_DYNAMIC_CLASS( a2dPieCurve, a2dCurve )
50 
51 
52 #ifdef wxUSE_INTPOINT
53 #define wxMAX_COORDINATE INT_MAX
54 #define wxMIN_COORDINATE INT_MIN
55 #else
56 #define wxMAX_COORDINATE 100e99
57 #define wxMIN_COORDINATE 100e-99
58 #endif
59 
60 
61 //! used to move points in VertexCurve objects
62 /*!
63 */
65 {
66 
67 public:
68 
69  static const a2dCommandId COMID_VertexCurveMovePoint;
70 
71  a2dCommand_VertexCurveMovePoint( a2dVertexCurve* curve, double x, double y, int index );
73 
74  bool Do( void );
75  bool Undo( void );
76 
77  inline a2dCanvasCommandProcessor* GetCanvasCmp() { return wxStaticCast( m_cmp, a2dCanvasCommandProcessor ); }
78 
79 protected:
80 
81  // x of point
82  double m_x;
83 
84  // y of point
85  double m_y;
86 
87  // index of point
88  int m_index;
89 
91 };
92 
93 const a2dCommandId a2dCommand_VertexCurveMovePoint::COMID_VertexCurveMovePoint( wxT( "VertexCurveMovePoint" ) );
94 
95 
96 /*
97 * a2dCommand_VertexCurveMovePoint
98 */
99 
100 a2dCommand_VertexCurveMovePoint::a2dCommand_VertexCurveMovePoint( a2dVertexCurve* curve, double x, double y, int index ):
101  a2dCommand( true, COMID_VertexCurveMovePoint )
102 {
103  m_x = x;
104  m_y = y;
105  m_index = index;
106 
107  m_curve = wxStaticCast( curve, a2dVertexCurve );
108 }
109 
110 a2dCommand_VertexCurveMovePoint::~a2dCommand_VertexCurveMovePoint( void )
111 {
112 }
113 
115 {
116  double x, y;
117  m_curve->GetPosXYPoint( m_index, x, y );
118  m_curve->SetPosXYPoint( m_index, m_x, m_y );
119  m_x = x;
120  m_y = y;
121 
122  m_curve->GetRoot()->Modify( true );
123  m_curve->GetRoot()->UpdateAllViews( a2dCANVIEW_UPDATE_OLDNEW );
124 
125  return true;
126 }
127 
129 {
130  m_curve->SetPosXYPoint( m_index, m_x, m_y );
131 
132  m_curve->GetRoot()->Modify( true );
133  m_curve->GetRoot()->UpdateAllViews( a2dCANVIEW_UPDATE_OLDNEW );
134 
135  a2dComEvent changed( this, m_curve );
136  ProcessEvent( changed );
137 
138  return true;
139 }
140 
141 //! used to move points in VertexCurve objects
142 /*!
143 */
145 {
146 
147 public:
148 
149  static const a2dCommandId COMID_SweepCurveMovePoint;
150 
151  a2dCommand_SweepCurveMovePoint( a2dSweepCurve* curve, double x, double y, int index );
152 
154 
155  bool Do( void );
156  bool Undo( void );
157 
158  inline a2dCanvasCommandProcessor* GetCanvasCmp() { return wxStaticCast( m_cmp, a2dCanvasCommandProcessor ); }
159 
160 protected:
161 
162  double m_sweep;
163 
164  // x of point
165  double m_x;
166 
167  // y of point
168  double m_y;
169 
170  // index of point
171  int m_index;
172 
174 };
175 
176 const a2dCommandId a2dCommand_SweepCurveMovePoint::COMID_SweepCurveMovePoint( wxT( "SweepCurveMovePoint" ) );
177 
178 /*
179 * a2dCommand_SweepCurveMovePoint
180 */
181 
182 a2dCommand_SweepCurveMovePoint::a2dCommand_SweepCurveMovePoint( a2dSweepCurve* curve, double x, double y, int index ):
183  a2dCommand( true, COMID_SweepCurveMovePoint )
184 {
185  m_x = x;
186  m_y = y;
187  m_index = index;
188 
189  m_curve = wxStaticCast( curve, a2dSweepCurve );
190 }
191 
192 a2dCommand_SweepCurveMovePoint::~a2dCommand_SweepCurveMovePoint( void )
193 {
194 }
195 
197 {
198  double x, y;
199  m_curve->GetPosXYPoint( m_index, x, y );
200  m_curve->SetPosXYPoint( m_index, m_x, m_y );
201  m_x = x;
202  m_y = y;
203 
204  m_curve->GetRoot()->Modify( true );
205  m_curve->GetRoot()->UpdateAllViews( a2dCANVIEW_UPDATE_OLDNEW );
206 
207  return true;
208 }
209 
211 {
212  m_curve->SetPosXYPoint( m_index, m_x, m_y );
213 
214  m_curve->GetRoot()->Modify( true );
215  m_curve->GetRoot()->UpdateAllViews( a2dCANVIEW_UPDATE_OLDNEW );
216 
217  a2dComEvent changed( this, m_curve );
218  ProcessEvent( changed );
219 
220  return true;
221 }
222 
223 //! used to move points in BandCurve objects
224 /*!
225 */
227 {
228 
229 public:
230 
231  static const a2dCommandId COMID_BandCurveMovePoint;
232 
233  a2dCommand_BandCurveMovePoint( a2dBandCurve* curve, double sweep, double y, bool up, int index );
234 
236 
237  bool Do( void );
238  bool Undo( void );
239 
240  inline a2dCanvasCommandProcessor* GetCanvasCmp() { return wxStaticCast( m_cmp, a2dCanvasCommandProcessor ); }
241 
242 protected:
243 
244  bool m_up;
245 
246  double m_sweep;
247 
248  // y of point
249  double m_y;
250 
251  // index of point
252  int m_index;
253 
254  a2dSmrtPtr<a2dBandCurve> m_curve;
255 };
256 
257 const a2dCommandId a2dCommand_BandCurveMovePoint::COMID_BandCurveMovePoint( wxT( "BandCurveMovePoint" ) );
258 
259 /*
260 * a2dCommand_BandCurveMovePoint
261 */
262 a2dCommand_BandCurveMovePoint::a2dCommand_BandCurveMovePoint( a2dBandCurve* curve, double sweep, double y, bool up, int index ):
263  a2dCommand( true, COMID_BandCurveMovePoint )
264 {
265  m_sweep = sweep;
266  m_up = up;
267  m_y = y;
268 
269  m_index = index;
270 
271  m_curve = wxStaticCast( curve, a2dBandCurve );
272 }
273 
274 a2dCommand_BandCurveMovePoint::~a2dCommand_BandCurveMovePoint( void )
275 {
276 }
277 
279 {
280  double sweep, y;
281 
282  m_curve->GetPosXYPoint( m_index, sweep, y, m_up );
283  m_curve->SetPosXYPoint( m_index, m_sweep, m_y, m_up );
284  m_sweep = sweep;
285  m_y = y;
286 
287  m_curve->GetRoot()->Modify( true );
288  m_curve->GetRoot()->UpdateAllViews( a2dCANVIEW_UPDATE_OLDNEW );
289 
290  return true;
291 }
292 
294 {
295  m_curve->SetPosXYPoint( m_index, m_sweep, m_y, m_up );
296 
297  m_curve->GetRoot()->Modify( true );
298  m_curve->GetRoot()->UpdateAllViews( a2dCANVIEW_UPDATE_OLDNEW );
299 
300  a2dComEvent changed( this, m_curve );
301  ProcessEvent( changed );
302 
303  return true;
304 }
305 
306 
307 /*
308 * a2dCommand_VertexListCurveMovePoint
309 */
310 
311 
312 //! used to move points in VertexCurve objects
313 /*!
314 */
316 {
317 
318 public:
319  a2dCommand_VertexListCurveMovePoint( a2dVertexListCurve* curve, double x, double y, int index );
320 
322 
323  bool Do( void );
324  bool Undo( void );
325 
326  inline a2dCanvasCommandProcessor* GetCanvasCmp() { return wxStaticCast( m_cmp, a2dCanvasCommandProcessor ); }
327 
328  static const a2dCommandId COMID_VertexListCurveMovePoint;
329 
330 protected:
331 
332  // x of point
333  double m_x;
334 
335  // y of point
336  double m_y;
337 
338  // index of point
339  int m_index;
340 
342 };
343 
344 const a2dCommandId a2dCommand_VertexListCurveMovePoint::COMID_VertexListCurveMovePoint( wxT( "VertexListCurveMovePoint" ) );
345 
346 a2dCommand_VertexListCurveMovePoint::a2dCommand_VertexListCurveMovePoint( a2dVertexListCurve* curve, double x, double y, int index ):
347  a2dCommand( true, COMID_VertexListCurveMovePoint )
348 {
349  m_x = x;
350  m_y = y;
351  m_index = index;
352 
353  m_curve = wxStaticCast( curve, a2dVertexListCurve ) ;
354 }
355 
356 a2dCommand_VertexListCurveMovePoint::~a2dCommand_VertexListCurveMovePoint( void )
357 {
358 }
359 
361 {
362  double x, y;
363  m_curve->GetPosXYPoint( m_index, x, y );
364  m_curve->SetPosXYPoint( m_index, m_x, m_y );
365  m_x = x;
366  m_y = y;
367 
368  m_curve->GetRoot()->Modify( true );
369  m_curve->GetRoot()->UpdateAllViews( a2dCANVIEW_UPDATE_OLDNEW );
370 
371  return true;
372 }
373 
375 {
376  m_curve->SetPosXYPoint( m_index, m_x, m_y );
377 
378  m_curve->GetRoot()->Modify( true );
379  m_curve->GetRoot()->UpdateAllViews( a2dCANVIEW_UPDATE_OLDNEW );
380 
381  a2dComEvent changed( this, m_curve );
382  ProcessEvent( changed );
383 
384  return true;
385 }
386 
387 
388 
389 //----------------------------------------------------------------------------
390 // a2dCurveObject
391 //----------------------------------------------------------------------------
392 
394 {
395  m_curvesArea = NULL;
396 }
397 
399 {
400 }
401 
402 //!copy constructor
404  : a2dCanvasObject( other, options, refs )
405 {
406  m_curvesArea = other.m_curvesArea;
408 }
409 
410 
411 void a2dCurveObject::World2Curve( double xw, double yw, double& xcurve, double& ycurve ) const
412 {
413  //wxASSERT_MSG( m_curvesArea != NULL, wxT("m_curvesArea not set") );
414 
415  if ( m_curvesArea )
416  m_curvesArea->World2Curve( xw, yw, xcurve, ycurve );
417  else
418  {
420  mat.Invert();
421  mat.TransformPoint( xw, yw, xcurve, ycurve );
422  }
423 }
424 
425 void a2dCurveObject::Curve2World( double xcurve, double ycurve, double& xw, double& yw ) const
426 {
427  //wxASSERT_MSG( m_curvesArea != NULL, wxT("m_curvesArea not set") );
428 
429  if ( m_curvesArea )
430  m_curvesArea->Curve2World( xcurve, ycurve, xw, yw );
431  else
432  {
433  m_lworld.TransformPoint( xcurve, ycurve, xw, yw );
434  }
435 }
436 
437 bool a2dCurveObject::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
438 {
439  if ( !m_bbox.GetValid() )
440  {
442  if ( m_bbox.GetValid() )
443  {
445  return true;
446  }
447  }
448 
449  return false;
450 }
451 
452 //----------------------------------------------------------------------------
453 // a2dCurve
454 //----------------------------------------------------------------------------
455 
456 a2dCurve::a2dCurve(): a2dCurveObject()
457 {
458  m_highlightmode = 0;
459  m_logFunction = wxNO_OP;
460  m_clipdata.SetValid( false );
461  m_curveBox.SetValid( false );
462 }
463 
464 a2dCurve::~a2dCurve()
465 {
466 }
467 
468 a2dCurve::a2dCurve( const a2dCurve& other, CloneOptions options, a2dRefMap* refs )
469  : a2dCurveObject( other, options, refs )
470 {
471  m_clipdata = other.m_clipdata;
472  m_highlightmode = other.m_highlightmode;
473  m_pointsFill = other.m_pointsFill;
474  m_logFunction = other.m_logFunction;
475  m_curveBox = other.m_curveBox;
476 }
477 
478 void a2dCurve::SetBoundaries( double xmin, double ymin, double xmax, double ymax )
479 {
480  SetPending( true );
481  m_clipdata.SetValid( false );
482  m_clipdata.Expand( xmin, ymin );
483  m_clipdata.Expand( xmax, ymax );
484 }
485 
486 #if wxART2D_USE_CVGIO
487 void a2dCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
488 {
489  a2dCanvasObject::DoSave( parent, out, xmlparts, towrite );
490  if ( xmlparts == a2dXmlSer_attrib )
491  {
492  if ( m_clipdata.GetValid() )
493  {
494  out.WriteAttribute( wxT( "xmin" ) , m_clipdata.GetMinX() );
495  out.WriteAttribute( wxT( "ymin" ) , m_clipdata.GetMinY() );
496  out.WriteAttribute( wxT( "xmax" ) , m_clipdata.GetMaxX() );
497  out.WriteAttribute( wxT( "ymax" ) , m_clipdata.GetMaxY() );
498  }
499  }
500  else
501  {
502  }
503 }
504 
505 void a2dCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
506 {
507  a2dCanvasObject::DoLoad( parent, parser, xmlparts );
508  if ( xmlparts == a2dXmlSer_attrib )
509  {
510  if ( parser.HasAttribute( wxT( "xmin" ) ) )
511  {
512  m_clipdata.SetValid( false );
513  m_clipdata.Expand( parser.GetAttributeValueDouble( wxT( "xmin" ) ), parser.RequireAttributeValueDouble( wxT( "ymin" ) ) );
514  m_clipdata.Expand( parser.GetAttributeValueDouble( wxT( "xmax" ) ), parser.RequireAttributeValueDouble( wxT( "ymax" ) ) );
515  }
516  }
517  else
518  {
519  }
520 }
521 #endif //wxART2D_USE_CVGIO
522 
523 
525 {
526  a2dBoundingBox curvebox = GetCurveBoundaries();
527  if ( m_clipdata.GetValid() )
528  {
529  if( !curvebox.And( &m_clipdata ) )
530  {
531  curvebox.SetValid( false );
532  return curvebox;
533  }
534  }
535 
537  if( curvebox.GetValid() && !curvebox.And( &areabox ) )
538  curvebox.SetValid( false );
539  return curvebox;
540 }
541 
543 {
544  return m_curveBox;
545  /*
546  a2dBoundingBox curvebox;
547  double xw1, yw1, xw2, yw2;
548  World2Curve( m_bbox.GetMinX(), m_bbox.GetMinY(), xw1, yw1 );
549  World2Curve( m_bbox.GetMaxX(), m_bbox.GetMaxY(), xw2, yw2 );
550  curvebox.Expand(xw1,yw1);
551  curvebox.Expand(xw1,yw2);
552  curvebox.Expand(xw2,yw1);
553  curvebox.Expand(xw2,yw2);
554  return curvebox;
555  */
556 }
557 
558 /*
559 double a2dCurve::GetBoundaryMinX()
560 {
561  double xw, yw;
562  World2Curve( m_bbox.GetMinX(), m_bbox.GetMinY(), xw, yw );
563  if ( m_clipdata.GetValid() )
564  {
565  double xmin = m_clipdata.GetMinX();
566  xw = wxMax( xmin, xw );
567  }
568  return wxMax( m_curvesArea->GetBoundaryMinX(), xw );
569 }
570 
571 double a2dCurve::GetBoundaryMaxX()
572 {
573  double xw, yw;
574  World2Curve( m_bbox.GetMaxX(), m_bbox.GetMaxY(), xw, yw );
575  if ( m_clipdata.GetValid() )
576  {
577  double xmax = m_clipdata.GetMaxX();
578  xw = wxMin( xmax, xw );
579  }
580  return wxMin( m_curvesArea->GetBoundaryMaxX(), xw );
581 }
582 
583 double a2dCurve::GetBoundaryMinY()
584 {
585  double xw, yw;
586  World2Curve( m_bbox.GetMinX(), m_bbox.GetMinY(), xw, yw );
587  if ( m_clipdata.GetValid() )
588  {
589  double ymin = m_clipdata.GetMinY();
590  yw = wxMax( ymin, yw );
591  }
592  return wxMax( m_curvesArea->GetBoundaryMinY(), yw );
593 }
594 
595 double a2dCurve::GetBoundaryMaxY()
596 {
597  double xw, yw;
598  World2Curve( m_bbox.GetMaxX(), m_bbox.GetMaxY(), xw, yw );
599  if ( m_clipdata.GetValid() )
600  {
601  double ymax = m_clipdata.GetMaxY();
602  yw = wxMin( ymax, yw );
603  }
604  return wxMin( m_curvesArea->GetBoundaryMaxY(), yw );
605 }
606 */
607 
608 //----------------------------------------------------------------------------
609 // a2dFunctionCurve
610 //----------------------------------------------------------------------------
611 
612 a2dFunctionCurve::a2dFunctionCurve( const wxString& curve ): a2dCurve()
613 {
614  m_curve = curve;
615 #if wxART2D_USE_CANEXTOBJ
616  m_toeval.SetEvalString( m_curve );
617 #endif //wxART2D_USE_CANEXTOBJ
618 
619  m_xstart = wxMIN_COORDINATE;
620  m_xstop = wxMAX_COORDINATE;
621  m_xstep = ( m_xstop - m_xstart ) / 100.0;
622 }
623 
624 a2dFunctionCurve::~a2dFunctionCurve()
625 {
626 }
627 
628 a2dFunctionCurve::a2dFunctionCurve( const a2dFunctionCurve& other, CloneOptions options, a2dRefMap* refs )
629  : a2dCurve( other, options, refs )
630 {
631  m_curve = other.m_curve;
632 #if wxART2D_USE_CANEXTOBJ
633  m_toeval.SetEvalString( m_curve );
634 #endif //wxART2D_USE_CANEXTOBJ
635  m_xstep = other.m_xstep;
636  m_xstart = other.m_xstart;
637  m_xstop = other.m_xstop;
638 }
639 
641 {
642  return new a2dFunctionCurve( *this, options, refs );
643 }
644 
645 bool a2dFunctionCurve::GetXyAtSweep( double sweepValue, a2dPoint2D& point ) const
646 {
647 #if wxART2D_USE_CANEXTOBJ
648  TYPENUMBER result;
649  int a;
650  m_toeval.ClearAllVars();
651 
652  m_toeval.SetValue( wxT( "x" ) , sweepValue );
653  m_toeval.Evaluate( &result, &a );
654  m_toeval.GetValue( wxT( "y" ) , &point.m_y );
655 
656  point.m_x = sweepValue;
657  return true;
658 #else
659  point.m_x = 0;
660  point.m_y = 0;
661  return false;
662 #endif //wxART2D_USE_CANEXTOBJ
663 }
664 
666 {
667  a2dBoundingBox bbox;
668  double x;
669  if ( m_clipdata.GetValid() )
670  {
671  m_curveBox.SetValid( false );
672  double start = wxMax( m_clipdata.GetMinX(), m_xstart );
673  double stop = wxMin( m_clipdata.GetMaxX(), m_xstop );
674  for ( x = start; x <= stop; x = x + m_xstep )
675  {
676  double xw, yw;
677  a2dPoint2D point;
678  GetXyAtSweep( x, point );
679  m_curveBox.Expand( point );
680  Curve2World( point.m_x, point.m_y, xw, yw );
681  bbox.Expand( xw , yw );
682  }
683  }
684  else
685  bbox.Expand( 0, 0 );
686  return bbox;
687 }
688 
689 bool a2dFunctionCurve::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
690 {
691  if ( !m_bbox.GetValid() )
692  {
695 
696  if ( m_clipdata.GetValid() )
697  {
698  double xw, yw;
700  a2dBoundingBox box;
701  box.Expand( xw, yw );
703  box.Expand( xw, yw );
704  box.MapBbox( m_lworld );
705 
706  m_bbox.And( &box );
707  }
708 
710  m_bbox.And( &box );
711  return true;
712  }
713 
714  return false;
715 }
716 
717 void a2dFunctionCurve::DoRender( a2dIterC& ic, OVERLAP WXUNUSED( clipparent ) )
718 {
720  if( !curvebox.GetValid() )
721  return;
722  double x;
723  bool second = false;
724  double xprev = 0, yprev = 0;
725  if ( m_clipdata.GetValid() )
726  {
727  wxRasterOperationMode prevlogfunction = wxNO_OP;
728  wxDC* aDC = NULL;
729  if( m_logFunction != wxNO_OP )
730  {
731  aDC = ic.GetDrawer2D()->GetRenderDC();
732  prevlogfunction = aDC->GetLogicalFunction();
733  aDC->SetLogicalFunction( m_logFunction );
734  }
735  for ( x = curvebox.GetMinX(); x < curvebox.GetMaxX(); x = x + m_xstep )
736  {
737  double xw, yw;
738  a2dPoint2D point;
739  GetXyAtSweep( x, point );
740  Curve2World( x, point.m_y, xw, yw );
741  if ( second )
742  {
743  ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
744  }
745  xprev = xw;
746  yprev = yw;
747  second = true;
748  }
749  if( aDC )
750  aDC->SetLogicalFunction( prevlogfunction );
751  }
752 }
753 
755 {
756  double pw = ic.GetWorldStrokeExtend();
757  double margin = ic.GetTransformedHitMargin();
758 
759  double xw, yw, xcurve, ycurve;
760  World2Curve( hitEvent.m_relx, hitEvent.m_rely, xcurve, ycurve );
761 
762  a2dPoint2D point;
763  GetXyAtSweep( xcurve, point );
764  Curve2World( point.m_x, point.m_y, xw, yw );
765 
766  if ( fabs( yw - hitEvent.m_rely ) < pw + margin )
767  {
769  return true;
770  }
771  else
772  {
773  hitEvent.m_how = a2dHit::stock_nohit;
774  return false;
775  }
776 }
777 
778 #if wxART2D_USE_CVGIO
779 void a2dFunctionCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
780 {
781  a2dCurve::DoSave( parent, out, xmlparts, towrite );
782  if ( xmlparts == a2dXmlSer_attrib )
783  {
784  }
785  else
786  {
787  }
788 }
789 
790 void a2dFunctionCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
791 {
792  a2dCurve::DoLoad( parent, parser, xmlparts );
793  if ( xmlparts == a2dXmlSer_attrib )
794  {
795  }
796  else
797  {
798  }
799 }
800 #endif //wxART2D_USE_CVGIO
801 
802 //----------------------------------------------------------------------------
803 // a2dVertexCurve
804 //----------------------------------------------------------------------------
805 BEGIN_EVENT_TABLE( a2dVertexCurve, a2dCurve )
806  EVT_CANVASOBJECT_MOUSE_EVENT( a2dVertexCurve::OnCanvasObjectMouseEvent )
807  EVT_CANVASOBJECT_ENTER_EVENT( a2dVertexCurve::OnEnterObject )
808  EVT_CANVASOBJECT_LEAVE_EVENT( a2dVertexCurve::OnLeaveObject )
809  EVT_CANVASHANDLE_MOUSE_EVENT( a2dVertexCurve::OnHandleEvent )
810 END_EVENT_TABLE()
811 
812 
813 a2dVertexCurve::a2dVertexCurve( a2dVertexArray* points ): a2dCurve()
814 {
815  m_points = points;
816  m_spline = false;
817  m_rendermode = a2dCURVES_RENDER_DEFAULT;
818  m_editmode = a2dCURVES_EDIT_DEFAULT;
819 }
820 
821 a2dVertexCurve::a2dVertexCurve( ): a2dCurve()
822 {
823  m_points = new a2dVertexArray;
824  m_spline = false;
825  m_rendermode = a2dCURVES_RENDER_DEFAULT;
826  m_editmode = a2dCURVES_EDIT_DEFAULT;
827 }
828 
829 
830 a2dVertexCurve::~a2dVertexCurve()
831 {
832  delete m_points;
833 }
834 
835 a2dVertexCurve::a2dVertexCurve( const a2dVertexCurve& other, CloneOptions options, a2dRefMap* refs )
836  : a2dCurve( other, options, refs )
837 {
838  m_points = new a2dVertexArray;
839  *m_points = *other.m_points;
840 
841  m_spline = other.m_spline;
842 
843  m_rendermode = other.m_rendermode;
844  m_editmode = other.m_editmode;
845 }
846 
848 {
849  return new a2dVertexCurve( *this, options, refs );
850 };
851 
853 {
854  if ( !m_lworld.IsIdentity() )
855  {
856  for( a2dVertexArray::const_iterator iter = m_points->begin(); iter != m_points->end(); ++iter )
857  {
858  a2dLineSegmentPtr seg = ( *iter )->Clone();
859  m_lworld.TransformPoint( seg->m_x, seg->m_y, seg->m_x, seg->m_y );
860  }
861 
862  }
863 
865 }
866 
867 void a2dVertexCurve::SetPosXYPoint( int n, double x, double y )
868 {
869  m_points->Item( n )->m_x = x;
870  m_points->Item( n )->m_y = y;
871 
872  SetPending( true );
873 }
874 
875 void a2dVertexCurve::RemovePoint( double& x, double& y , int index )
876 {
877  if ( index == -1 )
878  index = m_points->size();
879 
880  x = m_points->Item( index )->m_x;
881  y = m_points->Item( index )->m_y;
882  m_points->RemoveAt( index );
883 }
884 
885 void a2dVertexCurve::RemovePointWorld( double& x, double& y , int index, bool transformed )
886 {
887  if ( index == -1 )
888  index = m_points->size();
889 
890  x = m_points->Item( index )->m_x;
891  y = m_points->Item( index )->m_y;
892  m_points->RemoveAt( index );
893 
894  Curve2World( x, y, x, y );
895 
896  if ( transformed )
897  {
898  m_lworld.TransformPoint( x, y, x, y );
899  }
900 
901 }
902 
903 void a2dVertexCurve::AddPoint( const a2dPoint2D& P, int index )
904 {
905  AddPoint( P.m_x, P.m_y, index );
906 }
907 
908 void a2dVertexCurve::AddPoint( double x, double y, int index )
909 {
910  a2dLineSegment* point = new a2dLineSegment( x, y );
911 
912  if ( index == -1 )
913  m_points->push_back( point );
914  else
915  m_points->Insert( point, index );
916 
917  SetPending( true );
918 }
919 
920 void a2dVertexCurve::GetPosXYPoint( int index, double& x, double& y )
921 {
922  if ( index == -1 )
923  index = m_points->size();
924 
925  x = m_points->Item( index )->m_x;
926  y = m_points->Item( index )->m_y;
927 }
928 
929 void a2dVertexCurve::GetPosXYPointWorld( int index, double& x, double& y, bool transform )
930 {
931  if ( index == -1 )
932  index = m_points->size();
933 
934  x = m_points->Item( index )->m_x;
935  y = m_points->Item( index )->m_y;
936  Curve2World( x, y, x, y );
937 
938  if ( transform )
939  {
940  m_lworld.TransformPoint( x, y, x, y );
941  }
942 }
943 
944 bool a2dVertexCurve::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
945 {
946  if ( m_flags.m_editable )
947  {
948  if ( editmode == 1 )
949  {
950  m_flags.m_draggable = false;
951 
952  m_flags.m_visiblechilds = true;
954 
955  //add properties and handles as children in order to edit the object.
956  a2dVertexArray* array = GetPoints();
957  size_t i;
958  for ( i = 0; i < array->size(); i++ )
959  {
960  double xw, yw;
961  Curve2World( array->Item( i )->m_x, array->Item( i )->m_y, xw, yw );
962 
963  //not inclusive matrix so relative to polygon
964  a2dHandle* handle = new a2dHandle( this, xw, yw, wxT( "__index__" ) );
965  handle->SetLayer( m_layer );
966  Append( handle );
967  handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
968  PROPID_Index->SetPropertyToObject( handle, i );
969  }
971 
972  //calculate bbox's else mouse events may take place when first, and idle event is not yet
973  //processed to do this calculation.
975 
976  //still set it pending to do the redraw ( in place )
977  SetPending( true );
978  return true;
979  }
980  else
981  {
982  PROPID_Allowrotation->SetPropertyToObject( this, true );
983  PROPID_Allowskew->SetPropertyToObject( this, true );
984 
985  return a2dCanvasObject::DoStartEdit( editmode, editstyle );
986  }
987  }
988 
989  return false;
990 }
991 
992 bool a2dVertexCurve::GetXyAtSweep( double sweepValue, a2dPoint2D& point ) const
993 {
994  double xp, yp;
995  if( !m_points->size() )
996  return false;
997 
998  xp = m_points->Item( 0 )->m_x;
999  yp = m_points->Item( 0 )->m_y;
1000 
1001  if ( sweepValue <= m_points->Item( 0 )->m_x )
1002  {
1003  point.m_x = m_points->Item( 0 )->m_x;
1004  point.m_y = m_points->Item( 0 )->m_y;
1005  return false;
1006  }
1007 
1008  unsigned int i;
1009  for ( i = 0; i < m_points->size(); i++ )
1010  {
1011  if ( xp < sweepValue && m_points->Item( i )->m_x >= sweepValue )
1012  {
1013  point.m_x = sweepValue;
1014  point.m_y = ( m_points->Item( i )->m_y - yp ) * ( sweepValue - xp ) / ( m_points->Item( i )->m_x - xp ) + yp;
1015  return true;
1016  }
1017  xp = m_points->Item( i )->m_x;
1018  yp = m_points->Item( i )->m_y;
1019  }
1020 
1021  //return the end, so at least a normal value
1022  point.m_x = m_points->Item( i - 1 )->m_x;
1023  point.m_y = m_points->Item( i - 1 )->m_y;
1024 
1025  return false;
1026 }
1027 
1029 {
1030  a2dBoundingBox bbox;
1031  unsigned int i;
1032  double xw, yw;
1033  m_curveBox.SetValid( false );
1034  for ( i = 0; i < m_points->size(); i++ )
1035  {
1036  m_curveBox.Expand( m_points->Item( i )->m_x, m_points->Item( i )->m_y );
1037  Curve2World( m_points->Item( i )->m_x, m_points->Item( i )->m_y, xw, yw );
1038  bbox.Expand( xw, yw );
1039  }
1040  return bbox;
1041 }
1042 
1043 bool a2dVertexCurve::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
1044 {
1045  if ( !m_bbox.GetValid() && m_points->size() )
1046  {
1048  m_bbox.MapBbox( m_lworld );
1049 
1050  if ( m_clipdata.GetValid() )
1051  {
1052  double xw, yw;
1054  a2dBoundingBox box;
1055  box.Expand( xw, yw );
1057  box.Expand( xw, yw );
1058  box.MapBbox( m_lworld );
1059 
1060  m_bbox.And( &box );
1061  }
1062 
1064  m_bbox.And( &box );
1065  return true;
1066  }
1067  return false;
1068 }
1069 
1070 void a2dVertexCurve::DoRender( a2dIterC& ic, OVERLAP WXUNUSED( clipparent ) )
1071 {
1072 // double minx = GetBoundaryMinX();
1073 // double maxx = GetBoundaryMaxX();
1075  if( !curvebox.GetValid() )
1076  return;
1077 
1078  unsigned int i = 0;
1079  double xw, yw;
1080  if ( !( m_rendermode & a2dCURVES_RENDER_NO_POINTS ) )
1081  {
1082  a2dStroke current = ic.GetDrawer2D()->GetDrawerStroke();
1083  a2dFill fillcurrent = ic.GetDrawer2D()->GetDrawerFill();
1084 
1085  a2dStroke highlight = a2dStroke( wxColour( 239, 2, 0 ), 3 );
1086 
1087  if ( m_highlightmode )
1088  {
1089  ic.GetDrawer2D()->SetDrawerStroke( highlight );
1091  }
1092  else
1093  {
1096  }
1097 
1100 
1101  bool firstPoint = true;
1102  for ( i = 0; i < m_points->size(); i++ )
1103  {
1104  if ( m_points->Item( i )->m_x >= curvebox.GetMinX() )
1105  {
1106  if( firstPoint && i )
1107  {
1108  Curve2World( m_points->Item( i - 1 )->m_x, m_points->Item( i - 1 )->m_y, xw, yw );
1109  double xd, yd;
1110  matrix.TransformPoint( xw, yw, xd, yd );
1111 
1112  int radius = 2; //pixels
1113  ic.GetDrawer2D()->DrawCircle( xd, yd, radius );
1114  }
1115  firstPoint = false;
1116  Curve2World( m_points->Item( i )->m_x, m_points->Item( i )->m_y, xw, yw );
1117  double xd, yd;
1118  matrix.TransformPoint( xw, yw, xd, yd );
1119 
1120  int radius = 2; //pixels
1121  ic.GetDrawer2D()->DrawCircle( xd, yd, radius );
1122  }
1123  if ( m_points->Item( i )->m_x > curvebox.GetMaxX() )
1124  {
1125  Curve2World( m_points->Item( i )->m_x, m_points->Item( i )->m_y, xw, yw );
1126  double xd, yd;
1127  matrix.TransformPoint( xw, yw, xd, yd );
1128 
1129  int radius = 2; //pixels
1130  ic.GetDrawer2D()->DrawCircle( xd, yd, radius );
1131  break;
1132  }
1133  }
1134  ic.GetDrawer2D()->PopTransform();
1135 
1136  ic.GetDrawer2D()->SetDrawerStroke( current );
1137  ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
1138  }
1139 
1140  wxRasterOperationMode prevlogfunction = wxNO_OP;
1141  wxDC* aDC = NULL;
1142  if( m_logFunction != wxNO_OP )
1143  {
1144  aDC = ic.GetDrawer2D()->GetRenderDC();
1145  wxASSERT_MSG( aDC, wxT( "TODO: aDC not defined for aggdrawer" ) );
1146  prevlogfunction = aDC->GetLogicalFunction();
1147  aDC->SetLogicalFunction( m_logFunction );
1148  }
1149  if ( m_rendermode & a2dCURVES_RENDER_NORMAL )
1150  {
1151  double xprev = 0, yprev = 0;
1152  if( m_points->size() )
1153  Curve2World( m_points->Item( 0 )->m_x, m_points->Item( 0 )->m_y, xprev, yprev );
1154  int iprev = 0;
1155  for ( i = 1; i < m_points->size(); i++ )
1156  {
1157  if ( m_points->Item( i )->m_x >= curvebox.GetMinX() )
1158  {
1159  Curve2World( m_points->Item( i )->m_x, m_points->Item( i )->m_y, xw, yw );
1160  if( iprev != i - 1 )
1161  Curve2World( m_points->Item( i - 1 )->m_x, m_points->Item( i - 1 )->m_y, xprev, yprev );
1162  ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
1163  xprev = xw; yprev = yw;
1164  iprev = i;
1165  }
1166  if ( m_points->Item( i )->m_x > curvebox.GetMaxX() )
1167  break;
1168  }
1169  }
1170  else if ( m_rendermode & a2dCURVES_RENDER_FILL_LINE )
1171  {
1172  double xprev = 0, yprev = 0;
1173  double yw0;
1174  Curve2World( m_points->Item( i )->m_x, 0, xw, yw0 );
1175  for ( i = 1; i < m_points->size(); i++ )
1176  {
1177  if ( m_points->Item( i )->m_x >= curvebox.GetMinX() )
1178  {
1179  Curve2World( m_points->Item( i )->m_x, m_points->Item( i )->m_y, xw, yw );
1180  ic.GetDrawer2D()->DrawLine( xw, yw0, xw, yw );
1181  Curve2World( m_points->Item( i - 1 )->m_x, m_points->Item( i - 1 )->m_y, xprev, yprev );
1182  ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
1183  }
1184  if ( m_points->Item( i )->m_x > curvebox.GetMaxX() )
1185  break;
1186  }
1187  }
1188  else if ( m_rendermode & a2dCURVES_RENDER_FILL )
1189  {
1190  a2dVertexArray* cpoints = new a2dVertexArray;
1191 
1192  bool first = false;
1193 
1194  for ( i = 0; i < m_points->size(); i++ )
1195  {
1196  if ( m_points->Item( i )->m_x >= curvebox.GetMinX() )
1197  {
1198  Curve2World( m_points->Item( i )->m_x, m_points->Item( i )->m_y, xw, yw );
1199 
1200  if ( ! first )
1201  {
1202  double xw0, yw0;
1203  Curve2World( m_points->Item( i )->m_x, 0, xw0, yw0 );
1204  cpoints->push_back( new a2dLineSegment( xw0, yw0 ) );
1205  }
1206  cpoints->push_back( new a2dLineSegment( xw, yw ) );
1207  first = true;
1208  }
1209  if ( m_points->Item( i )->m_x > curvebox.GetMaxX() )
1210  break;
1211  }
1212  double xw0, yw0;
1213  Curve2World( m_points->Item( i - 1 )->m_x, 0, xw0, yw0 );
1214  cpoints->push_back( new a2dLineSegment( xw0, yw0 ) );
1215 
1216  ic.GetDrawer2D()->DrawPolygon( cpoints, false, wxWINDING_RULE );
1217  delete cpoints;
1218  }
1219  if( aDC )
1220  aDC->SetLogicalFunction( prevlogfunction );
1221 }
1222 
1223 #if wxART2D_USE_CVGIO
1224 void a2dVertexCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
1225 {
1226  a2dCurve::DoSave( parent, out, xmlparts, towrite );
1227  if ( xmlparts == a2dXmlSer_attrib )
1228  {
1229  if ( m_spline )
1230  {
1231  out.WriteAttribute( wxT( "spline" ) , m_spline );
1232  }
1233  out.WriteAttribute( wxT( "points" ) , m_points->size() );
1234  out.WriteAttribute( wxT( "rendermode" ) , m_rendermode );
1235  out.WriteAttribute( wxT( "editmode" ) , m_editmode );
1236  }
1237  else
1238  {
1239  unsigned int i;
1240  for ( i = 0; i < m_points->size(); i++ )
1241  {
1242  if ( i % 6 == 0 )
1243  out.WriteNewLine();
1244  out.WriteStartElementAttributes( wxT( "xy" ) );
1245  out.WriteAttribute( wxT( "x" ) , m_points->Item( i )->m_x );
1246  out.WriteAttribute( wxT( "y" ) , m_points->Item( i )->m_y );
1247  out.WriteEndAttributes( true );
1248  }
1249  }
1250 }
1251 
1252 void a2dVertexCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
1253 {
1254  a2dCurve::DoLoad( parent, parser, xmlparts );
1255  if ( xmlparts == a2dXmlSer_attrib )
1256  {
1257  m_spline = parser.GetAttributeValueBool( wxT( "spline" ), false );
1258  m_rendermode = parser.GetAttributeValueInt( wxT( "rendermode" ) );
1259  m_editmode = parser.GetAttributeValueInt( wxT( "editmode" ) );
1260  }
1261  else
1262  {
1263  while( parser.GetTagName() == wxT( "xy" ) )
1264  {
1265  double x = parser.GetAttributeValueDouble( wxT( "x" ) );
1266  double y = parser.GetAttributeValueDouble( wxT( "y" ) );
1267  a2dLineSegment* point = new a2dLineSegment( x, y );
1268  m_points->push_back( point );
1269 
1270  parser.Next();
1271  parser.Require( END_TAG, wxT( "xy" ) );
1272  parser.Next();
1273  }
1274  }
1275 }
1276 #endif //wxART2D_USE_CVGIO
1277 
1279 {
1280 
1281  double xcurve, ycurve;
1282  World2Curve( hitEvent.m_relx, hitEvent.m_rely, xcurve, ycurve );
1283 
1284  a2dPoint2D P = a2dPoint2D( xcurve, ycurve );
1285  double pw = ic.GetWorldStrokeExtend();
1286  double margin = ic.GetTransformedHitMargin();
1287 
1288  if ( PointOnCurve( P, pw + margin ) )
1289  {
1291  return true;
1292  }
1293  else
1294  {
1295  hitEvent.m_how = a2dHit::stock_nohit;
1296  return false;
1297  }
1298 }
1299 
1300 bool a2dVertexCurve::PointOnCurve( const a2dPoint2D& P, double margin )
1301 {
1302  bool result = false;
1303  double distance;
1304  a2dPoint2D p1, p2;
1305 
1306  if( m_points->size() )
1307  {
1308  p2 = m_points->Item( 0 )->GetPoint();
1309  unsigned int i;
1310  for ( i = 0; i < m_points->size() - 1; i++ )
1311  {
1312  p1 = p2;
1313  p2 = m_points->Item( i + 1 )->GetPoint();
1314  if ( margin > sqrt( pow( p1.m_x - P.m_x, 2 ) + pow( p1.m_y - P.m_y, 2 ) ) )
1315  {
1316  result = true;
1317  break;
1318  }
1319  else if ( !( ( p1.m_x == p2.m_x ) && ( p1.m_y == p2.m_y ) ) )
1320  {
1321  a2dLine line1( p1, p2 );
1322  if ( line1.PointInLine( P, distance, margin ) == R_IN_AREA )
1323  {
1324  result = true;
1325  break;
1326  }
1327  }
1328  }
1329  }
1330 
1331  return result;
1332 }
1333 
1334 void a2dVertexCurve::OnHandleEvent( a2dHandleMouseEvent& event )
1335 {
1336  a2dIterC* ic = event.GetIterC();
1337 
1338  if ( m_flags.m_editingCopy )
1339  {
1340  double xw, yw;
1341  xw = event.GetX();
1342  yw = event.GetY();
1343 
1344  a2dAffineMatrix atWorld = ic->GetTransform();
1345 
1346  //we need to get the matrix until the parent of the a2dHandle,
1347  // and not inclusif the handle itself.
1348  //and therefore apply inverted handle matrix.
1349  a2dAffineMatrix inverselocal = m_lworld;
1350  inverselocal.Invert();
1351 
1353 
1354  double xinternal, yinternal;
1355  inverse.TransformPoint( xw, yw, xinternal, yinternal );
1356  //now in relative world coordinates, and so one more to get to curve coordinates.
1357  World2Curve( xinternal, yinternal, xinternal, yinternal );
1358 
1359  a2dHandle* draghandle = event.GetCanvasHandle();
1360  wxUint16 index = PROPID_Index->GetPropertyValue( draghandle );
1361 
1362  wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
1363 
1364  if ( editmode == 1 )
1365  {
1366  if ( !( m_editmode & a2dCURVES_EDIT_NORMAL ) )
1367  {
1368  a2dPoint2D p1;
1369  p1 = m_points->Item( index )->GetPoint();
1370 
1371  if ( m_editmode & a2dCURVES_EDIT_FIXED_X )
1372  {
1373  xinternal = p1.m_x;
1374  }
1375  else if ( m_editmode & a2dCURVES_EDIT_FIXED_Y )
1376  {
1377  yinternal = p1.m_y;
1378  }
1379  }
1380 
1381  a2dVertexCurve* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dVertexCurve );
1382 
1383  double xwi;
1384  double ywi;
1385  Curve2World( xinternal, yinternal, xwi, ywi );
1386 
1387  if ( event.GetMouseEvent().LeftUp() )
1388  {
1389  if ( draghandle->GetName() == wxT( "__index__" ) )
1390  {
1391  m_root->GetCommandProcessor()->Submit( new a2dCommand_VertexCurveMovePoint( original, xinternal, yinternal, index ) );
1392  }
1393  else
1394  event.Skip(); //maybe the base class handles
1395  }
1396  else if ( event.GetMouseEvent().Dragging() )
1397  {
1398  SetPosXYPoint( index, xinternal, yinternal );
1399  draghandle->SetPosXY( xwi, ywi );
1400  }
1401  else
1402  event.Skip(); //maybe on the base class handles
1403  }
1404  else
1405  event.Skip();
1406  }
1407  else
1408  {
1409  event.Skip();
1410  }
1411 }
1412 
1413 void a2dVertexCurve::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
1414 {
1415  a2dIterC* ic = event.GetIterC();
1416 
1417  if ( m_flags.m_editingCopy )
1418  {
1419  //to world group coordinates to do hit test in world group coordinates
1420  double xw, yw;
1421  xw = event.GetX();
1422  yw = event.GetY();
1423 
1424  if ( event.GetMouseEvent().LeftDown() && ( m_editmode & a2dCURVES_EDIT_ALLOW_ADD ) )
1425  {
1426  if ( event.GetHow().IsEdgeHit() && !PROPID_FirstEventInObject->GetPropertyValue( this ) )
1427  {
1429 
1430  double xinternal, yinternal;
1431  inverse.TransformPoint( xw, yw, xw, yw );
1432  // now in relative world coordinates, and so one more to get to curve coordinates.
1433  World2Curve( xw, yw, xinternal, yinternal );
1434 
1435  //add point to original and editcopy, at the right place
1436  a2dVertexCurve* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dVertexCurve );
1437  double x, y;
1438  size_t i;
1439  int insertpos = -1;
1440  for ( i = 0; i < GetPoints()->size(); i++ )
1441  {
1442  GetPosXYPoint( i, x, y );
1443  if ( x < xinternal )
1444  insertpos = i;
1445  else
1446  break;
1447  }
1448  insertpos++;
1449 
1450  original->AddPoint( xinternal, yinternal, insertpos );
1451  AddPoint( xinternal, yinternal, insertpos );
1452 
1454  {
1456  {
1457  a2dCanvasObject* obj = *iter;
1458  a2dHandle* handle = wxDynamicCast( obj, a2dHandle );
1459  if ( handle && !handle->GetRelease( ) )
1460  {
1461  wxUint16 index = PROPID_Index->GetPropertyValue( handle );
1462  if ( index >= insertpos )
1463  PROPID_Index->SetPropertyToObject( handle, index + 1 );
1464  }
1465  }
1466  }
1467 
1468  //add handle for point
1469  a2dHandle* handle = new a2dHandle( this, xw, yw, wxT( "__index__" ) );
1471  Append( handle );
1472 
1473  handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
1474  PROPID_Index->SetPropertyToObject( handle, insertpos );
1475  ic->SetCorridorPath( true, handle );
1476  }
1477  else
1478  event.Skip();
1479  }
1480  else if ( event.GetMouseEvent().LeftDClick() )
1481  {
1482  EndEdit();
1483  }
1484  else if ( event.GetMouseEvent().Moving() )
1485  {
1486  event.Skip();
1487  }
1488  else
1489  event.Skip();
1490  }
1491  else
1492  event.Skip();
1493 }
1494 
1495 void a2dVertexCurve::OnEnterObject( a2dCanvasObjectMouseEvent& event )
1496 {
1497  a2dIterC* ic = event.GetIterC();
1498 
1499  //ic->GetTransform().DebugDump( "group", 0, 0);
1500 
1501  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS ) );
1502  // PushLayer(wxLAYER_ONTOP);
1503  m_highlightmode = 1;
1504  SetPending( true );
1505  event.Skip();
1506 }
1507 
1508 void a2dVertexCurve::OnLeaveObject( a2dCanvasObjectMouseEvent& event )
1509 {
1510  //a2dIterC* ic = event.GetIterC();
1511 
1512  event.Skip();
1513  // PopLayer();
1514  m_highlightmode = 0;
1515  SetPending( true );
1516 }
1517 
1518 
1519 
1520 //----------------------------------------------------------------------------
1521 // a2dSweepCurve
1522 //----------------------------------------------------------------------------
1523 a2dSweepPoint::a2dSweepPoint( double sweep, double a, double b )
1524 {
1525  m_sweep = sweep;
1526  m_a = a;
1527  m_b = b;
1528 }
1529 
1530 #include <wx/arrimpl.cpp>
1531 WX_DEFINE_OBJARRAY( a2dSweepPointArray );
1532 
1533 BEGIN_EVENT_TABLE( a2dSweepCurve, a2dCurve )
1534  EVT_CANVASOBJECT_MOUSE_EVENT( a2dSweepCurve::OnCanvasObjectMouseEvent )
1535  EVT_CANVASOBJECT_ENTER_EVENT( a2dSweepCurve::OnEnterObject )
1536  EVT_CANVASOBJECT_LEAVE_EVENT( a2dSweepCurve::OnLeaveObject )
1537  EVT_CANVASHANDLE_MOUSE_EVENT( a2dSweepCurve::OnHandleEvent )
1538 END_EVENT_TABLE()
1539 
1540 
1541 a2dSweepCurve::a2dSweepCurve( a2dSweepPointArray* points ): a2dCurve()
1542 {
1543  m_points = points;
1544  m_spline = false;
1545  m_rendermode = a2dCURVES_RENDER_DEFAULT;
1546  m_editmode = a2dCURVES_EDIT_DEFAULT;
1547 }
1548 
1549 a2dSweepCurve::a2dSweepCurve( ): a2dCurve()
1550 {
1551  m_points = new a2dSweepPointArray;
1552  m_spline = false;
1553  m_rendermode = a2dCURVES_RENDER_DEFAULT;
1554  m_editmode = a2dCURVES_EDIT_DEFAULT;
1555 }
1556 
1557 
1558 a2dSweepCurve::~a2dSweepCurve()
1559 {
1560  delete m_points;
1561 }
1562 
1563 a2dSweepCurve::a2dSweepCurve( const a2dSweepCurve& other, CloneOptions options, a2dRefMap* refs )
1564  : a2dCurve( other, options, refs )
1565 {
1566  m_points = new a2dSweepPointArray;
1567  unsigned int i;
1568  for ( i = 0; i < other.m_points->size(); i++ )
1569  m_points->push_back( new a2dSweepPoint( other.m_points->Item( i ) ) );
1570 
1571  m_spline = other.m_spline;
1572 
1573  m_rendermode = other.m_rendermode;
1574  m_editmode = other.m_editmode;
1575 }
1576 
1578 {
1579  return new a2dSweepCurve( *this, options, refs );
1580 };
1581 
1583 {
1584  unsigned int i;
1585  if ( !m_lworld.IsIdentity() )
1586  {
1587  for ( i = 0; i < m_points->size(); i++ )
1588  {
1589  m_lworld.TransformPoint( m_points->Item( i ).m_a, m_points->Item( i ).m_b, m_points->Item( i ).m_a, m_points->Item( i ).m_b );
1590  }
1591 
1592  }
1593 
1595 }
1596 
1597 void a2dSweepCurve::SetPosXYPoint( int n, double x, double y )
1598 {
1599  m_points->Item( n ).m_a = x;
1600  m_points->Item( n ).m_b = y;
1601 
1602  SetPending( true );
1603 }
1604 
1605 void a2dSweepCurve::RemovePoint( double& x, double& y , int index )
1606 {
1607  if ( index == -1 )
1608  index = m_points->size();
1609 
1610  x = m_points->Item( index ).m_a;
1611  y = m_points->Item( index ).m_b;
1612  m_points->RemoveAt( index );
1613 }
1614 
1615 void a2dSweepCurve::RemovePointWorld( double& x, double& y , int index, bool transformed )
1616 {
1617  if ( index == -1 )
1618  index = m_points->size();
1619 
1620  x = m_points->Item( index ).m_a;
1621  y = m_points->Item( index ).m_b;
1622  m_points->RemoveAt( index );
1623 
1624  Curve2World( x, y, x, y );
1625 
1626  if ( transformed )
1627  {
1628  m_lworld.TransformPoint( x, y, x, y );
1629  }
1630 
1631 }
1632 
1633 void a2dSweepCurve::AddPoint( double sweep, const a2dPoint2D& P )
1634 {
1635  AddPoint( sweep, P.m_x, P.m_y );
1636 }
1637 
1638 void a2dSweepCurve::AddPoint( double sweep, double x, double y )
1639 {
1640  a2dSweepPoint* point = new a2dSweepPoint( sweep, x, y );
1641 
1642  m_points->push_back( point );
1643  SetPending( true );
1644 }
1645 
1646 void a2dSweepCurve::GetPosXYPoint( int index, double& x, double& y )
1647 {
1648  if ( index == -1 )
1649  index = m_points->size();
1650 
1651  x = m_points->Item( index ).m_a;
1652  y = m_points->Item( index ).m_b;
1653 }
1654 
1655 void a2dSweepCurve::GetPosXYPointWorld( int index, double& x, double& y, bool transform )
1656 {
1657  if ( index == -1 )
1658  index = m_points->size();
1659 
1660  x = m_points->Item( index ).m_a;
1661  y = m_points->Item( index ).m_b;
1662  Curve2World( x, y, x, y );
1663 
1664  if ( transform )
1665  {
1666  m_lworld.TransformPoint( x, y, x, y );
1667  }
1668 }
1669 
1670 bool a2dSweepCurve::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
1671 {
1672  if ( m_flags.m_editable )
1673  {
1674  if ( editmode == 1 )
1675  {
1676  m_flags.m_draggable = false;
1677 
1678  m_flags.m_visiblechilds = true;
1680 
1681  //add properties and handles as children in order to edit the object.
1682  a2dSweepPointArray* array = GetPoints();
1683  size_t i;
1684  for ( i = 0; i < array->size(); i++ )
1685  {
1686  double xw, yw;
1687  Curve2World( array->Item( i ).m_a, array->Item( i ).m_b, xw, yw );
1688  a2dHandle* handle = new a2dHandle( this, xw, yw, wxT( "__index__" ) );
1689  handle->SetLayer( m_layer );
1690  Append( handle );
1691  handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
1692  PROPID_Index->SetPropertyToObject( handle, i );
1693 
1694  //not inclusive matrix so relative to polygon
1695  }
1696  m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT( "a2dHandle" ) );
1697 
1698  //calculate bbox's else mouse events may take place when first, and idle event is not yet
1699  //processed to do this calculation.
1701  //still set it pending to do the redraw ( in place )
1702  SetPending( true );
1703  return true;
1704  }
1705  else
1706  {
1707  PROPID_Allowrotation->SetPropertyToObject( this, true );
1708  PROPID_Allowskew->SetPropertyToObject( this, true );
1709 
1710  return a2dCanvasObject::DoStartEdit( editmode, editstyle );
1711  }
1712  }
1713 
1714  return false;
1715 }
1716 
1717 bool a2dSweepCurve::GetXyAtSweep( double sweepValue, a2dPoint2D& point ) const
1718 {
1719  double xp, yp;
1720  if( !m_points->size() )
1721  return false;
1722 
1723  xp = m_points->Item( 0 ).m_a;
1724  yp = m_points->Item( 0 ).m_b;
1725  if ( sweepValue <= m_points->Item( 0 ).m_a )
1726  {
1727  point.m_x = m_points->Item( 0 ).m_a;
1728  point.m_y = m_points->Item( 0 ).m_b;
1729  return false;
1730  }
1731 
1732  unsigned int i;
1733  for ( i = 0; i < m_points->size(); i++ )
1734  {
1735  if ( xp < sweepValue && m_points->Item( i ).m_a >= sweepValue )
1736  {
1737  point.m_x = sweepValue;
1738  point.m_y = ( m_points->Item( i ).m_b - yp ) * ( sweepValue - xp ) / ( m_points->Item( i ).m_a - xp ) + yp;
1739  return true;
1740  }
1741  xp = m_points->Item( i ).m_a;
1742  yp = m_points->Item( i ).m_b;
1743  }
1744 
1745  //return the end, so at least a normal value
1746  point.m_x = m_points->Item( i - 1 ).m_a;
1747  point.m_y = m_points->Item( i - 1 ).m_b;
1748 
1749  return false;
1750 }
1751 
1753 {
1754  a2dBoundingBox bbox;
1755  unsigned int i;
1756  double xw, yw;
1757  m_curveBox.SetValid( false );
1758  for ( i = 0; i < m_points->size(); i++ )
1759  {
1760  m_curveBox.Expand( m_points->Item( i ).m_a, m_points->Item( i ).m_b );
1761  Curve2World( m_points->Item( i ).m_a, m_points->Item( i ).m_b, xw, yw );
1762  bbox.Expand( xw, yw );
1763  }
1764  return bbox;
1765 }
1766 
1767 bool a2dSweepCurve::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
1768 {
1769  if ( !m_bbox.GetValid() && m_points->size() )
1770  {
1771  //trigger children ( markers etc. which normally do change when curve changes )
1774 
1776  m_bbox.MapBbox( m_lworld );
1777 
1778  if ( m_clipdata.GetValid() )
1779  {
1780  double xw, yw;
1782  a2dBoundingBox box;
1783  box.Expand( xw, yw );
1785  box.Expand( xw, yw );
1786  box.MapBbox( m_lworld );
1787 
1788  m_bbox.And( &box );
1789  }
1790 
1792  m_bbox.And( &box );
1793  return true;
1794  }
1795  return false;
1796 }
1797 
1798 void a2dSweepCurve::DoRender( a2dIterC& ic, OVERLAP WXUNUSED( clipparent ) )
1799 {
1800  // use next for clipping
1801  //double minx = GetBoundaryMinX();
1802  //double maxx = GetBoundaryMaxX();
1803 
1804  unsigned int i = 0;
1805  double xw, yw;
1806  if ( !( m_rendermode & a2dCURVES_RENDER_NO_POINTS ) )
1807  {
1808  a2dStroke current = ic.GetDrawer2D()->GetDrawerStroke();
1809  a2dFill fillcurrent = ic.GetDrawer2D()->GetDrawerFill();
1810 
1811  a2dStroke highlight = a2dStroke( wxColour( 239, 2, 0 ), 3 );
1812 
1813  if ( m_highlightmode )
1814  {
1815  ic.GetDrawer2D()->SetDrawerStroke( highlight );
1817  }
1818  else
1819  {
1822  }
1823 
1826 
1827  for ( i = 0; i < m_points->size(); i++ )
1828  {
1829  Curve2World( m_points->Item( i ).m_a, m_points->Item( i ).m_b, xw, yw );
1830  double xd, yd;
1831  matrix.TransformPoint( xw, yw, xd, yd );
1832 
1833  int radius = 2; //pixels
1834  ic.GetDrawer2D()->DrawCircle( xd, yd, radius );
1835  }
1836  ic.GetDrawer2D()->PopTransform();
1837 
1838  ic.GetDrawer2D()->SetDrawerStroke( current );
1839  ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
1840  }
1841 
1842  wxRasterOperationMode prevlogfunction = wxNO_OP;
1843  wxDC* aDC = NULL;
1844  if( m_logFunction != wxNO_OP )
1845  {
1846  aDC = ic.GetDrawer2D()->GetRenderDC();
1847  if( aDC )
1848  {
1849  prevlogfunction = aDC->GetLogicalFunction();
1850  aDC->SetLogicalFunction( m_logFunction );
1851  }
1852  }
1853  if ( m_rendermode & a2dCURVES_RENDER_NORMAL )
1854  {
1855  double xprev = 0, yprev = 0;
1856  for ( i = 1; i < m_points->size(); i++ )
1857  {
1858  Curve2World( m_points->Item( i ).m_a, m_points->Item( i ).m_b, xw, yw );
1859  Curve2World( m_points->Item( i - 1 ).m_a, m_points->Item( i - 1 ).m_b, xprev, yprev );
1860  ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
1861  }
1862  }
1863  else if ( m_rendermode & a2dCURVES_RENDER_FILL_LINE )
1864  {
1865  double xprev = 0, yprev = 0;
1866  double yw0;
1867  Curve2World( m_points->Item( i ).m_a, 0, xw, yw0 );
1868  for ( i = 1; i < m_points->size(); i++ )
1869  {
1870  Curve2World( m_points->Item( i ).m_a, m_points->Item( i ).m_b, xw, yw );
1871  ic.GetDrawer2D()->DrawLine( xw, yw0, xw, yw );
1872  Curve2World( m_points->Item( i - 1 ).m_a, m_points->Item( i - 1 ).m_b, xprev, yprev );
1873  ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
1874  }
1875  }
1876  else if ( m_rendermode & a2dCURVES_RENDER_FILL )
1877  {
1878  a2dVertexArray* cpoints = new a2dVertexArray();
1879 
1880  bool first = false;
1881 
1882  for ( i = 0; i < m_points->size(); i++ )
1883  {
1884  Curve2World( m_points->Item( i ).m_a, m_points->Item( i ).m_b, xw, yw );
1885 
1886  if ( ! first )
1887  {
1888  double xw0, yw0;
1889  Curve2World( m_points->Item( i ).m_a, 0, xw0, yw0 );
1890  cpoints->push_back( new a2dLineSegment( xw0, yw0 ) );
1891  }
1892  cpoints->push_back( new a2dLineSegment( xw, yw ) );
1893  first = true;
1894  }
1895  double xw0, yw0;
1896  Curve2World( m_points->Item( i - 1 ).m_a, 0, xw0, yw0 );
1897  cpoints->push_back( new a2dLineSegment( xw0, yw0 ) );
1898 
1899  ic.GetDrawer2D()->DrawPolygon( cpoints, false, wxWINDING_RULE );
1900  delete cpoints;
1901 
1902  double xprev = 0, yprev = 0;
1903  for ( i = 1; i < m_points->size(); i++ )
1904  {
1905  Curve2World( m_points->Item( i ).m_a, m_points->Item( i ).m_b, xw, yw );
1906  Curve2World( m_points->Item( i - 1 ).m_a, m_points->Item( i - 1 ).m_b, xprev, yprev );
1907  ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
1908  }
1909  }
1910  if( aDC )
1911  aDC->SetLogicalFunction( prevlogfunction );
1912 }
1913 
1914 #if wxART2D_USE_CVGIO
1915 void a2dSweepCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
1916 {
1917  a2dCurve::DoSave( parent, out, xmlparts, towrite );
1918  if ( xmlparts == a2dXmlSer_attrib )
1919  {
1920  if ( m_spline )
1921  {
1922  out.WriteAttribute( wxT( "spline" ) , m_spline );
1923  }
1924  out.WriteAttribute( wxT( "points" ) , m_points->size() );
1925  out.WriteAttribute( wxT( "rendermode" ) , m_rendermode );
1926  out.WriteAttribute( wxT( "editmode" ) , m_editmode );
1927  }
1928  else
1929  {
1930  unsigned int i;
1931  for ( i = 0; i < m_points->size(); i++ )
1932  {
1933  if ( i % 6 == 0 )
1934  out.WriteNewLine();
1935  out.WriteStartElementAttributes( wxT( "xy" ) );
1936  out.WriteAttribute( wxT( "x" ) , m_points->Item( i ).m_a );
1937  out.WriteAttribute( wxT( "y" ) , m_points->Item( i ).m_b );
1938  out.WriteEndAttributes( true );
1939  }
1940  }
1941 }
1942 
1943 void a2dSweepCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
1944 {
1945  a2dCurve::DoLoad( parent, parser, xmlparts );
1946  if ( xmlparts == a2dXmlSer_attrib )
1947  {
1948  m_spline = parser.GetAttributeValueBool( wxT( "spline" ), false );
1949  m_rendermode = parser.GetAttributeValueInt( wxT( "rendermode" ) );
1950  m_editmode = parser.GetAttributeValueInt( wxT( "editmode" ) );
1951  }
1952  else
1953  {
1954  while( parser.GetTagName() == wxT( "xy" ) )
1955  {
1956  double sweep = parser.GetAttributeValueDouble( wxT( "sweep" ) );
1957  double x = parser.GetAttributeValueDouble( wxT( "x" ) );
1958  double y = parser.GetAttributeValueDouble( wxT( "y" ) );
1959  a2dSweepPoint* point = new a2dSweepPoint( sweep, x, y );
1960  m_points->push_back( point );
1961 
1962  parser.Next();
1963  parser.Require( END_TAG, wxT( "xy" ) );
1964  parser.Next();
1965  }
1966  }
1967 }
1968 #endif //wxART2D_USE_CVGIO
1969 
1971 {
1972  double xcurve, ycurve;
1973  World2Curve( hitEvent.m_relx, hitEvent.m_rely, xcurve, ycurve );
1974 
1975  a2dPoint2D P = a2dPoint2D( xcurve, ycurve );
1976  double pw = ic.GetWorldStrokeExtend();
1977  double margin = ic.GetTransformedHitMargin();
1978 
1979  if ( PointOnCurve( P, pw + margin ) )
1980  {
1982  return true;
1983  }
1984  else
1985  {
1986  hitEvent.m_how = a2dHit::stock_nohit;
1987  return false;
1988  }
1989 }
1990 
1991 bool a2dSweepCurve::PointOnCurve( const a2dPoint2D& P, double margin )
1992 {
1993  bool result = false;
1994  double distance;
1995  a2dPoint2D p1, p2;
1996 
1997  if( m_points->size() )
1998  {
1999  p2 = m_points->Item( 0 ).GetPoint();
2000  unsigned int i;
2001  for ( i = 0; i < m_points->size() - 1; i++ )
2002  {
2003  p1 = p2;
2004  p2 = m_points->Item( i + 1 ).GetPoint();
2005  if ( margin > sqrt( pow( p1.m_x - P.m_x, 2 ) + pow( p1.m_y - P.m_y, 2 ) ) )
2006  {
2007  result = true;
2008  break;
2009  }
2010  else if ( !( ( p1.m_x == p2.m_x ) && ( p1.m_y == p2.m_y ) ) )
2011  {
2012  a2dLine line1( p1, p2 );
2013  if ( line1.PointInLine( P, distance, margin ) == R_IN_AREA )
2014  {
2015  result = true;
2016  break;
2017  }
2018  }
2019  }
2020  }
2021 
2022  return result;
2023 }
2024 
2025 void a2dSweepCurve::OnHandleEvent( a2dHandleMouseEvent& event )
2026 {
2027  a2dIterC* ic = event.GetIterC();
2028 
2029  if ( m_flags.m_editingCopy )
2030  {
2031  double xw, yw;
2032  xw = event.GetX();
2033  yw = event.GetY();
2034 
2035  a2dAffineMatrix atWorld = ic->GetTransform();
2036 
2037  //we need to get the matrix until the parent of the a2dHandle,
2038  // and not inclusif the handle itself.
2039  //and therefore apply inverted handle matrix.
2040  a2dAffineMatrix inverselocal = m_lworld;
2041  inverselocal.Invert();
2042 
2044 
2045  double xinternal, yinternal;
2046  inverse.TransformPoint( xw, yw, xinternal, yinternal );
2047  //now in relative world coordinates, and so one more to get to curve coordinates.
2048  World2Curve( xinternal, yinternal, xinternal, yinternal );
2049 
2050  a2dHandle* draghandle = event.GetCanvasHandle();
2051  wxUint16 index = PROPID_Index->GetPropertyValue( draghandle );
2052 
2053  wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
2054 
2055  if ( editmode == 1 )
2056  {
2057  if ( !( m_editmode & a2dCURVES_EDIT_NORMAL ) )
2058  {
2059  a2dPoint2D p1;
2060  p1 = m_points->Item( index ).GetPoint();
2061 
2062  if ( m_editmode & a2dCURVES_EDIT_FIXED_X )
2063  {
2064  xinternal = p1.m_x;
2065  }
2066  else if ( m_editmode & a2dCURVES_EDIT_FIXED_Y )
2067  {
2068  yinternal = p1.m_y;
2069  }
2070  }
2071 
2072  a2dSweepCurve* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dSweepCurve );
2073 
2074  double xwi;
2075  double ywi;
2076  Curve2World( xinternal, yinternal, xwi, ywi );
2077 
2078  if ( event.GetMouseEvent().LeftUp() )
2079  {
2080  if ( draghandle->GetName() == wxT( "__index__" ) )
2081  {
2082  m_root->GetCommandProcessor()->Submit( new a2dCommand_SweepCurveMovePoint( original, xinternal, yinternal, index ) );
2083  }
2084  else
2085  event.Skip(); //maybe the base class handles
2086  }
2087  else if ( event.GetMouseEvent().Dragging() )
2088  {
2089  SetPosXYPoint( index, xinternal, yinternal );
2090  draghandle->SetPosXY( xwi, ywi );
2091  }
2092  else
2093  event.Skip(); //maybe on the base class handles
2094  }
2095  else
2096  event.Skip();
2097  }
2098  else
2099  {
2100  event.Skip();
2101  }
2102 }
2103 
2104 void a2dSweepCurve::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
2105 {
2106  event.Skip();
2107 }
2108 
2109 void a2dSweepCurve::OnEnterObject( a2dCanvasObjectMouseEvent& event )
2110 {
2111  a2dIterC* ic = event.GetIterC();
2112 
2113  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS ) );
2114  // PushLayer(wxLAYER_ONTOP);
2115  m_highlightmode = 1;
2116  SetPending( true );
2117  event.Skip();
2118 }
2119 
2120 void a2dSweepCurve::OnLeaveObject( a2dCanvasObjectMouseEvent& event )
2121 {
2122  //a2dIterC* ic = event.GetIterC();
2123 
2124  event.Skip();
2125  // PopLayer();
2126  m_highlightmode = 0;
2127  SetPending( true );
2128 }
2129 
2130 
2131 //----------------------------------------------------------------------------
2132 // a2dCanvasBandCurveHandle
2133 //----------------------------------------------------------------------------
2134 IMPLEMENT_DYNAMIC_CLASS( a2dCanvasBandCurveHandle, a2dHandle )
2135 
2137  : a2dHandle( NULL, 0, 0, wxT( "dummy" ), 5, 5 )
2138 {
2139  m_index = 0;
2140  m_arcMid = false;
2141 }
2142 
2144  unsigned int index, bool arcMid, double xc, double yc, const wxString& name )
2145  : a2dHandle( parent, xc, yc, name )
2146 {
2147  m_index = index;
2148  m_arcMid = arcMid;
2149 }
2150 
2152  : a2dHandle( other, options, refs )
2153 {
2154  m_index = other.m_index;
2155  m_arcMid = other.m_arcMid;
2156 }
2157 
2159 {
2160 }
2161 
2162 //----------------------------------------------------------------------------
2163 // a2dBandCurve
2164 //----------------------------------------------------------------------------
2165 
2166 BEGIN_EVENT_TABLE( a2dBandCurve, a2dCurve )
2167  EVT_CANVASOBJECT_MOUSE_EVENT( a2dBandCurve::OnCanvasObjectMouseEvent )
2168  EVT_CANVASOBJECT_ENTER_EVENT( a2dBandCurve::OnEnterObject )
2169  EVT_CANVASOBJECT_LEAVE_EVENT( a2dBandCurve::OnLeaveObject )
2170  EVT_CANVASHANDLE_MOUSE_EVENT( a2dBandCurve::OnHandleEvent )
2171 END_EVENT_TABLE()
2172 
2173 
2174 a2dBandCurve::a2dBandCurve( a2dSweepPointArray* points ): a2dCurve()
2175 {
2176  m_points = points;
2177  m_spline = false;
2178  m_rendermode = a2dCURVES_RENDER_DEFAULT;
2179  m_editmode = a2dCURVES_EDIT_DEFAULT;
2180  m_markerUpLow = true;
2181 }
2182 
2183 a2dBandCurve::a2dBandCurve( ): a2dCurve()
2184 {
2185  m_points = new a2dSweepPointArray;
2186  m_spline = false;
2187  m_rendermode = a2dCURVES_RENDER_DEFAULT;
2188  m_editmode = a2dCURVES_EDIT_DEFAULT;
2189  m_markerUpLow = true;
2190 }
2191 
2192 
2193 a2dBandCurve::~a2dBandCurve()
2194 {
2195  delete m_points;
2196 }
2197 
2198 a2dBandCurve::a2dBandCurve( const a2dBandCurve& other, CloneOptions options, a2dRefMap* refs )
2199  : a2dCurve( other, options, refs )
2200 {
2201  m_points = new a2dSweepPointArray;
2202  unsigned int i;
2203  for ( i = 0; i < other.m_points->size(); i++ )
2204  m_points->push_back( new a2dSweepPoint( other.m_points->Item( i ) ) );
2205 
2206  m_spline = other.m_spline;
2207 
2208  m_rendermode = other.m_rendermode;
2209  m_editmode = other.m_editmode;
2210  m_markerUpLow = other.m_markerUpLow;
2211 }
2212 
2214 {
2215  return new a2dBandCurve( *this, options, refs );
2216 };
2217 
2219 {
2220  unsigned int i;
2221  if ( !m_lworld.IsIdentity() )
2222  {
2223  for ( i = 0; i < m_points->size(); i++ )
2224  {
2225  m_lworld.TransformPoint( m_points->Item( i ).m_a, m_points->Item( i ).m_b, m_points->Item( i ).m_a, m_points->Item( i ).m_b );
2226  }
2227 
2228  }
2229 
2231 }
2232 
2233 void a2dBandCurve::SetPosXYPoint( int index, double sweep, double y, bool upper )
2234 {
2235  m_points->Item( index ).m_sweep = sweep;
2236  if ( upper )
2237  m_points->Item( index ).m_b = y;
2238  else
2239  m_points->Item( index ).m_a = y;
2240 
2241  SetPending( true );
2242 }
2243 
2244 void a2dBandCurve::RemovePoint( double& sweep, double& y, bool upper, int index )
2245 {
2246  if ( index == -1 )
2247  index = m_points->size();
2248 
2249  sweep = m_points->Item( index ).m_sweep;
2250  if ( upper )
2251  y = m_points->Item( index ).m_b;
2252  else
2253  y = m_points->Item( index ).m_a;
2254 
2255  m_points->RemoveAt( index );
2256 }
2257 
2258 void a2dBandCurve::RemovePointWorld( double& sweep, double& y, bool upper, int index, bool transformed )
2259 {
2260  if ( index == -1 )
2261  index = m_points->size();
2262 
2263  sweep = m_points->Item( index ).m_sweep;
2264  if ( upper )
2265  y = m_points->Item( index ).m_b;
2266  else
2267  y = m_points->Item( index ).m_a;
2268 
2269  m_points->RemoveAt( index );
2270 
2271  Curve2World( sweep, y, sweep, y );
2272 
2273  if ( transformed )
2274  {
2275  m_lworld.TransformPoint( sweep, y, sweep, y );
2276  }
2277 
2278 }
2279 
2280 void a2dBandCurve::AddPoint( double sweep, const a2dPoint2D& P )
2281 {
2282  AddPoint( sweep, P.m_x, P.m_y );
2283 }
2284 
2285 void a2dBandCurve::AddPoint( double sweep, double x, double y )
2286 {
2287  a2dSweepPoint* point = new a2dSweepPoint( sweep, x, y );
2288 
2289  m_points->push_back( point );
2290  SetPending( true );
2291 }
2292 
2293 void a2dBandCurve::GetPosXYPoint( int index, double& sweep, double& y, bool upper )
2294 {
2295  if ( index == -1 )
2296  index = m_points->size();
2297 
2298  sweep = m_points->Item( index ).m_sweep;
2299  if ( upper )
2300  y = m_points->Item( index ).m_b;
2301  else
2302  y = m_points->Item( index ).m_a;
2303 }
2304 
2305 void a2dBandCurve::GetPosXYPointWorld( int index, double& sweep, double& y, bool transform, bool upper )
2306 {
2307  if ( index == -1 )
2308  index = m_points->size();
2309 
2310  sweep = m_points->Item( index ).m_sweep;
2311  if ( upper )
2312  y = m_points->Item( index ).m_b;
2313  else
2314  y = m_points->Item( index ).m_a;
2315  Curve2World( sweep, y, sweep, y );
2316 
2317  if ( transform )
2318  {
2319  m_lworld.TransformPoint( sweep, y, sweep, y );
2320  }
2321 }
2322 
2323 bool a2dBandCurve::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
2324 {
2325  if ( m_flags.m_editable )
2326  {
2327  if ( editmode == 1 )
2328  {
2329  m_flags.m_draggable = false;
2330 
2331  m_flags.m_visiblechilds = true;
2333 
2334  //add properties and handles as children in order to edit the object.
2335  a2dSweepPointArray* array = GetPoints();
2336  size_t i;
2337  for ( i = 0; i < array->size(); i++ )
2338  {
2339  double xw, yw, yw2;
2340  Curve2World( array->Item( i ).m_sweep, array->Item( i ).m_a, xw, yw );
2341  a2dCanvasBandCurveHandle* handle = new a2dCanvasBandCurveHandle( this, i, false, xw, yw, wxT( "__indexlow__" ) );
2342  handle->SetLayer( m_layer );
2343  Append( handle );
2344  Curve2World( array->Item( i ).m_sweep, array->Item( i ).m_b, xw, yw2 );
2345  handle = new a2dCanvasBandCurveHandle( this, i, false, xw, yw2, wxT( "__indexhigh__" ) );
2346  Append( handle );
2347  }
2348  m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT( "a2dHandle" ) );
2349 
2350  //calculate bbox's else mouse events may take place when first, and idle event is not yet
2351  //processed to do this calculation.
2353  //still set it pending to do the redraw ( in place )
2354  SetPending( true );
2355  return true;
2356  }
2357  else
2358  {
2359  PROPID_Allowrotation->SetPropertyToObject( this, true );
2360  PROPID_Allowskew->SetPropertyToObject( this, true );
2361 
2362  return a2dCanvasObject::DoStartEdit( editmode, editstyle );
2363  }
2364  }
2365 
2366  return false;
2367 }
2368 
2369 void a2dBandCurve::SyncHandlesWithLineSegments()
2370 {
2371  for( a2dCanvasObjectList::iterator iter = m_childobjects->begin(); iter != m_childobjects->end(); ++iter )
2372  {
2373  a2dCanvasObject* obj = *iter;
2374 
2376 
2377  if ( handle && !handle->GetRelease( ) )
2378  {
2379  unsigned int index = handle->GetIndex();
2380  double xw, yw;
2381  if ( handle->GetName() == wxT( "__indexlow__" ) )
2382  {
2383  Curve2World( m_points->Item( index ).m_sweep, m_points->Item( index ).m_a, xw, yw );
2384  handle->SetPosXY( xw, yw );
2385  }
2386  else if ( handle->GetName() == wxT( "__indexhigh__" ) )
2387  {
2388  Curve2World( m_points->Item( index ).m_sweep, m_points->Item( index ).m_b, xw, yw );
2389  handle->SetPosXY( xw, yw );
2390  }
2391  }
2392  }
2393 }
2394 
2395 void a2dBandCurve::OnHandleEvent( a2dHandleMouseEvent& event )
2396 {
2397  a2dIterC* ic = event.GetIterC();
2398 
2399  if ( m_flags.m_editingCopy )
2400  {
2401  double xw, yw;
2402  xw = event.GetX();
2403  yw = event.GetY();
2404 
2405  a2dAffineMatrix atWorld = ic->GetTransform();
2406 
2407  //we need to get the matrix until the parent of the a2dHandle,
2408  // and not inclusif the handle itself.
2409  //and therefore apply inverted handle matrix.
2410  a2dAffineMatrix inverselocal = m_lworld;
2411  inverselocal.Invert();
2412 
2414 
2415  double xinternal, yinternal;
2416  inverse.TransformPoint( xw, yw, xinternal, yinternal );
2417  //now in relative world coordinates, and so one more to get to curve coordinates.
2418  World2Curve( xinternal, yinternal, xinternal, yinternal );
2419 
2421  wxUint16 index = draghandle->GetIndex();
2422 
2423  wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
2424 
2425  if ( editmode == 1 )
2426  {
2427  if ( !( m_editmode & a2dCURVES_EDIT_NORMAL ) )
2428  {
2429  if ( m_editmode & a2dCURVES_EDIT_FIXED_X )
2430  {
2431  xinternal = m_points->Item( index ).m_sweep;
2432  }
2433  else if ( m_editmode & a2dCURVES_EDIT_FIXED_Y )
2434  {
2435  if ( draghandle->GetName() == wxT( "__indexlow__" ) )
2436  yinternal = m_points->Item( index ).m_a;
2437  else
2438  yinternal = m_points->Item( index ).m_b;
2439  }
2440  }
2441 
2442  a2dBandCurve* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dBandCurve );
2443 
2444  double xwi;
2445  double ywi;
2446  Curve2World( xinternal, yinternal, xwi, ywi );
2447 
2448  if ( event.GetMouseEvent().LeftUp() )
2449  {
2450  if ( draghandle->GetName() == wxT( "__indexlow__" ) )
2451  {
2452  m_root->GetCommandProcessor()->Submit( new a2dCommand_BandCurveMovePoint( original, xinternal, yinternal, false, index ) );
2453  SyncHandlesWithLineSegments();
2454  }
2455  else if ( draghandle->GetName() == wxT( "__indexhigh__" ) )
2456  {
2457  m_root->GetCommandProcessor()->Submit( new a2dCommand_BandCurveMovePoint( original, xinternal, yinternal, true, index ) );
2458  SyncHandlesWithLineSegments();
2459  }
2460  else
2461  event.Skip(); //maybe the base class handles
2462  }
2463  else if ( event.GetMouseEvent().Dragging() )
2464  {
2465  if ( draghandle->GetName() == wxT( "__indexlow__" ) )
2466  {
2467  SetPosXYPoint( index, xinternal, yinternal, false );
2468  }
2469  else if ( draghandle->GetName() == wxT( "__indexhigh__" ) )
2470  {
2471  SetPosXYPoint( index, xinternal, yinternal, true );
2472  }
2473  draghandle->SetPosXY( xwi, ywi );
2474  }
2475  else
2476  event.Skip(); //maybe on the base class handles
2477  }
2478  else
2479  event.Skip();
2480  }
2481  else
2482  {
2483  event.Skip();
2484  }
2485 }
2486 
2487 bool a2dBandCurve::GetXyAtSweep( double sweepValue, a2dPoint2D& point ) const
2488 {
2489  double xp, yp;
2490  if( !m_points->size() )
2491  return false;
2492 
2493 
2494  xp = m_points->Item( 0 ).m_sweep;
2495  if ( m_markerUpLow )
2496  yp = m_points->Item( 0 ).m_b;
2497  else
2498  yp = m_points->Item( 0 ).m_b;
2499  if ( sweepValue <= m_points->Item( 0 ).m_sweep )
2500  {
2501  point.m_x = m_points->Item( 0 ).m_sweep;
2502  if ( m_markerUpLow )
2503  point.m_y = m_points->Item( 0 ).m_b;
2504  else
2505  point.m_y = m_points->Item( 0 ).m_a;
2506  return false;
2507  }
2508 
2509  unsigned int i;
2510  for ( i = 0; i < m_points->size(); i++ )
2511  {
2512  if ( xp < sweepValue && m_points->Item( i ).m_sweep >= sweepValue )
2513  {
2514  point.m_x = sweepValue;
2515  if ( m_markerUpLow )
2516  point.m_y = ( m_points->Item( i ).m_b - yp ) * ( sweepValue - xp ) / ( m_points->Item( i ).m_sweep - xp ) + yp;
2517  else
2518  point.m_y = ( m_points->Item( i ).m_a - yp ) * ( sweepValue - xp ) / ( m_points->Item( i ).m_sweep - xp ) + yp;
2519 
2520  return true;
2521  }
2522  xp = m_points->Item( i ).m_sweep;
2523  if ( m_markerUpLow )
2524  yp = m_points->Item( i ).m_b;
2525  else
2526  yp = m_points->Item( i ).m_a;
2527  }
2528 
2529  //return the end, so at least a normal value
2530  point.m_x = m_points->Item( i - 1 ).m_sweep;
2531  if ( m_markerUpLow )
2532  point.m_y = m_points->Item( i - 1 ).m_b;
2533  else
2534  point.m_y = m_points->Item( i - 1 ).m_a;
2535  return false;
2536 }
2537 
2539 {
2540  a2dBoundingBox bbox;
2541  unsigned int i;
2542  double xw, yw;
2543  m_curveBox.SetValid( false );
2544  for ( i = 0; i < m_points->size(); i++ )
2545  {
2546  m_curveBox.Expand( m_points->Item( i ).m_sweep, m_points->Item( i ).m_a );
2547  Curve2World( m_points->Item( i ).m_sweep, m_points->Item( i ).m_a, xw, yw );
2548  bbox.Expand( xw, yw );
2549  m_curveBox.Expand( m_points->Item( i ).m_sweep, m_points->Item( i ).m_b );
2550  Curve2World( m_points->Item( i ).m_sweep, m_points->Item( i ).m_b, xw, yw );
2551  bbox.Expand( xw, yw );
2552  }
2553  return bbox;
2554 }
2555 
2556 bool a2dBandCurve::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
2557 {
2558  if ( !m_bbox.GetValid() && m_points->size() )
2559  {
2560  //trigger children ( markers etc. which normally do change when curve changes )
2563 
2565  m_bbox.MapBbox( m_lworld );
2566 
2567  if ( m_clipdata.GetValid() )
2568  {
2569  double xw, yw;
2571  a2dBoundingBox box;
2572  box.Expand( xw, yw );
2574  box.Expand( xw, yw );
2575  box.MapBbox( m_lworld );
2576 
2577  m_bbox.And( &box );
2578  }
2579 
2581  m_bbox.And( &box );
2582  return true;
2583  }
2584  return false;
2585 }
2586 
2587 void a2dBandCurve::DoRender( a2dIterC& ic, OVERLAP WXUNUSED( clipparent ) )
2588 {
2589 // double minx = GetBoundaryMinX();
2590 // double maxx = GetBoundaryMaxX();
2592  if( !curvebox.GetValid() )
2593  return ;
2594 
2595  unsigned int i;
2596  double xw, yw, yw2;
2597  if ( !( m_rendermode & a2dCURVES_RENDER_NO_POINTS ) )
2598  {
2599  a2dStroke current = ic.GetDrawer2D()->GetDrawerStroke();
2600  a2dFill fillcurrent = ic.GetDrawer2D()->GetDrawerFill();
2601 
2602  a2dStroke highlight = a2dStroke( wxColour( 239, 2, 0 ), 3 );
2603 
2604  if ( m_highlightmode )
2605  {
2606  ic.GetDrawer2D()->SetDrawerStroke( highlight );
2608  }
2609  else
2610  {
2613  }
2614 
2617 
2618  int radius = 2; //pixels
2619  for ( i = 0; i < m_points->size(); i++ )
2620  {
2621  if ( m_points->Item( i ).m_sweep >= curvebox.GetMinX() )
2622  {
2623  Curve2World( m_points->Item( i ).m_sweep, m_points->Item( i ).m_a, xw, yw );
2624  Curve2World( m_points->Item( i ).m_sweep, m_points->Item( i ).m_b, xw, yw2 );
2625  double xd, yd, xd2, yd2;
2626 
2627  matrix.TransformPoint( xw, yw, xd, yd );
2628  matrix.TransformPoint( xw, yw2, xd2, yd2 );
2629  ic.GetDrawer2D()->DrawCircle( xd, yd, radius );
2630  ic.GetDrawer2D()->DrawCircle( xd2, yd2, radius );
2631  }
2632  if ( m_points->Item( i ).m_sweep > curvebox.GetMaxX() )
2633  break;
2634  }
2635  ic.GetDrawer2D()->PopTransform();
2636 
2637  ic.GetDrawer2D()->SetDrawerStroke( current );
2638  ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
2639  }
2640 
2641  wxRasterOperationMode prevlogfunction = wxNO_OP;
2642  wxDC* aDC = NULL;
2643  if( m_logFunction != wxNO_OP )
2644  {
2645  aDC = ic.GetDrawer2D()->GetRenderDC();
2646  prevlogfunction = aDC->GetLogicalFunction();
2647  aDC->SetLogicalFunction( m_logFunction );
2648  }
2649  if ( m_rendermode & a2dCURVES_RENDER_NORMAL )
2650  {
2651  bool second = false;
2652  double xprev = 0, yprev = 0;
2653  for ( i = 0; i < m_points->size(); i++ )
2654  {
2655  if ( second && m_points->Item( i ).m_sweep >= curvebox.GetMinX() )
2656  {
2657  Curve2World( m_points->Item( i ).m_sweep, m_points->Item( i ).m_a, xw, yw );
2658  Curve2World( m_points->Item( i - 1 ).m_sweep, m_points->Item( i - 1 ).m_a, xprev, yprev );
2659  ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
2660  Curve2World( m_points->Item( i ).m_sweep, m_points->Item( i ).m_b, xw, yw2 );
2661  Curve2World( m_points->Item( i - 1 ).m_sweep, m_points->Item( i - 1 ).m_b, xprev, yprev );
2662  ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw2 );
2663  }
2664  if ( m_points->Item( i ).m_sweep > curvebox.GetMaxX() )
2665  break;
2666  second = true;
2667  }
2668  }
2669  else if ( m_rendermode & a2dCURVES_RENDER_FILL_LINE )
2670  {
2671  bool second = false;
2672  double xprev = 0, yprev = 0;
2673  for ( i = 0; i < m_points->size(); i++ )
2674  {
2675  if ( second && m_points->Item( i ).m_sweep >= curvebox.GetMinX() )
2676  {
2677  Curve2World( m_points->Item( i ).m_sweep, m_points->Item( i ).m_a, xw, yw );
2678  Curve2World( m_points->Item( i - 1 ).m_sweep, m_points->Item( i - 1 ).m_a, xprev, yprev );
2679  Curve2World( m_points->Item( i ).m_sweep, m_points->Item( i ).m_b, xw, yw2 );
2680  ic.GetDrawer2D()->DrawLine( xw, yw, xw, yw2 );
2681  ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
2682  Curve2World( m_points->Item( i - 1 ).m_sweep, m_points->Item( i - 1 ).m_b, xprev, yprev );
2683  ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw2 );
2684 
2685  }
2686  if ( m_points->Item( i ).m_sweep > curvebox.GetMaxX() )
2687  break;
2688  second = true;
2689  }
2690  }
2691  else if ( m_rendermode & a2dCURVES_RENDER_FILL )
2692  {
2693  a2dVertexArray* cpoints = new a2dVertexArray();
2694  for ( i = 0; i < m_points->size(); i++ )
2695  {
2696  Curve2World( m_points->Item( i ).m_sweep, m_points->Item( i ).m_a, xw, yw );
2697  Curve2World( m_points->Item( i ).m_sweep, m_points->Item( i ).m_b, xw, yw2 );
2698 
2699  cpoints->Insert( new a2dLineSegment( xw, yw ), 0 );
2700 
2701  cpoints->push_back( new a2dLineSegment( xw, yw2 ) );
2702  }
2703 
2704  ic.GetDrawer2D()->DrawPolygon( cpoints, false, wxWINDING_RULE );
2705  delete cpoints;
2706  }
2707  if( aDC )
2708  aDC->SetLogicalFunction( prevlogfunction );
2709 }
2710 
2711 #if wxART2D_USE_CVGIO
2712 void a2dBandCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
2713 {
2714  a2dCurve::DoSave( parent, out, xmlparts, towrite );
2715  if ( xmlparts == a2dXmlSer_attrib )
2716  {
2717  if ( m_spline )
2718  {
2719  out.WriteAttribute( wxT( "spline" ) , m_spline );
2720  }
2721  out.WriteAttribute( wxT( "points" ) , m_points->size() );
2722  out.WriteAttribute( wxT( "rendermode" ) , m_rendermode );
2723  out.WriteAttribute( wxT( "editmode" ) , m_editmode );
2724  }
2725  else
2726  {
2727  unsigned int i;
2728  for ( i = 0; i < m_points->size(); i++ )
2729  {
2730  if ( i % 6 == 0 )
2731  out.WriteNewLine();
2732  out.WriteStartElementAttributes( wxT( "ab" ) );
2733  out.WriteAttribute( wxT( "sweep" ) , m_points->Item( i ).m_sweep );
2734  out.WriteAttribute( wxT( "a" ) , m_points->Item( i ).m_a );
2735  out.WriteAttribute( wxT( "b" ) , m_points->Item( i ).m_b );
2736  out.WriteEndAttributes( true );
2737  }
2738  }
2739 }
2740 
2741 void a2dBandCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
2742 {
2743  a2dCurve::DoLoad( parent, parser, xmlparts );
2744  if ( xmlparts == a2dXmlSer_attrib )
2745  {
2746  m_spline = parser.GetAttributeValueBool( wxT( "spline" ), false );
2747  m_rendermode = parser.GetAttributeValueInt( wxT( "rendermode" ) );
2748  m_editmode = parser.GetAttributeValueInt( wxT( "editmode" ) );
2749  }
2750  else
2751  {
2752  while( parser.GetTagName() == wxT( "ab" ) )
2753  {
2754  double sweep = parser.GetAttributeValueDouble( wxT( "sweep" ) );
2755  double x = parser.GetAttributeValueDouble( wxT( "a" ) );
2756  double y = parser.GetAttributeValueDouble( wxT( "b" ) );
2757  a2dSweepPoint* point = new a2dSweepPoint( sweep, x, y );
2758  m_points->push_back( point );
2759 
2760  parser.Next();
2761  parser.Require( END_TAG, wxT( "ab" ) );
2762  parser.Next();
2763  }
2764  }
2765 }
2766 #endif //wxART2D_USE_CVGIO
2767 
2769 {
2770  double xh, yh;
2771  ic.GetInverseTransform().TransformPoint( hitEvent.m_x, hitEvent.m_y, xh, yh );
2772 
2773  double xcurve, ycurve;
2774  World2Curve( xh, yh, xcurve, ycurve );
2775 
2776  a2dPoint2D P = a2dPoint2D( xcurve, ycurve );
2777  double pw = ic.GetWorldStrokeExtend();
2778  double margin = ic.GetTransformedHitMargin();
2779 
2780  if ( PointOnCurve( P, pw + margin ) )
2781  {
2783  return true;
2784  }
2785  else
2786  {
2787  hitEvent.m_how = a2dHit::stock_nohit;
2788  return false;
2789  }
2790 }
2791 
2792 bool a2dBandCurve::PointOnCurve( const a2dPoint2D& P, double margin )
2793 {
2794  bool result = false;
2795  double distance;
2796  a2dPoint2D pup1, pup2, plow1, plow2;
2797 
2798  if( m_points->size() )
2799  {
2800  pup2 = m_points->Item( 0 ).GetPoint();
2801  unsigned int i;
2802  for ( i = 0; i < m_points->size() - 1; i++ )
2803  {
2804  R_PointStatus up = R_RIGHT_SIDE;
2805  R_PointStatus low = R_RIGHT_SIDE;
2806 
2807  pup1 = pup2;
2808  pup2 = m_points->Item( i + 1 ).GetPointUp();
2809  if ( margin > sqrt( pow( pup1.m_x - P.m_x, 2 ) + pow( pup1.m_y - P.m_y, 2 ) ) )
2810  {
2811  result = true;
2812  break;
2813  }
2814  else if ( !( ( pup1.m_x == pup2.m_x ) && ( pup1.m_y == pup2.m_y ) ) )
2815  {
2816  a2dLine line1( pup1, pup2 );
2817  if ( ( up = line1.PointInLine( P, distance, margin ) ) == R_IN_AREA )
2818  {
2819  result = true;
2820  break;
2821  }
2822  }
2823  plow1 = plow2;
2824  plow2 = m_points->Item( i + 1 ).GetPointLow();
2825  if ( margin > sqrt( pow( plow1.m_x - P.m_x, 2 ) + pow( plow1.m_y - P.m_y, 2 ) ) )
2826  {
2827  result = true;
2828  break;
2829  }
2830  else if ( !( ( plow1.m_x == plow2.m_x ) && ( plow1.m_y == plow2.m_y ) ) )
2831  {
2832  a2dLine line1( pup1, pup2 );
2833  if ( ( low = line1.PointInLine( P, distance, margin ) ) == R_IN_AREA )
2834  {
2835  result = true;
2836  break;
2837  }
2838  }
2839 
2840  if ( pup1.m_x > plow1.m_x && up == R_RIGHT_SIDE && low == R_LEFT_SIDE )
2841  {
2842  result = true;
2843  break;
2844  }
2845  if ( pup1.m_x < plow1.m_x && low == R_RIGHT_SIDE && up == R_LEFT_SIDE )
2846  {
2847  result = true;
2848  break;
2849  }
2850 
2851  }
2852  }
2853 
2854  return result;
2855 }
2856 
2857 void a2dBandCurve::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
2858 {
2859  event.Skip();
2860 }
2861 
2862 void a2dBandCurve::OnEnterObject( a2dCanvasObjectMouseEvent& event )
2863 {
2864  a2dIterC* ic = event.GetIterC();
2865 
2866  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS ) );
2867  // PushLayer(wxLAYER_ONTOP);
2868  m_highlightmode = 1;
2869  SetPending( true );
2870  event.Skip();
2871 }
2872 
2873 void a2dBandCurve::OnLeaveObject( a2dCanvasObjectMouseEvent& event )
2874 {
2875  //a2dIterC* ic = event.GetIterC();
2876 
2877  event.Skip();
2878  // PopLayer();
2879  m_highlightmode = 0;
2880  SetPending( true );
2881 }
2882 
2883 
2884 
2885 //----------------------------------------------------------------------------
2886 // a2dBarCurve
2887 //----------------------------------------------------------------------------
2888 const a2dPropertyIdRefObject a2dBarCurve::PROPID_extrudeFill( wxT( "extrudeFill" ), a2dPropertyId::flag_none, 0 );
2889 
2890 void a2dBarCurve::DoWalker( wxObject* parent, a2dWalkerIOHandler& handler )
2891 {
2892  handler.WalkTask( parent, this, a2dWalker_a2dDerivedCanvasObjectStart );
2893  a2dCanvasObject::DoWalker( parent, handler );
2894 
2895  handler.WalkTask( parent, this, a2dWalker_a2dDerivedCanvasObjectEnd );
2896 }
2897 
2898 a2dBarCurve::a2dBarCurve( a2dVertexArray* points ): a2dVertexCurve( points )
2899 {
2900  m_barwidth = 0;
2901  m_depth = m_barwidth / 2;
2902  m_angle3d = wxDegToRad( 30 );
2903  m_extrudeFill = *a2dBLACK_FILL;
2904  m_rendermode = a2dBAR_RENDER_NORMAL;
2905 }
2906 
2907 a2dBarCurve::a2dBarCurve( ): a2dVertexCurve()
2908 {
2909  m_barwidth = 0;
2910  m_depth = m_barwidth / 2;
2911  m_angle3d = wxDegToRad( 30 );
2912  m_extrudeFill = *a2dBLACK_FILL;
2913  m_rendermode = a2dBAR_RENDER_NORMAL;
2914 }
2915 
2916 
2917 a2dBarCurve::~a2dBarCurve()
2918 {
2919 }
2920 
2921 a2dBarCurve::a2dBarCurve( const a2dBarCurve& other, CloneOptions options, a2dRefMap* refs )
2922  : a2dVertexCurve( other, options, refs )
2923 {
2924  m_barwidth = other.m_barwidth;
2925  m_depth = other.m_depth;
2926  m_angle3d = other.m_angle3d;
2927 
2928  m_extrudeFill = other.m_extrudeFill;
2929 
2930 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
2931  //klion: it is because the CurrentSmartPointerOwner can change in property->TClone()
2932  CurrentSmartPointerOwner = this;
2933 #endif
2934 }
2935 
2937 {
2938  return new a2dBarCurve( *this, options, refs );
2939 };
2940 
2941 void a2dBarCurve::SetExtrudeFill( const a2dFill& fill )
2942 {
2943  m_extrudeFill = fill;
2944 }
2945 
2946 void a2dBarCurve::DoRender( a2dIterC& ic, OVERLAP WXUNUSED( clipparent ) )
2947 {
2948  double xw, yw;
2949  a2dStroke current = ic.GetDrawer2D()->GetDrawerStroke();
2950  a2dFill fillcurrent = ic.GetDrawer2D()->GetDrawerFill();
2951  if ( m_highlightmode )
2952  {
2953  a2dStroke tmps = a2dStroke( wxColour( 239, 232, 0 ), 3 );
2954  ic.GetDrawer2D()->SetDrawerStroke( tmps );
2956  }
2957  else
2958  {
2961  }
2962 
2965 
2966  if ( !( m_rendermode & a2dCURVES_RENDER_NO_POINTS ) )
2967  {
2968  unsigned int i;
2969  for ( i = 0; i < m_points->size(); i++ )
2970  {
2971  Curve2World( m_points->Item( i )->m_x, m_points->Item( i )->m_y, xw, yw );
2972 
2973  double xd, yd;
2974  matrix.TransformPoint( xw, yw, xd, yd );
2975  int radius = 2; //pixels
2976  ic.GetDrawer2D()->DrawCircle( xd, yd, radius );
2977  }
2978  }
2979  ic.GetDrawer2D()->PopTransform();
2980 
2981  ic.GetDrawer2D()->SetDrawerStroke( current );
2982  ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
2983 
2984  wxRasterOperationMode prevlogfunction = wxNO_OP;
2985  wxDC* aDC = NULL;
2986  if( m_logFunction != wxNO_OP )
2987  {
2988  aDC = ic.GetDrawer2D()->GetRenderDC();
2989  prevlogfunction = aDC->GetLogicalFunction();
2990  aDC->SetLogicalFunction( m_logFunction );
2991  }
2992 
2993  double yw0;
2994  Curve2World( m_points->Item( 0 )->m_x, 0, xw, yw0 );
2995  switch ( m_rendermode )
2996  {
2997  default:
2998  case a2dBAR_RENDER_NORMAL:
2999  {
3000  double w2 = m_barwidth / 2;
3001  unsigned int i;
3002  a2dlist< a2dFill >::iterator iter = m_pointsFill.begin();
3003  for ( i = 0; i < m_points->size(); i++ )
3004  {
3005  if ( m_pointsFill.size() )
3006  ic.GetDrawer2D()->SetDrawerFill( *iter );
3007 
3008  Curve2World( m_points->Item( i )->m_x, m_points->Item( i )->m_y, xw, yw );
3009  ic.GetDrawer2D()->DrawRoundedRectangle( xw - w2, yw0, m_barwidth, yw - yw0, 0 );
3010 
3011  iter = m_pointsFill.GetNextAround( iter );
3012  }
3013  break;
3014  }
3015  case a2dBAR_RENDER_3D:
3016  {
3017  a2dVertexArray* cpoints = new a2dVertexArray;
3018  double w2 = m_barwidth / 2;
3019 
3020  a2dlist< a2dFill >::iterator iter = m_pointsFill.begin();
3021  unsigned int i;
3022  for ( i = 0; i < m_points->size(); i++ )
3023  {
3024  Curve2World( m_points->Item( i )->m_x, m_points->Item( i )->m_y, xw, yw );
3025  double barx = xw;
3026  double barlow = yw0;
3027  double barheight = yw;
3028 
3029  if ( barheight < 0 )
3030  {
3031  barlow = yw;
3032  barheight = 0;
3033  }
3034 
3035  ic.GetDrawer2D()->SetDrawerFill( m_extrudeFill );
3036 
3037  //top plate
3038  cpoints->clear();
3039  cpoints->push_back( new a2dLineSegment( barx - w2, barheight ) );
3040  cpoints->push_back( new a2dLineSegment( barx - w2 + cos( m_angle3d - wxPI / 30 )*m_depth, barheight + sin( m_angle3d - wxPI / 30 )*m_depth ) );
3041  cpoints->push_back( new a2dLineSegment( barx + w2 + cos( m_angle3d )*m_depth, barheight + sin( m_angle3d - wxPI / 30 )*m_depth ) );
3042  cpoints->push_back( new a2dLineSegment( barx + w2, barheight ) );
3043  ic.GetDrawer2D()->DrawPolygon( cpoints, false, wxWINDING_RULE );
3044 
3045  //side plate
3046  cpoints->clear();
3047  cpoints->push_back( new a2dLineSegment( barx + w2, barheight ) );
3048  cpoints->push_back( new a2dLineSegment( barx + w2 + cos( m_angle3d )*m_depth, barheight + sin( m_angle3d - wxPI / 30 )*m_depth ) );
3049  cpoints->push_back( new a2dLineSegment( barx + w2 + cos( m_angle3d )*m_depth, barlow + sin( m_angle3d )*m_depth ) );
3050  cpoints->push_back( new a2dLineSegment( barx + w2, barlow ) );
3051 
3052  ic.GetDrawer2D()->DrawPolygon( cpoints, false, wxWINDING_RULE );
3053 
3054  if ( m_pointsFill.size() )
3055  ic.GetDrawer2D()->SetDrawerFill( *iter );
3056  else
3057  ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
3058 
3059  ic.GetDrawer2D()->DrawRoundedRectangle( xw - w2, yw0, m_barwidth, yw - yw0, 0 );
3060 
3061  iter = m_pointsFill.GetNextAround( iter );
3062  }
3063  delete cpoints;
3064  break;
3065  }
3066  case a2dBAR_RENDER_LINE:
3067  {
3068  unsigned int i;
3069  for ( i = 0; i < m_points->size(); i++ )
3070  {
3071  Curve2World( m_points->Item( i )->m_x, m_points->Item( i )->m_y, xw, yw );
3072  ic.GetDrawer2D()->DrawLine( xw, yw0, xw, yw );
3073  }
3074  break;
3075  }
3076  }
3077  if( aDC )
3078  aDC->SetLogicalFunction( prevlogfunction );
3079 
3080  ic.GetDrawer2D()->SetDrawerStroke( current );
3081  ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
3082 }
3083 
3084 #if wxART2D_USE_CVGIO
3085 void a2dBarCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
3086 {
3087  a2dVertexCurve::DoSave( parent, out, xmlparts, towrite );
3088  if ( xmlparts == a2dXmlSer_attrib )
3089  {
3090  out.WriteAttribute( wxT( "barwidth" ) , m_barwidth );
3091  out.WriteAttribute( wxT( "depth" ) , m_depth );
3092  out.WriteAttribute( wxT( "angle3d" ) , m_angle3d );
3093  }
3094  else
3095  {
3096  out.WriteStartElement( wxT( "derived" ) );
3097  m_extrudeFill.Save( this, out, towrite );
3098  out.WriteEndElement();
3099  }
3100 }
3101 
3102 void a2dBarCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
3103 {
3104  a2dVertexCurve::DoLoad( parent, parser, xmlparts );
3105  if ( xmlparts == a2dXmlSer_attrib )
3106  {
3107  m_barwidth = parser.RequireAttributeValueDouble( wxT( "barwidth" ) );
3108  m_depth = parser.RequireAttributeValueDouble( wxT( "depth" ) );
3109  m_angle3d = parser.RequireAttributeValueDouble( wxT( "angle3d" ) );
3110  }
3111  else
3112  {
3113  parser.Require( START_TAG, wxT( "derived" ) );
3114  parser.Next();
3115  m_extrudeFill.Load( parent, parser );
3116  parser.Require( END_TAG, wxT( "derived" ) );
3117  parser.Next();
3118  }
3119 }
3120 #endif //wxART2D_USE_CVGIO
3121 
3122 
3123 
3124 //----------------------------------------------------------------------------
3125 // a2dVertexListCurve
3126 //----------------------------------------------------------------------------
3127 BEGIN_EVENT_TABLE( a2dVertexListCurve, a2dCurve )
3128  EVT_CANVASOBJECT_MOUSE_EVENT( a2dVertexListCurve::OnCanvasObjectMouseEvent )
3129  EVT_CANVASOBJECT_ENTER_EVENT( a2dVertexListCurve::OnEnterObject )
3130  EVT_CANVASOBJECT_LEAVE_EVENT( a2dVertexListCurve::OnLeaveObject )
3131  EVT_CANVASHANDLE_MOUSE_EVENT( a2dVertexListCurve::OnHandleEvent )
3132 END_EVENT_TABLE()
3133 
3134 
3135 a2dVertexListCurve::a2dVertexListCurve( a2dVertexList* points ): a2dCurve()
3136 {
3137  m_lpoints = points;
3138  m_spline = false;
3139  m_rendermode = a2dCURVES_RENDER_DEFAULT;
3140  m_editmode = a2dCURVES_EDIT_DEFAULT;
3141 }
3142 
3143 a2dVertexListCurve::a2dVertexListCurve( ): a2dCurve()
3144 {
3145  m_lpoints = new a2dVertexList();
3146  m_spline = false;
3147  m_rendermode = a2dCURVES_RENDER_DEFAULT;
3148  m_editmode = a2dCURVES_EDIT_DEFAULT;
3149 }
3150 
3151 
3152 a2dVertexListCurve::~a2dVertexListCurve()
3153 {
3154  delete m_lpoints;
3155 }
3156 
3157 a2dVertexListCurve::a2dVertexListCurve( const a2dVertexListCurve& other, CloneOptions options, a2dRefMap* refs )
3158  : a2dCurve( other, options, refs )
3159 {
3160  m_lpoints = new a2dVertexList();
3161  *m_lpoints = *other.m_lpoints;
3162 
3163  m_spline = other.m_spline;
3164  m_rendermode = other.m_rendermode;
3165  m_editmode = other.m_editmode;
3166 }
3167 
3169 {
3170  return new a2dVertexListCurve( *this, options, refs );
3171 };
3172 
3174 {
3175  if ( !m_lworld.IsIdentity() )
3176  {
3177  for( a2dVertexList::iterator iter = m_lpoints->begin(); iter != m_lpoints->end(); ++iter )
3178  {
3179  a2dLineSegment* point = ( *iter );
3180  m_lworld.TransformPoint( point->m_x, point->m_y, point->m_x, point->m_y );
3181  }
3182 
3183  }
3185 }
3186 
3187 void a2dVertexListCurve::SetPosXYPoint( int n, double x, double y, bool afterinversion )
3188 {
3189  if ( afterinversion )
3190  {
3191  a2dAffineMatrix inverse = m_lworld;
3192  inverse.Invert();
3193  inverse.TransformPoint( x, y, x, y );
3194  }
3195 
3196  int i = 0;
3197  for( a2dVertexList::iterator iter = m_lpoints->begin(); iter != m_lpoints->end(); ++iter )
3198  {
3199  if ( i == n )
3200  {
3201  a2dLineSegment* point = ( *iter );
3202  point->m_x = x;
3203  point->m_y = y;
3204  break;
3205  }
3206  i++;
3207  }
3208  SetPending( true );
3209 }
3210 
3211 void a2dVertexListCurve::AddPoint( const a2dPoint2D& P, int index, bool afterinversion )
3212 {
3213  AddPoint( P.m_x, P.m_y, index, afterinversion );
3214 }
3215 
3216 void a2dVertexListCurve::AddPoint( double x, double y, int index, bool afterinversion )
3217 {
3218  if ( afterinversion )
3219  {
3220  a2dAffineMatrix inverse = m_lworld;
3221  inverse.Invert();
3222  inverse.TransformPoint( x, y, x, y );
3223  }
3224 
3225  a2dLineSegment* point = new a2dLineSegment( x, y );
3226 
3227  if ( index == -1 )
3228  m_lpoints->push_back( point );
3229  else
3230  {
3231  a2dVertexList::iterator iter = m_lpoints->begin();
3232  int i = 0;
3233  while ( i < index ) { ++iter; i++; }
3234  m_lpoints->insert( iter, point );
3235  }
3236  SetPending( true );
3237 }
3238 
3239 void a2dVertexListCurve::RemovePoint( double& x, double& y , int index, bool transformed )
3240 {
3241  if ( index == -1 )
3242  {
3243  a2dLineSegment* point;
3244  point = m_lpoints->back();
3245  x = point->m_x;
3246  y = point->m_y;
3247  m_lpoints->pop_back();
3248  }
3249  else
3250  {
3251  int i = 0;
3252  a2dVertexList::iterator iter = m_lpoints->begin();
3253  a2dLineSegment* point;
3254  while ( iter != m_lpoints->end() )
3255  {
3256  if ( i == index )
3257  {
3258  point = ( *iter );
3259  x = point->m_x;
3260  y = point->m_y;
3261  m_lpoints->erase( iter );
3262  break;
3263  }
3264  i++;
3265  iter++;
3266  }
3267  }
3268 
3269  if ( transformed )
3270  {
3271  m_lworld.TransformPoint( x, y, x, y );
3272  }
3273 
3274  SetPending( true );
3275 }
3276 
3277 void a2dVertexListCurve::GetPosXYPoint( int index, double& x, double& y, bool transform )
3278 {
3279  if ( index == -1 )
3280  {
3281  a2dLineSegment* point;
3282  point = m_lpoints->back();
3283  x = point->m_x;
3284  y = point->m_y;
3285  }
3286  else
3287  {
3288  int i = 0;
3289  a2dVertexList::iterator iter = m_lpoints->begin();
3290  a2dLineSegment* point;
3291  while ( iter != m_lpoints->end() )
3292  {
3293  if ( i == index )
3294  {
3295  point = ( *iter );
3296  x = point->m_x;
3297  y = point->m_y;
3298  break;
3299  }
3300  i++;
3301  iter++;
3302  }
3303  }
3304 
3305  if ( transform )
3306  {
3307  m_lworld.TransformPoint( x, y, x, y );
3308  }
3309 }
3310 
3311 bool a2dVertexListCurve::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
3312 {
3313  if ( m_flags.m_editable )
3314  {
3315  if ( editmode == 1 )
3316  {
3317  m_flags.m_visiblechilds = true;
3319 
3320  //add properties and handles as children in order to edit the object.
3321  int index = 0;
3323  {
3324  a2dLineSegment* point = *iter;
3325  //not inclusive matrix so relative to polygon
3326  a2dHandle* handle = new a2dHandle( this, point->m_x, point->m_y, wxT( "__index__" ) );
3327  handle->SetLayer( m_layer );
3328  Append( handle );
3329  handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
3330  PROPID_Index->SetPropertyToObject( handle, index++ );
3331  }
3332 
3333  m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT( "a2dHandle" ) );
3334  m_flags.m_editingCopy = true;
3335 
3336  //calculate bbox's elase mouse events may take place when first idle event is not yet
3337  //processed to do this calculation.
3339  //stil set it pending to do the redraw ( in place )
3340  SetPending( true );
3341  return true;
3342  }
3343  else
3344  {
3345  PROPID_Allowrotation->SetPropertyToObject( this, true );
3346  PROPID_Allowskew->SetPropertyToObject( this, true );
3347 
3348  return a2dCanvasObject::DoStartEdit( editmode, editstyle );
3349  }
3350  }
3351 
3352  return false;
3353 }
3354 
3355 bool a2dVertexListCurve::GetXyAtSweep( double sweepValue, a2dPoint2D& point ) const
3356 {
3357  double xp, yp;
3358  if( !m_lpoints->size() )
3359  return false;
3360 
3361  a2dVertexList::iterator iter = m_lpoints->begin();
3362  a2dPoint2D pointc = ( *iter )->GetPoint();
3363  xp = pointc.m_x;
3364  yp = pointc.m_y;
3365 
3366  while ( iter != m_lpoints->end() )
3367  {
3368  a2dPoint2D pointc = ( *iter )->GetPoint();
3369  if ( xp < sweepValue && pointc.m_x >= sweepValue )
3370  {
3371  point.m_x = sweepValue;
3372  point.m_y = ( pointc.m_y - yp ) * ( pointc.m_x - xp ) / ( pointc.m_x - xp ) + yp;
3373  return true;
3374  }
3375  xp = pointc.m_x;
3376  yp = pointc.m_y;
3377  iter++;
3378  }
3379 
3380  //return the end, so at least a normal value
3381  point.m_x = sweepValue;
3382  point.m_y = yp;
3383 
3384  return false;
3385 }
3386 
3388 {
3389  a2dBoundingBox bbox;
3390  double xw, yw;
3391  m_curveBox.SetValid( false );
3392  if ( m_spline )
3393  {
3394  a2dVertexList* lpoints = new a2dVertexList();
3395  a2dLineSegment* pointo;
3396  a2dVertexList::iterator iter;
3397  for( iter = m_lpoints->begin(); iter != m_lpoints->end(); ++iter )
3398  {
3399  pointo = ( *iter );
3400  a2dLineSegment* point = new a2dLineSegment( *pointo );
3401  lpoints->push_back( point );
3402  }
3403 
3404  lpoints->ConvertSplinedPolygon( 10 );
3405  for( iter = lpoints->begin(); iter != lpoints->end(); ++iter )
3406  {
3407  a2dLineSegment* point = ( *iter );
3408  m_curveBox.Expand( point->m_x, point->m_y );
3409  Curve2World( point->m_x, point->m_y, xw, yw );
3410  bbox.Expand( xw, yw );
3411  }
3412  delete lpoints;
3413  }
3414  else
3415  {
3416  for( a2dVertexList::iterator iter = m_lpoints->begin(); iter != m_lpoints->end(); ++iter )
3417  {
3418  a2dLineSegment* point = ( *iter );
3419  m_curveBox.Expand( point->m_x, point->m_y );
3420  Curve2World( point->m_x, point->m_y, xw, yw );
3421  bbox.Expand( xw, yw );
3422  }
3423  }
3424  return bbox;
3425 }
3426 
3427 bool a2dVertexListCurve::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
3428 {
3429  if ( !m_bbox.GetValid() )
3430  {
3431  //trigger children ( markers etc. which normally do change when curve changes )
3434 
3436  m_bbox.MapBbox( m_lworld );
3437 
3438  if ( m_flags.m_editingCopy && m_spline )
3439  {
3440  m_spline = false;
3442  bboxs.MapBbox( m_lworld );
3443  m_bbox.Expand( bboxs );
3444  m_spline = true;
3445 
3446  if ( m_clipdata.GetValid() )
3447  {
3448  double xw, yw;
3450  a2dBoundingBox box;
3451  box.Expand( xw, yw );
3453  box.Expand( xw, yw );
3454  box.MapBbox( m_lworld );
3455 
3456  m_bbox.And( &box );
3457  }
3458  }
3459 
3461  m_bbox.And( &box );
3462  return true;
3463  }
3464  return false;
3465 }
3466 
3467 void a2dVertexListCurve::DoRender( a2dIterC& ic, OVERLAP WXUNUSED( clipparent ) )
3468 {
3469 // double minx = GetBoundaryMinX();
3470 // double maxx = GetBoundaryMaxX();
3472  if( !curvebox.GetValid() )
3473  return;
3474 
3475  double xw, yw;
3476  if ( !( m_rendermode & a2dCURVES_RENDER_NO_POINTS ) )
3477  {
3478  a2dStroke current = ic.GetDrawer2D()->GetDrawerStroke();
3479  a2dFill fillcurrent = ic.GetDrawer2D()->GetDrawerFill();
3480 
3481  if ( m_highlightmode )
3482  {
3483  a2dStroke tmps = a2dStroke( wxColour( 239, 232, 0 ), 3 );
3484  ic.GetDrawer2D()->SetDrawerStroke( tmps );
3486  }
3487  else
3488  {
3491  }
3492 
3495 
3496  forEachIn( a2dVertexList, m_lpoints )
3497  {
3498  a2dLineSegment* point = *iter;
3499  if ( point->m_x >= curvebox.GetMinX() && point->m_x <= curvebox.GetMaxX() )
3500  {
3501  Curve2World( point->m_x, point->m_y, xw, yw );
3502 
3503  double xd, yd;
3504  matrix.TransformPoint( xw, yw, xd, yd );
3505  int radius = 2; //pixels
3506  ic.GetDrawer2D()->DrawCircle( xd, yd, radius );
3507  }
3508  if ( point->m_x > curvebox.GetMaxX() )
3509  break;
3510  }
3511  ic.GetDrawer2D()->PopTransform();
3512 
3513  ic.GetDrawer2D()->SetDrawerStroke( current );
3514  ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
3515  }
3516 
3517  wxRasterOperationMode prevlogfunction = wxNO_OP;
3518  wxDC* aDC = NULL;
3519  if( m_logFunction != wxNO_OP )
3520  {
3521  aDC = ic.GetDrawer2D()->GetRenderDC();
3522  prevlogfunction = aDC->GetLogicalFunction();
3523  aDC->SetLogicalFunction( m_logFunction );
3524  }
3525 
3526  if ( m_rendermode & a2dCURVES_RENDER_NORMAL )
3527  {
3528  bool second = false;
3529  double xprev = 0, yprev = 0;
3530  a2dLineSegment* lastpoint = NULL;
3531  forEachIn( a2dVertexList, m_lpoints )
3532  {
3533  a2dLineSegment* point = *iter;
3534  if ( second && point->m_x >= curvebox.GetMinX() )
3535  {
3536  Curve2World( lastpoint->m_x, lastpoint->m_y, xprev, yprev );
3537  Curve2World( point->m_x, point->m_y, xw, yw );
3538  ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
3539  }
3540  if ( point->m_x > curvebox.GetMaxX() )
3541  break;
3542 
3543  lastpoint = point;
3544 
3545  second = true;
3546  }
3547  }
3548  else if ( m_rendermode & a2dCURVES_RENDER_FILL_LINE )
3549  {
3550  bool second = false;
3551  double xprev = 0, yprev = 0;
3552  double yw0;
3553  a2dLineSegment* point = *( m_lpoints->begin() );
3554  Curve2World( point->m_x, 0, xw, yw0 );
3555  a2dLineSegment* lastpoint = NULL;
3556  forEachIn( a2dVertexList, m_lpoints )
3557  {
3558  a2dLineSegment* point = *iter;
3559  if ( second && point->m_x >= curvebox.GetMinX() )
3560  {
3561  Curve2World( lastpoint->m_x, lastpoint->m_y, xprev, yprev );
3562  Curve2World( point->m_x, point->m_y, xw, yw );
3563  ic.GetDrawer2D()->DrawLine( xw, yw0, xw, yw );
3564  ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
3565  }
3566  if ( point->m_x > curvebox.GetMaxX() )
3567  break;
3568 
3569  lastpoint = point;
3570  second = true;
3571  }
3572  }
3573  if( aDC )
3574  aDC->SetLogicalFunction( prevlogfunction );
3575 }
3576 
3577 #if wxART2D_USE_CVGIO
3578 void a2dVertexListCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
3579 {
3580  a2dCurve::DoSave( parent, out, xmlparts, towrite );
3581  if ( xmlparts == a2dXmlSer_attrib )
3582  {
3583  if ( m_spline )
3584  {
3585  out.WriteAttribute( wxT( "spline" ) , m_spline );
3586  }
3587  out.WriteAttribute( wxT( "points" ) , m_lpoints->size() );
3588  out.WriteAttribute( wxT( "rendermode" ) , m_rendermode );
3589  out.WriteAttribute( wxT( "editmode" ) , m_editmode );
3590  }
3591  else
3592  {
3593  unsigned int i = 0;
3594  forEachIn( a2dVertexList, m_lpoints )
3595  {
3596  if ( i % 6 == 0 )
3597  out.WriteNewLine();
3598  a2dLineSegment* point = *iter;
3599  out.WriteStartElementAttributes( wxT( "xy" ) );
3600  out.WriteAttribute( wxT( "x" ) , point->m_x );
3601  out.WriteAttribute( wxT( "y" ) , point->m_y );
3602  out.WriteEndAttributes( true );
3603  i++;
3604  }
3605  }
3606 }
3607 
3608 void a2dVertexListCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
3609 {
3610  a2dCurve::DoLoad( parent, parser, xmlparts );
3611  if ( xmlparts == a2dXmlSer_attrib )
3612  {
3613  m_spline = parser.GetAttributeValueBool( wxT( "spline" ), false );
3614  m_rendermode = parser.GetAttributeValueInt( wxT( "rendermode" ) );
3615  m_editmode = parser.GetAttributeValueInt( wxT( "editmode" ) );
3616  }
3617  else
3618  {
3619  while( parser.GetTagName() == wxT( "xy" ) )
3620  {
3621  double x = parser.GetAttributeValueDouble( wxT( "x" ) );
3622  double y = parser.GetAttributeValueDouble( wxT( "y" ) );
3623  a2dLineSegment* point = new a2dLineSegment( x, y );
3624  m_lpoints->push_back( point );
3625 
3626  parser.Next();
3627  parser.Require( END_TAG, wxT( "xy" ) );
3628  parser.Next();
3629  }
3630  }
3631 }
3632 #endif //wxART2D_USE_CVGIO
3633 
3635 {
3636  double xcurve, ycurve;
3637  World2Curve( hitEvent.m_relx, hitEvent.m_rely, xcurve, ycurve );
3638 
3639  a2dPoint2D P = a2dPoint2D( xcurve, ycurve );
3640  double pw = ic.GetWorldStrokeExtend();
3641  double margin = ic.GetTransformedHitMargin();
3642 
3643  if ( PointOnCurve( P, pw + margin ) )
3644  {
3646  return true;
3647  }
3648  else
3649  {
3650  hitEvent.m_how = a2dHit::stock_nohit;
3651  return false;
3652  }
3653 }
3654 
3655 bool a2dVertexListCurve::PointOnCurve( const a2dPoint2D& P, double margin )
3656 {
3657  bool result = false;
3658  double distance;
3659  a2dPoint2D p1, p2;
3660 
3661  a2dVertexList* rlist;
3662  if ( m_spline )
3663  {
3664 
3665  a2dVertexList* lpoints = new a2dVertexList();
3666  for( a2dVertexList::iterator iter = m_lpoints->begin(); iter != m_lpoints->end(); ++iter )
3667  {
3668  a2dLineSegment* point = new a2dLineSegment( *( *iter ) );
3669  lpoints->push_back( point );
3670  }
3671 
3672  lpoints->ConvertSplinedPolyline( 10 );
3673  rlist = lpoints;
3674  }
3675  else
3676  rlist = m_lpoints;
3677 
3678  if ( rlist->size() )
3679  {
3680  a2dVertexList::iterator iter = rlist->begin();
3681  p2 = ( *iter )->GetPoint();
3682  while ( iter != rlist->end() && !result )
3683  {
3684  p1 = p2;
3685  iter++;
3686  if ( iter != rlist->end() ) break;
3687  p2 = ( *iter )->GetPoint();
3688 
3689  if ( margin > sqrt( pow( p1.m_x - P.m_x, 2 ) + pow( p1.m_y - P.m_y, 2 ) ) )
3690  result = true;
3691  else if ( !( ( p1.m_x == p2.m_x ) && ( p1.m_y == p2.m_y ) ) )
3692  {
3693  a2dLine line1( p1, p2 );
3694  if ( line1.PointInLine( P, distance, margin ) == R_IN_AREA )
3695  result = true;
3696  }
3697  }
3698  }
3699 
3700  if ( m_spline )
3701  {
3702  for( a2dVertexList::iterator iter = rlist->begin(); iter != rlist->end(); ++iter )
3703  {
3704  a2dLineSegment* point = ( *iter );
3705  GetBbox().Expand( point->m_x, point->m_y );
3706  }
3707  delete rlist;
3708  }
3709 
3710  return result;
3711 }
3712 
3713 void a2dVertexListCurve::OnHandleEvent( a2dHandleMouseEvent& event )
3714 {
3715  a2dIterC* ic = event.GetIterC();
3716 
3717  if ( m_flags.m_editingCopy )
3718  {
3719  double xw, yw;
3720  xw = event.GetX();
3721  yw = event.GetY();
3722 
3723  a2dAffineMatrix atWorld = ic->GetTransform();
3724 
3725  //we need to get the matrix until the parent of the a2dHandle,
3726  // and not inclusif the handle itself.
3727  //and therefore apply inverted handle matrix.
3728  a2dAffineMatrix inverselocal = m_lworld;
3729  inverselocal.Invert();
3730 
3732 
3733  double xinternal, yinternal;
3734  inverse.TransformPoint( xw, yw, xinternal, yinternal );
3735 
3736  a2dHandle* draghandle = event.GetCanvasHandle();
3737  wxUint16 index = PROPID_Index->GetPropertyValue( draghandle );
3738 
3739  wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
3740 
3741  if ( editmode == 1 )
3742  {
3743  a2dVertexListCurve* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dVertexListCurve );
3744 
3745  double xwi;
3746  double ywi;
3747  inverselocal.TransformPoint( xinternal, yinternal, xwi, ywi );
3748 
3749  if ( event.GetMouseEvent().LeftUp() )
3750  {
3751  if ( draghandle->GetName() == wxT( "__index__" ) )
3752  {
3753  m_root->GetCommandProcessor()->Submit( new a2dCommand_VertexListCurveMovePoint( original, xinternal, yinternal, index ) );
3754  }
3755  else
3756  event.Skip(); //maybe the base class handles
3757  }
3758  else if ( event.GetMouseEvent().Dragging() )
3759  {
3760  SetPosXYPoint( index, xinternal, yinternal );
3761  draghandle->SetPosXY( xwi, ywi );
3762  }
3763  else
3764  event.Skip(); //maybe on the base class handles
3765  }
3766  else
3767  event.Skip();
3768  }
3769  else
3770  {
3771  event.Skip();
3772  }
3773 }
3774 
3775 void a2dVertexListCurve::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
3776 {
3777  event.Skip();
3778 }
3779 
3780 void a2dVertexListCurve::OnEnterObject( a2dCanvasObjectMouseEvent& event )
3781 {
3782  a2dIterC* ic = event.GetIterC();
3783  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS ) );
3784  // PushLayer(wxLAYER_ONTOP);
3785  m_highlightmode = 1;
3786  SetPending( true );
3787  event.Skip();
3788 }
3789 
3790 void a2dVertexListCurve::OnLeaveObject( a2dCanvasObjectMouseEvent& event )
3791 {
3792  //a2dIterC* ic = event.GetIterC();
3793  event.Skip();
3794  // PopLayer();
3795  m_highlightmode = 0;
3796  SetPending( true );
3797 }
3798 
3799 
3800 
3801 //----------------------------------------------------------------------------
3802 // a2dPieCurve
3803 //----------------------------------------------------------------------------
3804 BEGIN_EVENT_TABLE( a2dPieCurve, a2dCurve )
3805  EVT_CANVASOBJECT_MOUSE_EVENT( a2dPieCurve::OnCanvasObjectMouseEvent )
3806  EVT_CANVASOBJECT_ENTER_EVENT( a2dPieCurve::OnEnterObject )
3807  EVT_CANVASOBJECT_LEAVE_EVENT( a2dPieCurve::OnLeaveObject )
3808  EVT_CANVASHANDLE_MOUSE_EVENT( a2dPieCurve::OnHandleEvent )
3809 END_EVENT_TABLE()
3810 
3811 
3812 a2dPieCurve::a2dPieCurve( a2dVertexArray* points ): a2dCurve()
3813 {
3814  m_points = points;
3815  m_rendermode = a2dCURVES_RENDER_DEFAULT;
3816 }
3817 
3818 a2dPieCurve::a2dPieCurve( ): a2dCurve()
3819 {
3820  m_points = new a2dVertexArray;
3821  m_rendermode = a2dCURVES_RENDER_DEFAULT;
3822 }
3823 
3824 
3825 a2dPieCurve::~a2dPieCurve()
3826 {
3827  delete m_points;
3828 }
3829 
3830 a2dPieCurve::a2dPieCurve( const a2dPieCurve& other, CloneOptions options, a2dRefMap* refs )
3831  : a2dCurve( other, options, refs )
3832 {
3833  m_points = new a2dVertexArray;
3834  unsigned int i;
3835  for ( i = 0; i < other.m_points->size(); i++ )
3836  m_points->push_back( other.m_points->Item( i )->Clone() );
3837 
3838 
3839  m_rendermode = other.m_rendermode;
3840 }
3841 
3843 {
3844  return new a2dPieCurve( *this, options, refs );
3845 };
3846 
3847 void a2dPieCurve::RemovePointWorld( double& x, double& y , int index, bool transformed )
3848 {
3849  if ( index == -1 )
3850  index = m_points->size();
3851 
3852  x = m_points->Item( index )->m_x;
3853  y = m_points->Item( index )->m_y;
3854  m_points->RemoveAt( index );
3855 
3856  Curve2World( x, y, x, y );
3857 
3858  if ( transformed )
3859  {
3860  m_lworld.TransformPoint( x, y, x, y );
3861  }
3862 
3863 }
3864 
3865 void a2dPieCurve::AddPoint( const a2dPoint2D& P, int index )
3866 {
3867  AddPoint( P.m_x, P.m_y, index );
3868 }
3869 
3870 void a2dPieCurve::AddPoint( double x, double y, int index )
3871 {
3872  a2dLineSegment* point = new a2dLineSegment( x, y );
3873 
3874  if ( index == -1 )
3875  m_points->push_back( point );
3876  else
3877  m_points->Insert( point, index );
3878 
3879  SetPending( true );
3880 }
3881 
3882 void a2dPieCurve::GetPosXYPointWorld( int index, double& x, double& y, bool transform )
3883 {
3884  if ( index == -1 )
3885  index = m_points->size();
3886 
3887  x = m_points->Item( index )->m_x;
3888  y = m_points->Item( index )->m_y;
3889  Curve2World( x, y, x, y );
3890 
3891  if ( transform )
3892  {
3893  m_lworld.TransformPoint( x, y, x, y );
3894  }
3895 }
3896 
3897 bool a2dPieCurve::GetXyAtSweep( double sweepValue, a2dPoint2D& point ) const
3898 {
3899  double xp, yp;
3900  if( !m_points->size() )
3901  return false;
3902 
3903  xp = m_points->Item( 0 )->m_x;
3904  yp = m_points->Item( 0 )->m_y;
3905 
3906  if ( sweepValue <= m_points->Item( 0 )->m_x )
3907  {
3908  point.m_x = m_points->Item( 0 )->m_x;
3909  point.m_y = m_points->Item( 0 )->m_y;
3910  return false;
3911  }
3912 
3913  unsigned int i;
3914  for ( i = 0; i < m_points->size(); i++ )
3915  {
3916  if ( xp < sweepValue && m_points->Item( i )->m_x >= sweepValue )
3917  {
3918  point.m_x = sweepValue;
3919  point.m_y = ( m_points->Item( i )->m_y - yp ) * ( sweepValue - xp ) / ( m_points->Item( i )->m_x - xp ) + yp;
3920  return true;
3921  }
3922  xp = m_points->Item( i )->m_x;
3923  yp = m_points->Item( i )->m_y;
3924  }
3925 
3926  //return the end, so at least a normal value
3927  point.m_x = m_points->Item( i - 1 )->m_x;
3928  point.m_y = m_points->Item( i - 1 )->m_y;
3929 
3930  return false;
3931 }
3932 
3934 {
3936  m_curveBox = box;
3937  return box;
3938 }
3939 
3940 bool a2dPieCurve::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
3941 {
3942  if ( !m_bbox.GetValid() && m_points->size() )
3943  {
3945  m_bbox.MapBbox( m_lworld );
3946  m_width = m_bbox.GetWidth() * 0.95;
3947  m_height = m_bbox.GetHeight() * 0.95;
3948 
3949  return true;
3950  }
3951  return false;
3952 }
3953 
3954 void a2dPieCurve::DoRender( a2dIterC& ic, OVERLAP WXUNUSED( clipparent ) )
3955 {
3956  //double minx = GetBoundaryMinX();
3957  //double maxx = GetBoundaryMaxX();
3958 
3959  unsigned int i;
3960  double xw, yw;
3961 
3962  double yt = 0;
3963  for ( i = 0; i < m_points->size(); i++ )
3964  yt += m_points->Item( i )->m_y;
3965 
3966  double dangle = 2 * wxPI / yt;
3967 
3968  wxRasterOperationMode prevlogfunction = wxNO_OP;
3969  wxDC* aDC = NULL;
3970  if( m_logFunction != wxNO_OP )
3971  {
3972  aDC = ic.GetDrawer2D()->GetRenderDC();
3973  prevlogfunction = aDC->GetLogicalFunction();
3974  aDC->SetLogicalFunction( m_logFunction );
3975  }
3976 
3977  if ( m_rendermode & a2dCURVES_RENDER_NORMAL )
3978  {
3979  double theta = 0;
3980  double xn, yn;
3981  xn = m_width / 2 * cos ( theta );
3982  yn = m_height / 2 * sin ( theta );
3983  for ( i = 0; i < m_points->size(); i++ )
3984  {
3985  xw = xn; yw = yn;
3986  double theta2 = theta;
3987  theta += dangle * m_points->Item( i )->m_y;
3988  ic.GetDrawer2D()->DrawLine( 0, 0, xw, yw );
3989  theta2 += 0.02;
3990  xn = m_width / 2 * cos ( theta2 );
3991  yn = m_height / 2 * sin ( theta2 );
3992  while ( theta2 < theta )
3993  {
3994  ic.GetDrawer2D()->DrawLine( xw, yw, xn, yn );
3995  theta2 += 0.02;
3996  xw = xn; yw = yn;
3997  xn = m_width / 2 * cos ( theta2 );
3998  yn = m_height / 2 * sin ( theta2 );
3999  }
4000  xn = m_width / 2 * cos ( theta );
4001  yn = m_height / 2 * sin ( theta );
4002  ic.GetDrawer2D()->DrawLine( xw, yw, xn, yn );
4003  }
4004  }
4005  else
4006  {
4007  double theta = 0;
4008  double xn, yn;
4009  xn = m_width / 2 * cos ( theta );
4010  yn = m_height / 2 * sin ( theta );
4011  a2dlist< a2dFill >::iterator iter = m_pointsFill.begin();
4012  for ( i = 0; i < m_points->size(); i++ )
4013  {
4014  if ( m_pointsFill.size() )
4015  ic.GetDrawer2D()->SetDrawerFill( *iter );
4016 
4017  xw = xn; yw = yn;
4018  double theta2 = theta;
4019  theta += dangle * m_points->Item( i )->m_y;
4020 
4021  a2dVertexArray* cpoints = new a2dVertexArray;
4022  cpoints->push_back( new a2dLineSegment( 0, 0 ) );
4023  cpoints->push_back( new a2dLineSegment( xw, yw ) );
4024 
4025  theta2 += 0.02;
4026  xn = m_width / 2 * cos ( theta2 );
4027  yn = m_height / 2 * sin ( theta2 );
4028  while ( theta2 < theta )
4029  {
4030  cpoints->push_back( new a2dLineSegment( xn, yn ) );
4031  theta2 += 0.02;
4032  xw = xn; yw = yn;
4033  xn = m_width / 2 * cos ( theta2 );
4034  yn = m_height / 2 * sin ( theta2 );
4035  }
4036  xn = m_width / 2 * cos ( theta );
4037  yn = m_height / 2 * sin ( theta );
4038  cpoints->push_back( new a2dLineSegment( xn, yn ) );
4039 
4040  ic.GetDrawer2D()->DrawPolygon( cpoints, false, wxWINDING_RULE );
4041  delete cpoints;
4042 
4043  iter = m_pointsFill.GetNextAround( iter );
4044  }
4045  }
4046  if( aDC )
4047  aDC->SetLogicalFunction( prevlogfunction );
4048 }
4049 
4050 #if wxART2D_USE_CVGIO
4051 void a2dPieCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
4052 {
4053  a2dCurve::DoSave( parent, out, xmlparts, towrite );
4054  if ( xmlparts == a2dXmlSer_attrib )
4055  {
4056  out.WriteAttribute( wxT( "points" ) , m_points->size() );
4057  out.WriteAttribute( wxT( "rendermode" ) , m_rendermode );
4058  }
4059  else
4060  {
4061  unsigned int i;
4062  for ( i = 0; i < m_points->size(); i++ )
4063  {
4064  if ( i % 6 == 0 )
4065  out.WriteNewLine();
4066  out.WriteStartElementAttributes( wxT( "xy" ) );
4067  out.WriteAttribute( wxT( "x" ) , m_points->Item( i )->m_x );
4068  out.WriteAttribute( wxT( "y" ) , m_points->Item( i )->m_y );
4069  out.WriteEndAttributes( true );
4070  }
4071  }
4072 }
4073 
4074 void a2dPieCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
4075 {
4076  a2dCurve::DoLoad( parent, parser, xmlparts );
4077  if ( xmlparts == a2dXmlSer_attrib )
4078  {
4079  m_rendermode = parser.GetAttributeValueInt( wxT( "rendermode" ) );
4080  }
4081  else
4082  {
4083  while( parser.GetTagName() == wxT( "xy" ) )
4084  {
4085  double x = parser.GetAttributeValueDouble( wxT( "x" ) );
4086  double y = parser.GetAttributeValueDouble( wxT( "y" ) );
4087  a2dLineSegment* point = new a2dLineSegment( x, y );
4088  m_points->push_back( point );
4089 
4090  parser.Next();
4091  parser.Require( END_TAG, wxT( "xy" ) );
4092  parser.Next();
4093  }
4094  }
4095 }
4096 #endif //wxART2D_USE_CVGIO
4097 
4099 {
4100  double xh = hitEvent.m_relx, yh = hitEvent.m_rely;
4101 
4102  if ( m_height == 0 && m_width == 0 )
4103  {
4104  hitEvent.m_how = a2dHit::stock_nohit;
4105  return false;
4106  }
4107 
4108  if ( m_height == 0 || m_width == 0 )
4109  {
4110  hitEvent.m_how = a2dHit::stock_nohit;
4111  return false;
4112  }
4113 
4114  double pw = ic.GetWorldStrokeExtend();
4115  double margin = ic.GetTransformedHitMargin();
4116 
4117  double yt = 0;
4118  size_t i;
4119  for ( i = 0; i < m_points->size(); i++ )
4120  yt += m_points->Item( i )->m_y;
4121 
4122  double dangle = 2 * wxPI / yt;
4123 
4124  double a = m_width / 2 + pw + margin ;
4125  double b = m_height / 2 + pw + margin;
4126  double c = wxSqr( xh / a ) + wxSqr( yh / b );
4127  if ( 1 > c )
4128  {
4129  double dx = xh;
4130  double dy = yh;
4131  double theta = 0;
4132  size_t i;
4133  for ( i = 0; i < m_points->size(); i++ )
4134  {
4135 
4136  double start, end, angle;
4137  start = theta;
4138  theta += dangle * m_points->Item( i )->m_y;
4139  end = theta;
4140 
4141  double rx, ry;
4142  double c = m_height / m_width;
4143 
4144  rx = sqrt( dx * dx + ( dy * dy ) / ( c * c ) );
4145  ry = rx * c;
4146 
4147  if ( dx* ry == 0 && dy* rx == 0 )
4148  angle = 0;
4149  else
4150  angle = atan2( dy * rx, dx * ry );
4151 
4152  angle = angle - start;
4153  end = end - start;
4154 
4155  if ( angle <= 0 ) angle += 2.0 * wxPI;
4156 
4157  if ( end <= 0 ) end += 2.0 * wxPI;
4158  if ( start < 0 ) start += 2.0 * wxPI;
4159 
4160 
4161  angle = angle + start;
4162  end = end + start;
4163 
4164  if ( angle > start && angle < end )
4165  {
4166  //wxLogDebug( "pie %d", i );
4167  hitEvent.m_how = a2dHit::stock_fill;
4168  return true;
4169  }
4170  }
4171  }
4172 
4173  hitEvent.m_how = a2dHit::stock_nohit;
4174  return false;
4175 }
4176 
4177 bool a2dPieCurve::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
4178 {
4179  if ( m_flags.m_editable )
4180  {
4181  if ( editmode == 1 )
4182  {
4183  m_flags.m_draggable = false;
4184 
4185  m_flags.m_visiblechilds = true;
4187 
4188  //add properties and handles as children in order to edit the object.
4189  size_t i;
4190  double yt = 0;
4191  for ( i = 0; i < m_points->size(); i++ )
4192  yt += m_points->Item( i )->m_y;
4193 
4194  double dangle = 2 * wxPI / yt;
4195  double theta = 0;
4196  double xn, yn;
4197  for ( i = 0; i < m_points->size(); i++ )
4198  {
4199  xn = m_width / 2 * cos ( theta );
4200  yn = m_height / 2 * sin ( theta );
4201  theta += dangle * m_points->Item( i )->m_y;
4202 
4203  //not inclusive matrix so relative to polygon
4204  a2dHandle* handle = new a2dHandle( this, xn, yn, wxT( "__index__" ) );
4205  handle->SetLayer( m_layer );
4206  handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
4207  PROPID_Index->SetPropertyToObject( handle, i );
4208  Append( handle );
4209  }
4210  m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT( "a2dHandle" ) );
4211 
4212  //calculate bbox's else mouse events may take place when first, and idle event is not yet
4213  //processed to do this calculation.
4215  //still set it pending to do the redraw ( in place )
4216  SetPending( true );
4217  return true;
4218  }
4219  else
4220  {
4221  PROPID_Allowrotation->SetPropertyToObject( this, true );
4222  PROPID_Allowskew->SetPropertyToObject( this, true );
4223 
4224  return a2dCanvasObject::DoStartEdit( editmode, editstyle );
4225  }
4226  }
4227 
4228  return false;
4229 }
4230 
4231 void a2dPieCurve::OnHandleEvent( a2dHandleMouseEvent& event )
4232 {
4233  a2dIterC* ic = event.GetIterC();
4234 
4235  if ( m_flags.m_editingCopy )
4236  {
4237  double xw, yw;
4238  xw = event.GetX();
4239  yw = event.GetY();
4240 
4241  a2dAffineMatrix atWorld = ic->GetTransform();
4242 
4243  //we need to get the matrix until the parent of the a2dHandle,
4244  // and not inclusif the handle itself.
4245  //and therefore apply inverted handle matrix.
4246  a2dAffineMatrix inverselocal = m_lworld;
4247  inverselocal.Invert();
4248 
4250 
4251  double xinternal, yinternal;
4252  inverse.TransformPoint( xw, yw, xinternal, yinternal );
4253  //now in relative world coordinates, and so one more to get to curve coordinates.
4254  World2Curve( xinternal, yinternal, xinternal, yinternal );
4255 
4256  a2dHandle* draghandle = event.GetCanvasHandle();
4257  //wxUint16 index = PROPID_Index->GetPropertyValue( draghandle );
4258 
4259  wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
4260 
4261  if ( editmode == 1 )
4262  {
4263  //a2dPieCurve* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPieCurve );
4264 
4265  double xwi;
4266  double ywi;
4267  Curve2World( xinternal, yinternal, xwi, ywi );
4268 
4269  if ( event.GetMouseEvent().LeftUp() )
4270  {
4271  if ( draghandle->GetName() == wxT( "__index__" ) )
4272  {
4273  //m_root->GetCommandProcessor()->Submit(new a2dCommand_VertexCurveMovePoint( original, xinternal, yinternal, index ));
4274  }
4275  else
4276  event.Skip(); //maybe the base class handles
4277  }
4278  else if ( event.GetMouseEvent().Dragging() )
4279  {
4280  //SetPosXYPointWorld( index, xinternal, yinternal );
4281  draghandle->SetPosXY( xwi, ywi );
4282  }
4283  else
4284  event.Skip(); //maybe on the base class handles
4285  }
4286  else
4287  event.Skip();
4288  }
4289  else
4290  {
4291  event.Skip();
4292  }
4293 }
4294 
4295 void a2dPieCurve::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
4296 {
4297  event.Skip();
4298 }
4299 
4300 void a2dPieCurve::OnEnterObject( a2dCanvasObjectMouseEvent& event )
4301 {
4302  a2dIterC* ic = event.GetIterC();
4303 
4304  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS ) );
4305  // PushLayer(wxLAYER_ONTOP);
4306  m_highlightmode = 1;
4307  SetPending( true );
4308  event.Skip();
4309 }
4310 
4311 void a2dPieCurve::OnLeaveObject( a2dCanvasObjectMouseEvent& event )
4312 {
4313  //a2dIterC* ic = event.GetIterC();
4314 
4315  event.Skip();
4316  // PopLayer(wxLAYER_ONTOP);
4317  m_highlightmode = 0;
4318  SetPending( true );
4319 }
4320 
4321 
4322 
4323 
a2dHit m_how
return in which way the object was hit (stroke, fill, ...)
Definition: canobj.h:301
bool DoUpdate(UpdateMode mode, const a2dBoundingBox &childbox, const a2dBoundingBox &clipbox, const a2dBoundingBox &propbox)
Update derived Object specific things ( mainly boundingbox)
Definition: curve.cpp:3427
bool GetAttributeValueBool(const wxString &attrib, bool defaultv=false)
Returns the boolean value of an attribute.
Definition: genxmlpars.cpp:537
void DoRender(a2dIterC &ic, OVERLAP clipparent)
render derived object
Definition: curve.cpp:1070
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
Definition: artglob.h:47
a2dVertexArray * GetPoints()
return the array of points.
Definition: curve.h:312
void AddPoint(const a2dPoint2D &P, int index=-1, bool afterinversion=true)
Append a new point.
Definition: curve.cpp:3211
virtual bool GetXyAtSweep(double sweepValue, a2dPoint2D &point) const
calculate Y at X
Definition: curve.cpp:1717
double m_relx
(world coordinates) hit point x relative to the canvas object its parent object(s) ...
Definition: canobj.h:289
double GetHeight() const
returns height of the boundingbox
Definition: bbox.cpp:334
a2dSweepPointArray * GetPoints()
return the array of points.
Definition: curve.h:519
bool SetSpecificFlags(bool setOrClear, a2dCanvasObjectFlagsMask which, const wxString &classname=wxT(""), a2dCanvasObjectFlagsMask whichobjects=a2dCanvasOFlags::ALL, const a2dBoundingBox &bbox=wxNonValidBbox, const a2dAffineMatrix &tworld=a2dIDENTITY_MATRIX)
set all given bit flags at once recursive for all objects in given boundingbox
Definition: objlist.cpp:519
handle holds a pointer to a polygon/polyline segment
Definition: curve.h:912
#define wxDynamicCast(obj, className)
Define wxDynamicCast so that it will give a compiler error for unrelated types.
Definition: gen.h:75
Base class for all types of strokes, understood by a2dDrawer2D classes.
Definition: stylebase.h:378
virtual bool GetXyAtSweep(double sweepValue, a2dPoint2D &point) const
calculate Y at X
Definition: curve.cpp:3897
bool DoUpdate(UpdateMode mode, const a2dBoundingBox &childbox, const a2dBoundingBox &clipbox, const a2dBoundingBox &propbox)
Update derived Object specific things ( mainly boundingbox)
Definition: curve.cpp:1767
bool Undo(void)
Override this to undo a command.
Definition: curve.cpp:293
bool DoUpdate(UpdateMode mode, const a2dBoundingBox &childbox, const a2dBoundingBox &clipbox, const a2dBoundingBox &propbox)
Update derived Object specific things ( mainly boundingbox)
Definition: curve.cpp:689
classes for plotting curve and pie data, and editing them.
bool DoUpdate(UpdateMode mode, const a2dBoundingBox &childbox, const a2dBoundingBox &clipbox, const a2dBoundingBox &propbox)
Update derived Object specific things ( mainly boundingbox)
Definition: curve.cpp:3940
bool HasAttribute(const wxString &attrib)
Does the current tag have this attribute?
Definition: genxmlpars.cpp:560
a2dHandle is used inside editing versions of a certain objects.
Definition: canpin.h:30
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: curve.cpp:3933
mouse event sent from a2dCanvasObject to itself
Definition: canglob.h:223
a2dBoundingBox m_untransbbox
Untransformed bounding box.
Definition: curve.h:93
void GetPosXYPointWorld(int index, double &x, double &y, bool transform)
get point x and y at index in world coordinates
Definition: curve.cpp:929
bool DoUpdate(UpdateMode mode, const a2dBoundingBox &childbox, const a2dBoundingBox &clipbox, const a2dBoundingBox &propbox)
Update derived Object specific things ( mainly boundingbox)
Definition: curve.cpp:1043
const a2dStroke * a2dBLACK_STROKE
global a2dStroke stock object for BLACK stroking
bool DoIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
Does hit test on the object (exclusif child objects)
Definition: curve.cpp:3634
bool Undo(void)
Override this to undo a command.
Definition: curve.cpp:128
virtual void PopTransform(void)
Recall the previously saved user-to-world transform off the matrix stack.
Definition: drawer2d.cpp:480
XMLeventType Next()
Walks to next element and returns event type.
Definition: genxmlpars.cpp:422
void GetPosXYPointWorld(int index, double &x, double &y, bool transform)
get point x and y at index in world coordinates
Definition: curve.cpp:3882
a2dCurveObject()
default constructor
Definition: curve.cpp:393
void DoRender(a2dIterC &ic, OVERLAP clipparent)
render derived object
Definition: curve.cpp:2946
class to map references to objects stored in XML, in order to make the connection later on...
Definition: gen.h:3462
void RemovePoint(double &x, double &y, int index=-1)
removes point at index
Definition: curve.cpp:875
a2dDrawing * m_root
root group for rendering and accessing the canvas&#39;s also contains layer settings
Definition: canobj.h:2525
Bars in a Curve represented by a number of vertexes.
Definition: curve.h:962
Curve represented by a number of vertexes.
Definition: curve.h:501
a2dCanvasOFlags m_flags
holds flags for objects
Definition: canobj.h:2528
void SetPosXYPoint(int index, double sweep, double y, bool upper)
modify point at index to x,y
Definition: curve.cpp:2233
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: curve.cpp:1943
const a2dAffineMatrix & GetInverseTransform() const
Inverse of GetTransform()
Definition: canobj.cpp:699
static const a2dCanvasObjectFlagsMask BIN2
Definition: candefs.h:193
#define EVT_CANVASOBJECT_ENTER_EVENT(func)
static event table macro for a2dCanvasObject mouse enter event
Definition: canglob.h:314
void SetValid(bool)
Definition: bbox.cpp:364
void AddPoint(const a2dPoint2D &P, int index=-1)
Append a new point in curve coordinates.
Definition: curve.cpp:903
a2dSweepPointArray * GetPoints()
return the array of points.
Definition: curve.h:721
const a2dFill * a2dBLACK_FILL
global a2dFill stock object for BLACK filling
void WriteStartElementAttributes(const wxString &name, bool newLine=true)
Writes start tag which has attributes.
Definition: genxmlpars.cpp:757
static a2dHit stock_nohit
Stock object for no hit.
Definition: polyver.h:135
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: curve.cpp:3578
Ref Counted base object.
Definition: gen.h:1045
virtual bool GetXyAtSweep(double sweepValue, a2dPoint2D &point) const
calculate Y at X
Definition: curve.cpp:3355
virtual void Curve2World(double xcurve, double ycurve, double &xw, double &yw) const
used by a2dCurve to transform its own curve coordinates to the curve plotting area ...
Definition: curve.cpp:425
used to move points in BandCurve objects
Definition: curve.cpp:226
a2dDrawing * GetRoot() const
get a2dCanvasDocument of the object.
Definition: canobj.h:952
bool Do(void)
Override this to perform a command.
Definition: curve.cpp:196
bool PointOnCurve(const a2dPoint2D &P, double marge)
test if a point is on the curve.
Definition: curve.cpp:2792
double wxDegToRad(double deg)
conversion from degrees to radians
Definition: artglob.cpp:30
a2dBoundingBox GetClippedCurveBoundaries()
get clipped boundary box of plot boundary in curve coordinates
Definition: curve.cpp:524
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: curve.cpp:4074
virtual bool Update(UpdateMode mode)
Update the state of the object according to its current position etc.
Definition: canobj.cpp:5149
int GetAttributeValueInt(const wxString &attrib, int defaultv=0)
Returns the integer value of an attribute.
Definition: genxmlpars.cpp:495
bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: curve.cpp:4177
#define EVT_CANVASHANDLE_MOUSE_EVENT(func)
static event table macro for a2dHandle mouse event
Definition: canglob.h:318
void SetDrawerStroke(const a2dStroke &stroke)
Used to set the current stroke.
Definition: drawer2d.cpp:565
bool DoIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
Does hit test on the object (exclusif child objects)
Definition: curve.cpp:4098
bool IsIdentity(void) const
Is the matrix the identity matrix?
Definition: afmatrix.h:147
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:819
virtual void DrawPolygon(a2dVertexArray *points, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE)
Draw polygon in world coordinates using pointarray.
Definition: drawer2d.cpp:1889
UpdateMode
Various mode flags for Update.
Definition: canobj.h:1091
a2dBoundingBox GetCurveBoundaries()
get boundary box of plot boundary in curve coordinates
Definition: curve.cpp:542
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: curve.cpp:3387
R_PointStatus PointInLine(const a2dPoint2D &a_Point, double &Distance, double Marge) const
For a non-infinite a2dLine.
Definition: liner.cpp:560
void World2Curve(double xw, double yw, double &xcurve, double &ycurve)
used by a2dCurve to transform its own curve coordinates to the curve plotting area ...
Definition: curvegroup.cpp:164
a command processor specially designed to work with a a2dCanvasDocument
Definition: drawing.h:1046
virtual void SetPending(bool pending)
set this object pending for update
Definition: canobj.cpp:2585
OVERLAP
Result of a a2dBoundingBox intersection or hittest.
Definition: bbox.h:24
bool m_visiblechilds
child objects are visible or not
Definition: candefs.h:292
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
This is here so that this class cannot be used directly.
Definition: curve.cpp:2936
bool EliminateMatrix()
reduce matrix to identity without replacing object
Definition: curve.cpp:2218
The base class for all drawable objects in a a2dCanvasDocument.
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
This is here so that this class cannot be used directly.
Definition: curve.cpp:1577
double GetTransformedHitMargin()
transformed to object its coordinate system
Definition: canobj.cpp:616
a2dCommandProcessor * m_cmp
allows commands to get to the command processor that submitted the command.
Definition: comevt.h:279
a2dVertexList * ConvertSplinedPolyline(double Aber) const
Spline conversion for polyline.
Definition: polyver.cpp:2858
wxUint16 m_layer
layer of object, default wxLAYER_DEFAULT
Definition: canobj.h:2556
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: canobj.cpp:5728
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: curve.cpp:1252
void SetPosXYPoint(int index, double x, double y)
modify point at index to x,y
Definition: curve.cpp:1597
vertex array of line and arc segments.
Definition: polyver.h:494
a2dCanvasObject is the base class for Canvas Objects.
Definition: canobj.h:371
a2dLineSegmentPtr Item(size_t index) const
Returns the point pointer at the given position in the array.
Definition: curve.h:1239
bool EliminateMatrix()
reduce matrix to identity without replacing object
Definition: curve.cpp:3173
virtual void World2Curve(double xw, double yw, double &xcurve, double &ycurve) const
used by a2dCurve to transform its own curve coordinates to the curve plotting area ...
Definition: curve.cpp:411
Object to plot a Curve defined by a Function in form of a string.
Definition: curve.h:236
no special flags set
Definition: id.h:161
void AddPoint(double sweep, const a2dPoint2D &P)
Append a new point in curve coordinates.
Definition: curve.cpp:2280
bool And(a2dBoundingBox *, double Marge=0)
intersect the boundingbox with another, return true if the result is non zero
Definition: bbox.cpp:56
bool Undo(void)
Override this to undo a command.
Definition: curve.cpp:374
A2DGENERALDLLEXP a2dWalkEvent a2dWalker_a2dDerivedCanvasObjectStart
id for a2dWalkEvent issued from within a2dWalkerIOHandler
a2dCanvas uses a2dCanvasView for displaying a view on a a2dCanvasDocument.
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
wxString GetName() const
get the name given to the handle.
Definition: canpin.h:56
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: curve.cpp:790
virtual void EndEdit()
cleanup an editcopy object
Definition: canobj.cpp:1828
void WriteEndElement(bool newLine=true)
Writes correspondending end tag for the current start tag.
Definition: genxmlpars.cpp:862
void SetBoundaries(double xmin, double ymin, double xmax, double ymax)
define which part of the curve will be displayed.
Definition: curve.cpp:478
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
This is here so that this class cannot be used directly.
Definition: curve.cpp:640
void Curve2World(double xcurve, double ycurve, double &xw, double &yw)
used by a2dCurve to transform its own curve coordinates to the curve plotting area ...
Definition: curvegroup.cpp:171
bool PointOnCurve(const a2dPoint2D &P, double marge)
test if a point is on the curve.
Definition: curve.cpp:1300
a2dVertexList * ConvertSplinedPolygon(double Aber) const
Spline conversion for polygon.
Definition: polyver.cpp:2846
a2dCurveObject for objects needing to know its parent a2dCurvesArea.
Definition: curve.h:42
static a2dPropertyIdBool * PROPID_FirstEventInObject
set in Startedit(), to be used to detect first (mouse)event sent to object.
Definition: canobj.h:2694
a2dAffineMatrix m_lworld
used for positioning the object (x,y,ang,scale etc.)
Definition: canobj.h:2559
void SetDrawerFill(const a2dFill &fill)
Used to set the current fill.
Definition: drawer2d.cpp:621
Curve represented by a number of vertexes.
Definition: curve.h:1172
Io handler to iterate through a a2dDocument.
Definition: gen.h:3911
static const a2dCanvasObjectFlagsMask PENDING
Definition: candefs.h:194
wxMouseEvent & GetMouseEvent()
return the original mouse event that was redirected to the a2dHandle
Definition: canglob.h:290
void RemovePoint(double &x, double &y, int index=-1)
removes point at index
Definition: curve.cpp:1605
virtual bool GetXyAtSweep(double sweepValue, a2dPoint2D &point) const
calculate Y at X
Definition: curve.cpp:2487
bool m_draggable
can be dragged
Definition: candefs.h:253
void WriteNewLine()
Writes a new line and takes care of indentation.
Definition: genxmlpars.cpp:890
bool DoIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
Does hit test on the object (exclusif child objects)
Definition: curve.cpp:2768
bool IsEdgeHit() const
true if this is a stroke hit on an edge
Definition: polyver.h:128
a2dSweepPoint * Item(size_t index) const
Definition: curve.h:617
void DoRender(a2dIterC &ic, OVERLAP clipparent)
render derived object
Definition: curve.cpp:1798
used to move points in VertexCurve objects
Definition: curve.cpp:144
a2dCanvasObjectList * wxNullCanvasObjectList
define a NON a2dCanvasObjectList
Definition: objlist.cpp:53
std list compatible list
Definition: a2dlist.h:42
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: curve.cpp:2538
bool DoUpdate(UpdateMode mode, const a2dBoundingBox &childbox, const a2dBoundingBox &clipbox, const a2dBoundingBox &propbox)
Update derived Object specific things ( mainly boundingbox)
Definition: curve.cpp:437
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
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: curve.cpp:3608
double GetMinX() const
get minimum X of the boundingbox
Definition: bbox.cpp:304
virtual void DrawRoundedRectangle(double x, double y, double width, double height, double radius, bool pixelsize=false)
Draw RoundedRectangle in world coordinates.
Definition: drawer2d.cpp:2048
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
This is here so that this class cannot be used directly.
Definition: curve.cpp:3168
a2dCanvasObjectList * m_childobjects
holds child objects
Definition: canobj.h:2562
bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: curve.cpp:3311
~a2dCanvasBandCurveHandle()
destructor
Definition: curve.cpp:2158
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: curve.cpp:1028
#define forEachIn(listtype, list)
easy iteration for a2dlist
Definition: a2dlist.h:111
void RemovePointWorld(double &x, double &y, int index=-1, bool transformed=true)
removes point at index
Definition: curve.cpp:3847
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: curve.cpp:505
void SetPropertyToObject(a2dObject *obj, const basetype &value, SetFlags setflags=set_none) const
Set the property in obj to value.
Definition: id.inl:238
bool DoIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
Does hit test on the object (exclusif child objects)
Definition: curve.cpp:1970
a2dHit & GetHow()
in what manner the a2dCanvasObject was hit.
Definition: canglob.h:246
a2dCanvasXYDisplayGroupAreas * GetGroup(void)
the group of which the area is a part
Definition: curvegroup.h:203
a2dDrawer2D * GetDrawer2D() const
get current a2dDrawer2D
Definition: canobj.cpp:636
#define wxStaticCast(obj, className)
The wxWindows 2.4.2 wxStaticCast is buggy. It evaluates its argument twice.
Definition: gen.h:123
bool m_editable
object can be edited
Definition: candefs.h:295
void DoRender(a2dIterC &ic, OVERLAP clipparent)
render derived object
Definition: curve.cpp:717
bool m_markerUpLow
return of GetXyAtSweep() is upper side of curve if true, else low
Definition: curve.h:898
Normal straight line segment in a2dVertexList and a2dVertexArray.
Definition: polyver.h:163
void SetSpecificFlags(bool setOrClear, a2dCanvasObjectFlagsMask which)
set all bit flags in object that or true in mask to true or false
Definition: canobj.cpp:2645
#define EVT_CANVASOBJECT_MOUSE_EVENT(func)
static event table macro for a2dCanvasObject mouse event
Definition: canglob.h:312
used to move points in VertexCurve objects
Definition: curve.cpp:64
bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: curve.cpp:2323
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: curve.cpp:1224
used to move points in VertexCurve objects
Definition: curve.cpp:315
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: canobj.cpp:5569
general event sent from a2dHandle to its parent a2dCanvasObject
Definition: canglob.h:273
bool m_childrenOnSameLayer
Definition: candefs.h:311
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: curve.cpp:3102
virtual void DrawLine(double x1, double y1, double x2, double y2)
Draw line in world coordinates.
Definition: drawer2d.cpp:2167
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:862
static const a2dCanvasObjectFlagsMask EditingCopy
Definition: candefs.h:207
virtual bool GetXyAtSweep(double sweepValue, a2dPoint2D &point) const
return Points in plot at the value of sweep parameter.
Definition: curve.cpp:645
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: curve.cpp:2712
a2dHandle * GetCanvasHandle()
return the handle object hit
Definition: canglob.h:287
void GetPosXYPointWorld(int index, double &sweep, double &y, bool upper, bool transform)
get point x and y at index in world coordinates
Definition: curve.cpp:2305
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: curve.cpp:4051
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
Each a2dCommand is given a command id at construction.
Definition: comevt.h:99
void RemovePointWorld(double &sweep, double &y, bool upper, int index=-1, bool transformed=true)
removes point at index
Definition: curve.cpp:2258
virtual bool Submit(a2dCommand *command, bool storeIt=true)
next to the base class submit, it sets a2DocumentCommandProcessor for a2dCommand
Definition: comevt.cpp:842
bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: curve.cpp:944
bool Do(void)
Override this to perform a command.
Definition: curve.cpp:360
virtual bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: canobj.cpp:1739
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
void RemovePoint(double &sweep, double &y, bool upper, int index=-1)
removes point at index
Definition: curve.cpp:2244
wxMouseEvent & GetMouseEvent()
return the original mouse event that was redirected to the a2dCanvasObject
Definition: canglob.h:243
a2dStroke GetDrawerStroke() const
get the current stroke
Definition: drawer2d.h:548
Base class for curves.
Definition: curve.h:107
void DoRender(a2dIterC &ic, OVERLAP clipparent)
render derived object
Definition: curve.cpp:2587
double GetAttributeValueDouble(const wxString &attrib, double defaultv=0)
Returns the double value of an attribute.
Definition: genxmlpars.cpp:474
double GetMaxX() const
get maximum X of the boundingbox
Definition: bbox.cpp:316
void DoRender(a2dIterC &ic, OVERLAP clipparent)
render derived object
Definition: curve.cpp:3954
const a2dAffineMatrix & GetInverseParentTransform() const
inverse of GetParentTransform()
Definition: canobj.cpp:723
void SetPosXYPoint(int index, double x, double y)
modify point at index to x,y
Definition: curve.cpp:867
double GetWorldStrokeExtend()
Definition: canobj.h:3403
void SetPosXYPoint(int index, double x, double y, bool afterinversion=true)
modify point at index to x,y
Definition: curve.cpp:3187
virtual a2dLineSegment * Clone()
create exact copy
Definition: polyver.cpp:250
bool DoIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
Does hit test on the object (exclusif child objects)
Definition: curve.cpp:754
void RemovePointWorld(double &x, double &y, int index=-1, bool transformed=true)
removes point at index
Definition: curve.cpp:885
while iterating a a2dCanvasDocument, this holds the context.
Definition: canobj.h:3212
Curve represented by a number of vertexes.
Definition: curve.h:294
void RemovePoint(double &x, double &y, int index=-1, bool transformed=true)
removes point at index
Definition: curve.cpp:3239
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: curve.cpp:2741
a2dCanvasBandCurveHandle()
constructor
Definition: curve.cpp:2136
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
This is here so that this class cannot be used directly.
Definition: curve.cpp:2213
double m_x
x endpoint of line
Definition: polyver.h:232
void DoRender(a2dIterC &ic, OVERLAP clipparent)
render derived object
Definition: curve.cpp:3467
a2dBoundingBox m_clipdata
defines boundaries in which the curve will be calculated / displayed
Definition: curve.h:214
double m_x
(world coordinates) hit point x as in a2dDrawingPart or any other top level
Definition: canobj.h:293
double wxSqr(double x)
good replacement for pow(x,2)
Definition: artglob.h:66
All updates of these modes force an update (e.g. update non-pending valid bounding boxes) ...
Definition: canobj.h:1107
void MapBbox(const a2dAffineMatrix &matrix)
Definition: bbox.cpp:445
a2dCommandProcessor * GetCommandProcessor() const
Returns a pointer to the command processor associated with this document.
Definition: drawing.h:549
#define EVT_CANVASOBJECT_LEAVE_EVENT(func)
static event table macro for a2dCanvasObject mouse leave event
Definition: canglob.h:316
double m_y
y endpoint of line
Definition: polyver.h:235
Line calculations.
Definition: liner.h:36
void AddPoint(double sweep, const a2dPoint2D &P)
Append a new point in curve coordinates.
Definition: curve.cpp:1633
static a2dHit stock_strokeoutside
Stock object for an outer stroke hit on objects without vertices/edges (like circles) ...
Definition: polyver.h:139
bool DoUpdate(UpdateMode mode, const a2dBoundingBox &childbox, const a2dBoundingBox &clipbox, const a2dBoundingBox &propbox)
Update derived Object specific things ( mainly boundingbox)
Definition: curve.cpp:2556
void GetPosXYPointWorld(int index, double &x, double &y, bool transform)
get point x and y at index in world coordinates
Definition: curve.cpp:1655
std::list< T, std::allocator< T > >::iterator GetNextAround(typename std::list< T, std::allocator< T > >::iterator iter)
get the next node ( begin() if no next )
Definition: a2dlist.h:95
void GetPosXYPoint(int index, double &x, double &y)
get point x and y at index
Definition: curve.cpp:1646
bool GetRelease() const
get release flag
Definition: gen.h:1350
editing tool for a2dCanvasObject&#39;s
a2dCurvesArea * m_curvesArea
parent of curve
Definition: curve.h:90
a2dBoundingBox GetPlotAreaBbox() const
return plotting rectangle in world coordinates
a2dBoundingBox m_curveBox
defines boundaries in which the curve has points
Definition: curve.h:217
double GetMaxY() const
get maximum Y of the boundingbox
Definition: bbox.cpp:322
double GetWidth() const
returns width of the boundingbox
Definition: bbox.cpp:328
bool PointOnCurve(const a2dPoint2D &P, double marge)
test if a point is on the curve.
Definition: curve.cpp:3655
void Require(const XMLeventType &type, wxString name)
Forces a special tag.
Definition: genxmlpars.cpp:390
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: curve.cpp:3085
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: curve.cpp:1752
wxString GetTagName()
Returns name of the current XML tag.
Definition: genxmlpars.cpp:565
bool m_arcMid
handle for middle point of arc
Definition: curve.h:941
void SetPosXY(double x, double y, bool restrict=false)
set position to x,y
Definition: canobj.cpp:1624
virtual wxDC * GetRenderDC() const
get the DC that is used for rendering
Definition: drawer2d.h:226
bool PointOnCurve(const a2dPoint2D &P, double marge)
test if a point is on the curve.
Definition: curve.cpp:1991
bool m_editingCopy
true if the object needs to be rendered in edit mode.
Definition: candefs.h:304
virtual bool EliminateMatrix()
reduce matrix to identity
Definition: canobj.cpp:6191
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: curve.cpp:779
a2dFill GetDrawerFill() const
get the current fill
Definition: drawer2d.h:557
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: curve.cpp:665
see a2dComEvent
Definition: gen.h:371
void GetPosXYPoint(int index, double &x, double &y, bool transform=true)
get point x and y at index
Definition: curve.cpp:3277
a2dLineSegmentPtr Item(size_t index) const
Returns the point pointer at the given position in the array.
Definition: curve.h:400
const a2dBoundingBox & GetInternalBoundaries() const
get the plotting rectangle in curve coordinates
Definition: curvegroup.h:107
Curve represented by a number of vertexes.
Definition: curve.h:703
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
Definition: bbox.h:39
bool Invert(void)
Invert matrix.
Definition: afmatrix.cpp:197
bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: curve.cpp:1670
void AddPoint(const a2dPoint2D &P, int index=-1)
Append a new point in curve coordinates.
Definition: curve.cpp:3865
a2dVertexList * GetPoints()
return the array of points.
Definition: curve.h:1054
virtual 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: canobj.cpp:5031
void Modify(bool increment)
set the drawing as modified or not
Definition: drawing.cpp:146
a2dSweepPoint * Item(size_t index) const
Definition: curve.h:822
static a2dHit stock_fill
Stock object for a fill hit.
Definition: polyver.h:137
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: curve.cpp:1915
virtual bool WalkTask(wxObject *parent, wxObject *object, a2dWalkEvent event)
called from within a2dObject&#39;s and derived classes
Definition: gen.cpp:5265
double GetMinY() const
get minimum Y of the boundingbox
Definition: bbox.cpp:310
void RemovePointWorld(double &x, double &y, int index=-1, bool transformed=true)
removes point at index
Definition: curve.cpp:1615
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.
basetype GetPropertyValue(const a2dObject *obj) const
Get the property value in obj.
Definition: id.inl:325
A2DGENERALDLLEXP a2dWalkEvent a2dWalker_a2dDerivedCanvasObjectEnd
id for a2dWalkEvent issued from within a2dWalkerIOHandler
a2dCanvasGlobal * a2dCanvasGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: canglob.cpp:1234
virtual void DrawCircle(double x, double y, double radius)
Draw Circle in world coordinates.
Definition: drawer2d.cpp:2116
bool Undo(void)
Override this to undo a command.
Definition: curve.cpp:210
a2dDrawingPart * GetDrawingPart() const
get current a2dDrawingPart
Definition: canobj.cpp:631
This template class is for property ids with a known data type.
Definition: id.h:477
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
This is here so that this class cannot be used directly.
Definition: curve.cpp:847
a2dBoundingBox m_bbox
boundingbox in world coordinates
Definition: canobj.h:2539
double RequireAttributeValueDouble(const wxString &attrib)
Forces an attribute and returns its double value.
Definition: genxmlpars.cpp:487
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
This is here so that this class cannot be used directly.
Definition: curve.cpp:3842
void Append(a2dCanvasObject *obj)
append a a2dCanvasObject to the childobjects
Definition: canobj.cpp:6224
bool EliminateMatrix()
reduce matrix to identity without replacing object
Definition: curve.cpp:852
Curve represented by a number of vertexes in a List.
Definition: curve.h:1036
const a2dAffineMatrix & GetTransform() const
Get the accumulated transform up to and including m_lworld of the current object. ...
Definition: canobj.cpp:663
virtual void SetLayer(wxUint16 layer)
set layer index where this object is drawn upon.
Definition: canobj.cpp:5920
void GetPosXYPoint(int index, double &x, double &y)
get point x and y at index
Definition: curve.cpp:920
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
double m_y
(world coordinates) hit point y as in a2dDrawingPart or any other top level
Definition: canobj.h:295
virtual bool GetXyAtSweep(double sweepValue, a2dPoint2D &point) const
calculate Y at X
Definition: curve.cpp:992
bool DoIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
Does hit test on the object (exclusif child objects)
Definition: curve.cpp:1278
CloneOptions
options for cloning
Definition: gen.h:1200
~a2dCurveObject()
destructor
Definition: curve.cpp:398
const a2dAffineMatrix & GetUserToDeviceTransform() const
get matrix which transforms directly from user coordinates to device
Definition: drawer2d.h:503
void SetCorridorPath(bool OnOff, a2dCanvasObject *captureObject=NULL)
to set corridor path ( also to captured object), its a2dCanvasOFlags::IsOnCorridorPath flag is set on...
Definition: canobj.cpp:739
void GetPosXYPoint(int index, double &sweep, double &y, bool upper)
get point x and y at index
Definition: curve.cpp:2293
bool EliminateMatrix()
reduce matrix to identity without replacing object
Definition: curve.cpp:1582
bool Do(void)
Override this to perform a command.
Definition: curve.cpp:114
a2dBoundingBox & GetBbox()
get boundingbox in world coordinates exclusive stroke width relative to its parent ...
Definition: canobj.cpp:3175
structure to give as parameter to member functions of a2dCanvasObject
Definition: canobj.h:252
const double wxPI
defines PI
Definition: artglob.cpp:28
virtual void PushIdentityTransform()
push no transform, to draw directly in device coordinates
Definition: drawer2d.cpp:469
void DoWalker(wxObject *parent, a2dWalkerIOHandler &handler)
iterate over this object and its children
Definition: curve.cpp:2890
virtual void DoWalker(wxObject *parent, a2dWalkerIOHandler &handler)
iterate over this object and its children
Definition: canobj.cpp:5504
bool Do(void)
Override this to perform a command.
Definition: curve.cpp:278
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: curve.cpp:487
const a2dFill * a2dTRANSPARENT_FILL
global a2dFill stock object for TRANSPARENT filling
static const a2dCanvasObjectFlagsMask PRERENDERASCHILD
Definition: candefs.h:198
general canvas module declarations and classes
void WriteStartElement(const wxString &name, bool newLine=true)
Writes start tag which has no attributes.
Definition: genxmlpars.cpp:738
old a complex point at a sweep value
Definition: curve.h:481
wxEditStyle
Definition: canobj.h:109
a base command for the a2dCommandProcessor
Definition: comevt.h:140
curve.cpp Source File -- Sun Oct 12 2014 17:04:15 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation