00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "a2dprec.h"
00012
00013 #ifdef __BORLANDC__
00014 #pragma hdrstop
00015 #endif
00016
00017 #ifndef WX_PRECOMP
00018 #include "wx/wx.h"
00019 #endif
00020
00021 #include <wx/wfstream.h>
00022 #include <math.h>
00023
00024 #if wxART2D_USE_CANEXTOBJ
00025 #include "wx/canextobj/eval.h"
00026 #endif //wxART2D_USE_CANEXTOBJ
00027
00028 #include "wx/curves/meta.h"
00029
00030 #include "wx/canvas/canglob.h"
00031 #include "wx/canvas/canobj.h"
00032 #include "wx/canvas/candoc.h"
00033 #include "wx/canvas/drawer.h"
00034 #include "wx/canvas/canvas.h"
00035 #include "wx/canvas/cancom.h"
00036
00037 #if wxART2D_USE_EDITOR
00038 #include "wx/editor/edit.h"
00039 #endif //wxART2D_USE_EDITOR
00040
00041
00042
00043
00044
00045 IMPLEMENT_CLASS(a2dCurveObject, a2dCanvasObject)
00046 IMPLEMENT_CLASS(a2dCurve, a2dCurveObject)
00047 IMPLEMENT_DYNAMIC_CLASS(a2dFunctionCurve, a2dCurve)
00048 IMPLEMENT_DYNAMIC_CLASS(a2dVertexCurve, a2dCurve)
00049 IMPLEMENT_DYNAMIC_CLASS(a2dSweepCurve, a2dCurve)
00050 IMPLEMENT_DYNAMIC_CLASS(a2dBandCurve, a2dCurve)
00051 IMPLEMENT_DYNAMIC_CLASS(a2dBarCurve, a2dVertexCurve)
00052 IMPLEMENT_DYNAMIC_CLASS(a2dVertexListCurve, a2dCurve)
00053 IMPLEMENT_DYNAMIC_CLASS(a2dPieCurve, a2dCurve)
00054
00055
00056 #ifdef wxUSE_INTPOINT
00057 #define wxMAX_COORDINATE INT_MAX
00058 #define wxMIN_COORDINATE INT_MIN
00059 #else
00060 #define wxMAX_COORDINATE 100e99
00061 #define wxMIN_COORDINATE 100e-99
00062 #endif
00063
00064
00065
00066
00067
00068 class a2dCommand_VertexCurveMovePoint: public a2dCommand
00069 {
00070
00071 public:
00072
00073 static const a2dCommandId COMID_VertexCurveMovePoint;
00074
00075 a2dCommand_VertexCurveMovePoint( a2dVertexCurve* curve, double x, double y, int index );
00076 ~a2dCommand_VertexCurveMovePoint(void);
00077
00078 bool Do(void);
00079 bool Undo(void);
00080
00081 inline a2dCanvasCommandProcessor *GetCanvasCmp() { return wxStaticCast( m_cmp, a2dCanvasCommandProcessor); }
00082
00083 protected:
00084
00085
00086 double m_x;
00087
00088
00089 double m_y;
00090
00091
00092 int m_index;
00093
00094 a2dSmrtPtr<a2dVertexCurve> m_curve;
00095 };
00096
00097 const a2dCommandId a2dCommand_VertexCurveMovePoint::COMID_VertexCurveMovePoint( wxT("VertexCurveMovePoint") );
00098
00099
00100
00101
00102
00103
00104 a2dCommand_VertexCurveMovePoint::a2dCommand_VertexCurveMovePoint( a2dVertexCurve* curve, double x, double y, int index ):
00105 a2dCommand( true, COMID_VertexCurveMovePoint )
00106 {
00107 m_x = x;
00108 m_y = y;
00109 m_index = index;
00110
00111 m_curve = wxStaticCast( curve, a2dVertexCurve );
00112 }
00113
00114 a2dCommand_VertexCurveMovePoint::~a2dCommand_VertexCurveMovePoint(void)
00115 {
00116 }
00117
00118 bool a2dCommand_VertexCurveMovePoint::Do(void)
00119 {
00120 double x, y;
00121 m_curve->GetPosXYPoint( m_index, x, y );
00122 m_curve->SetPosXYPoint( m_index, m_x, m_y );
00123 m_x = x;
00124 m_y = y;
00125
00126 GetCanvasCmp()->GetCanvasDocument()->Modify(true);
00127 GetCanvasCmp()->GetCanvasDocument()->UpdateAllViews( NULL, a2dCANVIEW_UPDATE_OLDNEW );
00128
00129 return true;
00130 }
00131
00132 bool a2dCommand_VertexCurveMovePoint::Undo(void)
00133 {
00134 m_curve->SetPosXYPoint( m_index, m_x, m_y );
00135
00136 GetCanvasCmp()->GetCanvasDocument()->Modify(true);
00137 GetCanvasCmp()->GetCanvasDocument()->UpdateAllViews( NULL, a2dCANVIEW_UPDATE_OLDNEW );
00138
00139 a2dComEvent changed( this, m_curve );
00140 a2dDocviewGlobals->GetEventDistributer()->ProcessEvent( changed );
00141
00142 return true;
00143 }
00144
00145
00146
00147
00148 class a2dCommand_SweepCurveMovePoint: public a2dCommand
00149 {
00150
00151 public:
00152
00153 static const a2dCommandId COMID_SweepCurveMovePoint;
00154
00155 a2dCommand_SweepCurveMovePoint( a2dSweepCurve* curve, double x, double y, int index );
00156
00157 ~a2dCommand_SweepCurveMovePoint(void);
00158
00159 bool Do(void);
00160 bool Undo(void);
00161
00162 inline a2dCanvasCommandProcessor *GetCanvasCmp() { return wxStaticCast( m_cmp, a2dCanvasCommandProcessor); }
00163
00164 protected:
00165
00166 double m_sweep;
00167
00168
00169 double m_x;
00170
00171
00172 double m_y;
00173
00174
00175 int m_index;
00176
00177 a2dSmrtPtr<a2dSweepCurve> m_curve;
00178 };
00179
00180 const a2dCommandId a2dCommand_SweepCurveMovePoint::COMID_SweepCurveMovePoint( wxT("SweepCurveMovePoint") );
00181
00182
00183
00184
00185
00186 a2dCommand_SweepCurveMovePoint::a2dCommand_SweepCurveMovePoint( a2dSweepCurve* curve, double x, double y, int index ):
00187 a2dCommand( true, COMID_SweepCurveMovePoint )
00188 {
00189 m_x = x;
00190 m_y = y;
00191 m_index = index;
00192
00193 m_curve = wxStaticCast( curve, a2dSweepCurve );
00194 }
00195
00196 a2dCommand_SweepCurveMovePoint::~a2dCommand_SweepCurveMovePoint(void)
00197 {
00198 }
00199
00200 bool a2dCommand_SweepCurveMovePoint::Do(void)
00201 {
00202 double x, y;
00203 m_curve->GetPosXYPoint( m_index, x, y );
00204 m_curve->SetPosXYPoint( m_index, m_x, m_y );
00205 m_x = x;
00206 m_y = y;
00207
00208 GetCanvasCmp()->GetCanvasDocument()->Modify(true);
00209 GetCanvasCmp()->GetCanvasDocument()->UpdateAllViews( NULL, a2dCANVIEW_UPDATE_OLDNEW );
00210
00211 return true;
00212 }
00213
00214 bool a2dCommand_SweepCurveMovePoint::Undo(void)
00215 {
00216 m_curve->SetPosXYPoint( m_index, m_x, m_y );
00217
00218 GetCanvasCmp()->GetCanvasDocument()->Modify(true);
00219 GetCanvasCmp()->GetCanvasDocument()->UpdateAllViews( NULL, a2dCANVIEW_UPDATE_OLDNEW );
00220
00221 a2dComEvent changed( this, m_curve );
00222 a2dDocviewGlobals->GetEventDistributer()->ProcessEvent( changed );
00223
00224 return true;
00225 }
00226
00227
00228
00229
00230 class a2dCommand_BandCurveMovePoint: public a2dCommand
00231 {
00232
00233 public:
00234
00235 static const a2dCommandId COMID_BandCurveMovePoint;
00236
00237 a2dCommand_BandCurveMovePoint( a2dBandCurve* curve, double sweep, double y, bool up, int index );
00238
00239 ~a2dCommand_BandCurveMovePoint(void);
00240
00241 bool Do(void);
00242 bool Undo(void);
00243
00244 inline a2dCanvasCommandProcessor *GetCanvasCmp() { return wxStaticCast( m_cmp, a2dCanvasCommandProcessor); }
00245
00246 protected:
00247
00248 bool m_up;
00249
00250 double m_sweep;
00251
00252
00253 double m_y;
00254
00255
00256 int m_index;
00257
00258 a2dSmrtPtr<a2dBandCurve> m_curve;
00259 };
00260
00261 const a2dCommandId a2dCommand_BandCurveMovePoint::COMID_BandCurveMovePoint( wxT("BandCurveMovePoint") );
00262
00263
00264
00265
00266 a2dCommand_BandCurveMovePoint::a2dCommand_BandCurveMovePoint( a2dBandCurve* curve, double sweep, double y, bool up, int index ):
00267 a2dCommand( true, COMID_BandCurveMovePoint )
00268 {
00269 m_sweep = sweep;
00270 m_up = up;
00271 m_y = y;
00272
00273 m_index = index;
00274
00275 m_curve = wxStaticCast( curve, a2dBandCurve );
00276 }
00277
00278 a2dCommand_BandCurveMovePoint::~a2dCommand_BandCurveMovePoint(void)
00279 {
00280 }
00281
00282 bool a2dCommand_BandCurveMovePoint::Do(void)
00283 {
00284 double sweep, y;
00285
00286 m_curve->GetPosXYPoint( m_index, sweep, y, m_up );
00287 m_curve->SetPosXYPoint( m_index, m_sweep, m_y, m_up );
00288 m_sweep = sweep;
00289 m_y = y;
00290
00291 GetCanvasCmp()->GetCanvasDocument()->Modify(true);
00292 GetCanvasCmp()->GetCanvasDocument()->UpdateAllViews( NULL, a2dCANVIEW_UPDATE_OLDNEW );
00293
00294 return true;
00295 }
00296
00297 bool a2dCommand_BandCurveMovePoint::Undo(void)
00298 {
00299 m_curve->SetPosXYPoint( m_index, m_sweep, m_y, m_up );
00300
00301 GetCanvasCmp()->GetCanvasDocument()->Modify(true);
00302 GetCanvasCmp()->GetCanvasDocument()->UpdateAllViews( NULL, a2dCANVIEW_UPDATE_OLDNEW );
00303
00304 a2dComEvent changed( this, m_curve );
00305 a2dDocviewGlobals->GetEventDistributer()->ProcessEvent( changed );
00306
00307 return true;
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 class a2dCommand_VertexListCurveMovePoint: public a2dCommand
00320 {
00321
00322 public:
00323 a2dCommand_VertexListCurveMovePoint( a2dVertexListCurve* curve, double x, double y, int index );
00324
00325 ~a2dCommand_VertexListCurveMovePoint(void);
00326
00327 bool Do(void);
00328 bool Undo(void);
00329
00330 inline a2dCanvasCommandProcessor *GetCanvasCmp() { return wxStaticCast( m_cmp, a2dCanvasCommandProcessor); }
00331
00332 static const a2dCommandId COMID_VertexListCurveMovePoint;
00333
00334 protected:
00335
00336
00337 double m_x;
00338
00339
00340 double m_y;
00341
00342
00343 int m_index;
00344
00345 a2dSmrtPtr<a2dVertexListCurve> m_curve;
00346 };
00347
00348 const a2dCommandId a2dCommand_VertexListCurveMovePoint::COMID_VertexListCurveMovePoint( wxT("VertexListCurveMovePoint") );
00349
00350 a2dCommand_VertexListCurveMovePoint::a2dCommand_VertexListCurveMovePoint( a2dVertexListCurve* curve, double x, double y, int index ):
00351 a2dCommand( true, COMID_VertexListCurveMovePoint )
00352 {
00353 m_x = x;
00354 m_y = y;
00355 m_index = index;
00356
00357 m_curve = wxStaticCast( curve, a2dVertexListCurve ) ;
00358 }
00359
00360 a2dCommand_VertexListCurveMovePoint::~a2dCommand_VertexListCurveMovePoint(void)
00361 {
00362 }
00363
00364 bool a2dCommand_VertexListCurveMovePoint::Do(void)
00365 {
00366 double x, y;
00367 m_curve->GetPosXYPoint( m_index, x, y );
00368 m_curve->SetPosXYPoint( m_index, m_x, m_y );
00369 m_x = x;
00370 m_y = y;
00371
00372 GetCanvasCmp()->GetCanvasDocument()->Modify(true);
00373 GetCanvasCmp()->GetCanvasDocument()->UpdateAllViews( NULL, a2dCANVIEW_UPDATE_OLDNEW );
00374
00375 return true;
00376 }
00377
00378 bool a2dCommand_VertexListCurveMovePoint::Undo(void)
00379 {
00380 m_curve->SetPosXYPoint( m_index, m_x, m_y );
00381
00382 GetCanvasCmp()->GetCanvasDocument()->Modify(true);
00383 GetCanvasCmp()->GetCanvasDocument()->UpdateAllViews( NULL, a2dCANVIEW_UPDATE_OLDNEW );
00384
00385 a2dComEvent changed( this, m_curve );
00386 a2dDocviewGlobals->GetEventDistributer()->ProcessEvent( changed );
00387
00388 return true;
00389 }
00390
00391
00392
00393
00394
00395
00396
00397 a2dCurveObject::a2dCurveObject()
00398 {
00399 m_curvesArea = NULL;
00400 }
00401
00402 a2dCurveObject::~a2dCurveObject()
00403 {
00404 }
00405
00406
00407 a2dCurveObject::a2dCurveObject( const a2dCurveObject& other, CloneOptions options )
00408 :a2dCanvasObject( other, options )
00409 {
00410 m_curvesArea = other.m_curvesArea;
00411 m_untransbbox = other.m_untransbbox;
00412 }
00413
00414
00415 void a2dCurveObject::World2Curve( double xw, double yw, double& xcurve, double& ycurve ) const
00416 {
00417
00418
00419 if ( m_curvesArea )
00420 m_curvesArea->World2Curve( xw, yw, xcurve, ycurve );
00421 else
00422 {
00423 a2dAffineMatrix mat = m_lworld;
00424 mat.Invert();
00425 mat.TransformPoint( xw, yw, xcurve, ycurve );
00426 }
00427 }
00428
00429 void a2dCurveObject::Curve2World( double xcurve, double ycurve, double& xw, double& yw ) const
00430 {
00431
00432
00433 if ( m_curvesArea )
00434 m_curvesArea->Curve2World( xcurve, ycurve, xw, yw );
00435 else
00436 {
00437 m_lworld.TransformPoint( xcurve, ycurve, xw, yw );
00438 }
00439 }
00440
00441 bool a2dCurveObject::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
00442 {
00443 if ( !m_bbox.GetValid())
00444 {
00445 m_untransbbox = m_bbox = DoGetUnTransformedBbox();
00446 if ( m_bbox.GetValid() )
00447 {
00448 m_bbox.MapBbox(m_lworld);
00449 return true;
00450 }
00451 }
00452
00453 return false;
00454 }
00455
00456
00457
00458
00459
00460 a2dCurve::a2dCurve(): a2dCurveObject()
00461 {
00462 m_highlightmode = 0;
00463 m_logFunction = wxNO_OP;
00464 m_clipdata.SetValid(false);
00465 m_curveBox.SetValid(false);
00466 }
00467
00468 a2dCurve::~a2dCurve()
00469 {
00470 }
00471
00472 a2dCurve::a2dCurve( const a2dCurve &other, CloneOptions options )
00473 :a2dCurveObject( other, options )
00474 {
00475 m_clipdata = other.m_clipdata;
00476 m_highlightmode = other.m_highlightmode;
00477 m_pointsFill = other.m_pointsFill;
00478 m_logFunction = other.m_logFunction;
00479 m_curveBox = other.m_curveBox;
00480 }
00481
00482 void a2dCurve::SetBoundaries( double xmin, double ymin, double xmax, double ymax )
00483 {
00484 SetPending(true);
00485 m_clipdata.SetValid(false);
00486 m_clipdata.Expand(xmin,ymin);
00487 m_clipdata.Expand(xmax,ymax);
00488 }
00489
00490 #if wxART2D_USE_CVGIO
00491 void a2dCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
00492 {
00493 a2dCanvasObject::DoSave( parent, out, xmlparts, towrite );
00494 if ( xmlparts == a2dXmlSer_attrib )
00495 {
00496 if ( m_clipdata.GetValid() )
00497 {
00498 out.WriteAttribute( wxT("xmin") , m_clipdata.GetMinX() );
00499 out.WriteAttribute( wxT("ymin") , m_clipdata.GetMinY() );
00500 out.WriteAttribute( wxT("xmax") , m_clipdata.GetMaxX() );
00501 out.WriteAttribute( wxT("ymax") , m_clipdata.GetMaxY() );
00502 }
00503 }
00504 else
00505 {
00506 }
00507 }
00508
00509 void a2dCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
00510 {
00511 a2dCanvasObject::DoLoad( parent, parser, xmlparts );
00512 if ( xmlparts == a2dXmlSer_attrib )
00513 {
00514 if ( parser.HasAttribute( wxT("xmin") ) )
00515 {
00516 m_clipdata.SetValid(false);
00517 m_clipdata.Expand(parser.GetAttributeValueDouble( wxT("xmin")), parser.RequireAttributeValueDouble( wxT("ymin")) );
00518 m_clipdata.Expand(parser.GetAttributeValueDouble( wxT("xmax")), parser.RequireAttributeValueDouble( wxT("ymax")) );
00519 }
00520 }
00521 else
00522 {
00523 }
00524 }
00525 #endif //wxART2D_USE_CVGIO
00526
00527
00528 a2dBoundingBox a2dCurve::GetClippedCurveBoundaries()
00529 {
00530 a2dBoundingBox curvebox = GetCurveBoundaries();
00531 if ( m_clipdata.GetValid() )
00532 {
00533 if(!curvebox.And(&m_clipdata))
00534 {
00535 curvebox.SetValid(false);
00536 return curvebox;
00537 }
00538 }
00539
00540 a2dBoundingBox areabox = m_curvesArea->GetInternalBoundaries();
00541 if(curvebox.GetValid() && !curvebox.And(&areabox))
00542 curvebox.SetValid(false);
00543 return curvebox;
00544 }
00545
00546 a2dBoundingBox a2dCurve::GetCurveBoundaries()
00547 {
00548 return m_curveBox;
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 a2dFunctionCurve::a2dFunctionCurve( const wxString& curve ): a2dCurve()
00617 {
00618 m_curve = curve;
00619 #if wxART2D_USE_CANEXTOBJ
00620 m_toeval.SetEvalString(m_curve);
00621 #endif //wxART2D_USE_CANEXTOBJ
00622
00623 m_xstart = wxMIN_COORDINATE;
00624 m_xstop = wxMAX_COORDINATE;
00625 m_xstep = (m_xstop - m_xstart)/100.0;
00626 }
00627
00628 a2dFunctionCurve::~a2dFunctionCurve()
00629 {
00630 }
00631
00632 a2dFunctionCurve::a2dFunctionCurve( const a2dFunctionCurve &other, CloneOptions options )
00633 :a2dCurve( other, options )
00634 {
00635 m_curve = other.m_curve;
00636 #if wxART2D_USE_CANEXTOBJ
00637 m_toeval.SetEvalString(m_curve);
00638 #endif //wxART2D_USE_CANEXTOBJ
00639 m_xstep = other.m_xstep;
00640 m_xstart = other.m_xstart;
00641 m_xstop = other.m_xstop;
00642 }
00643
00644 a2dObject* a2dFunctionCurve::Clone( CloneOptions options ) const
00645 {
00646 return new a2dFunctionCurve( *this, options );
00647 }
00648
00649 bool a2dFunctionCurve::GetXyAtSweep( double sweepValue, a2dPoint2D& point ) const
00650 {
00651 #if wxART2D_USE_CANEXTOBJ
00652 TYPENUMBER result;
00653 int a;
00654 m_toeval.ClearAllVars();
00655
00656 m_toeval.SetValue(wxT("x") , sweepValue );
00657 m_toeval.Evaluate( &result, &a );
00658 m_toeval.GetValue(wxT("y") ,&point.m_y);
00659
00660 point.m_x = sweepValue;
00661 return true;
00662 #else
00663 point.m_x = 0;
00664 point.m_y = 0;
00665 return false;
00666 #endif //wxART2D_USE_CANEXTOBJ
00667 }
00668
00669 a2dBoundingBox a2dFunctionCurve::DoGetUnTransformedBbox( a2dBboxFlags flags ) const
00670 {
00671 a2dBoundingBox bbox;
00672 double x;
00673 if (m_clipdata.GetValid())
00674 {
00675 m_curveBox.SetValid(false);
00676 double start = wxMax( m_clipdata.GetMinX(), m_xstart );
00677 double stop = wxMin( m_clipdata.GetMaxX(), m_xstop );
00678 for ( x = start; x <= stop; x = x + m_xstep )
00679 {
00680 double xw, yw;
00681 a2dPoint2D point;
00682 GetXyAtSweep( x, point );
00683 m_curveBox.Expand(point);
00684 Curve2World( point.m_x, point.m_y, xw, yw );
00685 bbox.Expand( xw , yw );
00686 }
00687 }
00688 else
00689 bbox.Expand( 0,0);
00690 return bbox;
00691 }
00692
00693 bool a2dFunctionCurve::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
00694 {
00695 if ( !m_bbox.GetValid())
00696 {
00697 m_bbox = DoGetUnTransformedBbox();
00698 m_bbox.MapBbox(m_lworld);
00699
00700 if (m_clipdata.GetValid())
00701 {
00702 double xw, yw;
00703 Curve2World( m_clipdata.GetMaxX(), m_clipdata.GetMaxY(), xw, yw );
00704 a2dBoundingBox box;
00705 box.Expand( xw, yw );
00706 Curve2World( m_clipdata.GetMinX(), m_clipdata.GetMinY(), xw, yw );
00707 box.Expand( xw, yw );
00708 box.MapBbox(m_lworld);
00709
00710 m_bbox.And(&box);
00711 }
00712
00713 a2dBoundingBox box = m_curvesArea->GetGroup()->GetPlotAreaBbox();
00714 m_bbox.And( &box );
00715 return true;
00716 }
00717
00718 return false;
00719 }
00720
00721 void a2dFunctionCurve::DoRender( a2dIterC& ic, OVERLAP WXUNUSED(clipparent) )
00722 {
00723 a2dBoundingBox curvebox = GetClippedCurveBoundaries();
00724 if(!curvebox.GetValid())
00725 return;
00726 double x;
00727 bool second = false;
00728 double xprev = 0, yprev = 0;
00729 if (m_clipdata.GetValid())
00730 {
00731 wxRasterOperationMode prevlogfunction = wxNO_OP;
00732 wxDC* aDC = NULL;
00733 if(m_logFunction != wxNO_OP)
00734 {
00735 aDC = ic.GetDrawer2D()->GetRenderDC();
00736 prevlogfunction = aDC->GetLogicalFunction();
00737 aDC->SetLogicalFunction(m_logFunction);
00738 }
00739 for ( x = curvebox.GetMinX(); x < curvebox.GetMaxX(); x = x + m_xstep )
00740 {
00741 double xw, yw;
00742 a2dPoint2D point;
00743 GetXyAtSweep( x, point );
00744 Curve2World( x, point.m_y, xw, yw );
00745 if (second)
00746 {
00747 ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
00748 }
00749 xprev = xw;
00750 yprev = yw;
00751 second = true;
00752 }
00753 if(aDC)
00754 aDC->SetLogicalFunction(prevlogfunction);
00755 }
00756 }
00757
00758 bool a2dFunctionCurve::DoIsHitWorld( a2dIterC& ic, a2dHitEvent& hitEvent )
00759 {
00760 double pw = ic.GetWorldStrokeExtend();
00761 double margin = ic.GetTransformedHitMargin();
00762
00763 double xw, yw, xcurve, ycurve;
00764 World2Curve( hitEvent.m_relx, hitEvent.m_rely, xcurve, ycurve );
00765
00766 a2dPoint2D point;
00767 GetXyAtSweep( xcurve, point );
00768 Curve2World( point.m_x, point.m_y, xw, yw );
00769
00770 if ( fabs( yw - hitEvent.m_rely ) < pw+margin )
00771 {
00772 hitEvent.m_how = a2dHit::stock_strokeoutside;
00773 return true;
00774 }
00775 else
00776 {
00777 hitEvent.m_how = a2dHit::stock_nohit;
00778 return false;
00779 }
00780 }
00781
00782 #if wxART2D_USE_CVGIO
00783 void a2dFunctionCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
00784 {
00785 a2dCurve::DoSave( parent, out, xmlparts, towrite );
00786 if ( xmlparts == a2dXmlSer_attrib )
00787 {
00788 }
00789 else
00790 {
00791 }
00792 }
00793
00794 void a2dFunctionCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
00795 {
00796 a2dCurve::DoLoad( parent, parser, xmlparts );
00797 if ( xmlparts == a2dXmlSer_attrib )
00798 {
00799 }
00800 else
00801 {
00802 }
00803 }
00804 #endif //wxART2D_USE_CVGIO
00805
00806
00807
00808
00809 A2D_BEGIN_EVENT_TABLE(a2dVertexCurve,a2dCurve)
00810 A2D_EVT_CANVASOBJECT_MOUSE_EVENT( a2dVertexCurve::OnCanvasObjectMouseEvent )
00811 A2D_EVT_CANVASOBJECT_ENTER_EVENT( a2dVertexCurve::OnEnterObject )
00812 A2D_EVT_CANVASOBJECT_LEAVE_EVENT( a2dVertexCurve::OnLeaveObject )
00813 A2D_EVT_CANVASHANDLE_MOUSE_EVENT( a2dVertexCurve::OnHandleEvent )
00814 A2D_END_EVENT_TABLE()
00815
00816
00817 a2dVertexCurve::a2dVertexCurve( a2dVertexArray* points ): a2dCurve()
00818 {
00819 m_points = points;
00820 m_spline = false;
00821 m_rendermode = a2dCURVES_RENDER_DEFAULT;
00822 m_editmode = a2dCURVES_EDIT_DEFAULT;
00823 }
00824
00825 a2dVertexCurve::a2dVertexCurve( ): a2dCurve()
00826 {
00827 m_points = new a2dVertexArray;
00828 m_spline = false;
00829 m_rendermode = a2dCURVES_RENDER_DEFAULT;
00830 m_editmode = a2dCURVES_EDIT_DEFAULT;
00831 }
00832
00833
00834 a2dVertexCurve::~a2dVertexCurve()
00835 {
00836 delete m_points;
00837 }
00838
00839 a2dVertexCurve::a2dVertexCurve( const a2dVertexCurve &other, CloneOptions options )
00840 :a2dCurve( other, options )
00841 {
00842 m_points = new a2dVertexArray;
00843 *m_points = *other.m_points;
00844
00845 m_spline = other.m_spline;
00846
00847 m_rendermode = other.m_rendermode;
00848 m_editmode = other.m_editmode;
00849 }
00850
00851 a2dObject* a2dVertexCurve::Clone( CloneOptions options ) const
00852 {
00853 return new a2dVertexCurve( *this, options );
00854 };
00855
00856 bool a2dVertexCurve::EliminateMatrix()
00857 {
00858 if (!m_lworld.IsIdentity())
00859 {
00860 for( a2dVertexArray::const_iterator iter = m_points->begin(); iter != m_points->end(); ++iter )
00861 {
00862 a2dLineSegmentPtr seg = (*iter)->Clone();
00863 m_lworld.TransformPoint( seg->m_x, seg->m_y, seg->m_x, seg->m_y );
00864 }
00865
00866 }
00867
00868 return a2dCanvasObject::EliminateMatrix();
00869 }
00870
00871 void a2dVertexCurve::SetPosXYPoint(int n, double x, double y )
00872 {
00873 m_points->Item(n)->m_x = x;
00874 m_points->Item(n)->m_y = y;
00875
00876 SetPending(true);
00877 }
00878
00879 void a2dVertexCurve::RemovePoint( double& x, double& y , int index )
00880 {
00881 if ( index == -1 )
00882 index = m_points->size();
00883
00884 x = m_points->Item( index )->m_x;
00885 y = m_points->Item( index )->m_y;
00886 m_points->RemoveAt( index );
00887 }
00888
00889 void a2dVertexCurve::RemovePointWorld( double& x, double& y , int index, bool transformed )
00890 {
00891 if ( index == -1 )
00892 index = m_points->size();
00893
00894 x = m_points->Item( index )->m_x;
00895 y = m_points->Item( index )->m_y;
00896 m_points->RemoveAt( index );
00897
00898 Curve2World( x, y, x, y );
00899
00900 if ( transformed )
00901 {
00902 m_lworld.TransformPoint( x, y, x, y );
00903 }
00904
00905 }
00906
00907 void a2dVertexCurve::AddPoint( const a2dPoint2D& P, int index )
00908 {
00909 AddPoint( P.m_x, P.m_y, index );
00910 }
00911
00912 void a2dVertexCurve::AddPoint( double x, double y, int index )
00913 {
00914 a2dLineSegment* point = new a2dLineSegment( x, y );
00915
00916 if ( index == -1 )
00917 m_points->push_back( point );
00918 else
00919 m_points->Insert( point, index );
00920
00921 SetPending(true);
00922 }
00923
00924 void a2dVertexCurve::GetPosXYPoint(int index, double& x, double& y )
00925 {
00926 if ( index == -1 )
00927 index = m_points->size();
00928
00929 x = m_points->Item( index )->m_x;
00930 y = m_points->Item( index )->m_y;
00931 }
00932
00933 void a2dVertexCurve::GetPosXYPointWorld(int index, double& x, double& y, bool transform )
00934 {
00935 if ( index == -1 )
00936 index = m_points->size();
00937
00938 x = m_points->Item( index )->m_x;
00939 y = m_points->Item( index )->m_y;
00940 Curve2World( x, y, x, y );
00941
00942 if ( transform )
00943 {
00944 m_lworld.TransformPoint( x, y, x, y );
00945 }
00946 }
00947
00948 bool a2dVertexCurve::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
00949 {
00950 if ( m_flags.m_editable )
00951 {
00952 if ( editmode == 1 )
00953 {
00954 m_flags.m_draggable = false;
00955
00956 m_flags.m_visiblechilds = true;
00957 m_flags.m_childrenOnSameLayer = true;
00958
00959
00960 a2dVertexArray* array = GetPoints();
00961 size_t i;
00962 for ( i=0; i< array->size(); i++)
00963 {
00964 double xw, yw;
00965 Curve2World( array->Item(i)->m_x, array->Item(i)->m_y, xw, yw );
00966
00967
00968 a2dHandle* handle = new a2dHandle( this, xw, yw, wxT("__index__") );
00969 handle->SetLayer( m_layer );
00970 Append(handle);
00971 handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
00972 PROPID_Index->SetPropertyToObject( handle, i );
00973 }
00974 m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT("a2dHandle") );
00975
00976
00977
00978 Update( updatemask_force );
00979
00980
00981 SetPending( true );
00982 return true;
00983 }
00984 else
00985 {
00986 PROPID_Allowrotation->SetPropertyToObject( this, true );
00987 PROPID_Allowskew->SetPropertyToObject( this, true );
00988
00989 return a2dCanvasObject::DoStartEdit( editmode, editstyle );
00990 }
00991 }
00992
00993 return false;
00994 }
00995
00996 bool a2dVertexCurve::GetXyAtSweep( double sweepValue, a2dPoint2D& point ) const
00997 {
00998 double xp,yp;
00999 if(!m_points->size())
01000 return false;
01001
01002 xp = m_points->Item(0)->m_x;
01003 yp = m_points->Item(0)->m_y;
01004
01005 if ( sweepValue <= m_points->Item(0)->m_x )
01006 {
01007 point.m_x = m_points->Item(0)->m_x;
01008 point.m_y = m_points->Item(0)->m_y;
01009 return false;
01010 }
01011
01012 unsigned int i;
01013 for (i=0; i < m_points->size(); i++)
01014 {
01015 if ( xp < sweepValue && m_points->Item(i)->m_x >= sweepValue )
01016 {
01017 point.m_x = sweepValue;
01018 point.m_y = (m_points->Item(i)->m_y-yp) * (sweepValue-xp)/(m_points->Item(i)->m_x-xp) + yp;
01019 return true;
01020 }
01021 xp = m_points->Item(i)->m_x;
01022 yp = m_points->Item(i)->m_y;
01023 }
01024
01025
01026 point.m_x = m_points->Item(i-1)->m_x;
01027 point.m_y = m_points->Item(i-1)->m_y;
01028
01029 return false;
01030 }
01031
01032 a2dBoundingBox a2dVertexCurve::DoGetUnTransformedBbox( a2dBboxFlags flags ) const
01033 {
01034 a2dBoundingBox bbox;
01035 unsigned int i;
01036 double xw,yw;
01037 m_curveBox.SetValid(false);
01038 for (i=0; i < m_points->size();i++)
01039 {
01040 m_curveBox.Expand(m_points->Item(i)->m_x, m_points->Item(i)->m_y);
01041 Curve2World( m_points->Item(i)->m_x, m_points->Item(i)->m_y, xw, yw );
01042 bbox.Expand( xw, yw );
01043 }
01044 return bbox;
01045 }
01046
01047 bool a2dVertexCurve::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
01048 {
01049 if ( !m_bbox.GetValid() && m_points->size() )
01050 {
01051 m_bbox = DoGetUnTransformedBbox();
01052 m_bbox.MapBbox(m_lworld);
01053
01054 if (m_clipdata.GetValid())
01055 {
01056 double xw, yw;
01057 Curve2World( m_clipdata.GetMaxX(), m_clipdata.GetMaxY(), xw, yw );
01058 a2dBoundingBox box;
01059 box.Expand( xw, yw );
01060 Curve2World( m_clipdata.GetMinX(), m_clipdata.GetMinY(), xw, yw );
01061 box.Expand( xw, yw );
01062 box.MapBbox(m_lworld);
01063
01064 m_bbox.And(&box);
01065 }
01066
01067 a2dBoundingBox box = m_curvesArea->GetGroup()->GetPlotAreaBbox();
01068 m_bbox.And( &box );
01069 return true;
01070 }
01071 return false;
01072 }
01073
01074 void a2dVertexCurve::DoRender( a2dIterC& ic, OVERLAP WXUNUSED(clipparent) )
01075 {
01076
01077
01078 a2dBoundingBox curvebox = GetClippedCurveBoundaries();
01079 if(!curvebox.GetValid())
01080 return;
01081
01082 unsigned int i = 0;
01083 double xw,yw;
01084 if (!(m_rendermode & a2dCURVES_RENDER_NO_POINTS))
01085 {
01086 a2dStroke current = ic.GetDrawer2D()->GetDrawerStroke();
01087 a2dFill fillcurrent = ic.GetDrawer2D()->GetDrawerFill();
01088
01089 a2dStroke highlight = a2dStroke(wxColour(239,2,0),3);
01090
01091 if ( m_highlightmode )
01092 {
01093 ic.GetDrawer2D()->SetDrawerStroke( highlight );
01094 ic.GetDrawer2D()->SetDrawerFill( *a2dBLACK_FILL );
01095 }
01096 else
01097 {
01098 ic.GetDrawer2D()->SetDrawerStroke( *a2dBLACK_STROKE );
01099 ic.GetDrawer2D()->SetDrawerFill( *a2dTRANSPARENT_FILL );
01100 }
01101
01102 bool firstPoint = true;
01103 for (i=0; i < m_points->size();i++)
01104 {
01105 if ( m_points->Item(i)->m_x >= curvebox.GetMinX() )
01106 {
01107 if(firstPoint && i)
01108 {
01109 Curve2World( m_points->Item(i-1)->m_x, m_points->Item(i-1)->m_y, xw, yw );
01110 double xd,yd;
01111 ic.GetTransform().TransformPoint( xw, yw, xd, yd );
01112
01113 int radius = 2;
01114 ic.GetDrawer2D()->PushIdentityTransform();
01115 ic.GetDrawer2D()->DrawCircle( ic.GetDrawer2D()->WorldToDeviceX( xd ), ic.GetDrawer2D()->WorldToDeviceY( yd ), radius );
01116 ic.GetDrawer2D()->PopTransform();
01117 }
01118 firstPoint = false;
01119 Curve2World( m_points->Item(i)->m_x, m_points->Item(i)->m_y, xw, yw );
01120 double xd,yd;
01121 ic.GetTransform().TransformPoint( xw, yw, xd, yd );
01122
01123 int radius = 2;
01124 ic.GetDrawer2D()->PushIdentityTransform();
01125 ic.GetDrawer2D()->DrawCircle( ic.GetDrawer2D()->WorldToDeviceX( xd ), ic.GetDrawer2D()->WorldToDeviceY( yd ), radius );
01126 ic.GetDrawer2D()->PopTransform();
01127 }
01128 if ( m_points->Item(i)->m_x > curvebox.GetMaxX() )
01129 {
01130 Curve2World( m_points->Item(i)->m_x, m_points->Item(i)->m_y, xw, yw );
01131 double xd,yd;
01132 ic.GetTransform().TransformPoint( xw, yw, xd, yd );
01133
01134 int radius = 2;
01135 ic.GetDrawer2D()->PushIdentityTransform();
01136 ic.GetDrawer2D()->DrawCircle( ic.GetDrawer2D()->WorldToDeviceX( xd ), ic.GetDrawer2D()->WorldToDeviceY( yd ), radius );
01137 ic.GetDrawer2D()->PopTransform();
01138 break;
01139 }
01140 }
01141
01142 ic.GetDrawer2D()->SetDrawerStroke( current );
01143 ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
01144 }
01145
01146 wxRasterOperationMode prevlogfunction = wxNO_OP;
01147 wxDC* aDC = NULL;
01148 if(m_logFunction != wxNO_OP)
01149 {
01150 aDC = ic.GetDrawer2D()->GetRenderDC();
01151 wxASSERT_MSG(aDC,wxT("TODO: aDC not defined for aggdrawer"));
01152 prevlogfunction = aDC->GetLogicalFunction();
01153 aDC->SetLogicalFunction(m_logFunction);
01154 }
01155 if (m_rendermode & a2dCURVES_RENDER_NORMAL)
01156 {
01157 double xprev = 0, yprev = 0;
01158 if(m_points->size())
01159 Curve2World(m_points->Item(0)->m_x, m_points->Item(0)->m_y, xprev, yprev);
01160 int iprev = 0;
01161 for (i=1; i < m_points->size(); i++)
01162 {
01163 if ( m_points->Item(i)->m_x >= curvebox.GetMinX() )
01164 {
01165 Curve2World( m_points->Item(i)->m_x, m_points->Item(i)->m_y, xw, yw );
01166 if(iprev != i-1)
01167 Curve2World( m_points->Item(i-1)->m_x, m_points->Item(i-1)->m_y, xprev, yprev );
01168 ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
01169 xprev = xw; yprev = yw;
01170 iprev = i;
01171 }
01172 if ( m_points->Item(i)->m_x > curvebox.GetMaxX() )
01173 break;
01174 }
01175 }
01176 else if (m_rendermode & a2dCURVES_RENDER_FILL_LINE)
01177 {
01178 double xprev = 0, yprev = 0;
01179 double yw0;
01180 Curve2World( m_points->Item(i)->m_x, 0, xw, yw0 );
01181 for (i=1; i < m_points->size(); i++)
01182 {
01183 if ( m_points->Item(i)->m_x >= curvebox.GetMinX() )
01184 {
01185 Curve2World( m_points->Item(i)->m_x, m_points->Item(i)->m_y, xw, yw );
01186 ic.GetDrawer2D()->DrawLine( xw, yw0, xw, yw );
01187 Curve2World( m_points->Item(i-1)->m_x, m_points->Item(i-1)->m_y, xprev, yprev );
01188 ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
01189 }
01190 if ( m_points->Item(i)->m_x > curvebox.GetMaxX() )
01191 break;
01192 }
01193 }
01194 else if (m_rendermode & a2dCURVES_RENDER_FILL)
01195 {
01196 a2dVertexArray* cpoints = new a2dVertexArray;
01197
01198 bool first = false;
01199
01200 for (i=0; i < m_points->size(); i++)
01201 {
01202 if ( m_points->Item(i)->m_x >= curvebox.GetMinX() )
01203 {
01204 Curve2World( m_points->Item(i)->m_x, m_points->Item(i)->m_y, xw, yw );
01205
01206 if ( ! first )
01207 { double xw0,yw0;
01208 Curve2World( m_points->Item(i)->m_x, 0, xw0, yw0 );
01209 cpoints->push_back( new a2dLineSegment( xw0, yw0 ) );
01210 }
01211 cpoints->push_back( new a2dLineSegment( xw, yw ) );
01212 first = true;
01213 }
01214 if ( m_points->Item(i)->m_x > curvebox.GetMaxX() )
01215 break;
01216 }
01217 double xw0,yw0;
01218 Curve2World( m_points->Item(i-1)->m_x, 0, xw0, yw0 );
01219 cpoints->push_back( new a2dLineSegment( xw0, yw0 ) );
01220
01221 ic.GetDrawer2D()->DrawPolygon( cpoints, false, wxWINDING_RULE);
01222 delete cpoints;
01223 }
01224 if(aDC)
01225 aDC->SetLogicalFunction(prevlogfunction);
01226 }
01227
01228 #if wxART2D_USE_CVGIO
01229 void a2dVertexCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
01230 {
01231 a2dCurve::DoSave( parent, out, xmlparts, towrite );
01232 if ( xmlparts == a2dXmlSer_attrib )
01233 {
01234 if ( m_spline )
01235 {
01236 out.WriteAttribute( wxT("spline") , m_spline );
01237 }
01238 out.WriteAttribute( wxT("points") , m_points->size() );
01239 out.WriteAttribute( wxT("rendermode") , m_rendermode );
01240 out.WriteAttribute( wxT("editmode") , m_editmode );
01241 }
01242 else
01243 {
01244 unsigned int i;
01245 for (i = 0; i < m_points->size(); i++)
01246 {
01247 if (i%6==0)
01248 out.WriteNewLine();
01249 out.WriteStartElementAttributes( wxT("xy") );
01250 out.WriteAttribute( wxT("x") , m_points->Item(i)->m_x );
01251 out.WriteAttribute( wxT("y") , m_points->Item(i)->m_y );
01252 out.WriteEndAttributes( true );
01253 }
01254 }
01255 }
01256
01257 void a2dVertexCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
01258 {
01259 a2dCurve::DoLoad( parent, parser, xmlparts );
01260 if ( xmlparts == a2dXmlSer_attrib )
01261 {
01262 m_spline = parser.GetAttributeValueBool( wxT("spline"), false );
01263 m_rendermode = parser.GetAttributeValueInt( wxT("rendermode") );
01264 m_editmode = parser.GetAttributeValueInt( wxT("editmode") );
01265 }
01266 else
01267 {
01268 while( parser.GetTagName() == wxT("xy") )
01269 {
01270 double x = parser.GetAttributeValueDouble( wxT("x") );
01271 double y = parser.GetAttributeValueDouble( wxT("y") );
01272 a2dLineSegment* point = new a2dLineSegment( x, y );
01273 m_points->push_back( point );
01274
01275 parser.Next();
01276 parser.Require( END_TAG, wxT("xy") );
01277 parser.Next();
01278 }
01279 }
01280 }
01281 #endif //wxART2D_USE_CVGIO
01282
01283 bool a2dVertexCurve::DoIsHitWorld( a2dIterC& ic, a2dHitEvent& hitEvent )
01284 {
01285
01286 double xcurve, ycurve;
01287 World2Curve( hitEvent.m_relx, hitEvent.m_rely, xcurve, ycurve );
01288
01289 a2dPoint2D P = a2dPoint2D( xcurve, ycurve );
01290 double pw = ic.GetWorldStrokeExtend();
01291 double margin = ic.GetTransformedHitMargin();
01292
01293 if ( PointOnCurve(P, pw+margin) )
01294 {
01295 hitEvent.m_how = a2dHit::stock_strokeoutside;
01296 return true;
01297 }
01298 else
01299 {
01300 hitEvent.m_how = a2dHit::stock_nohit;
01301 return false;
01302 }
01303 }
01304
01305 bool a2dVertexCurve::PointOnCurve(const a2dPoint2D& P, double margin)
01306 {
01307 bool result = false;
01308 double distance;
01309 a2dPoint2D p1,p2;
01310
01311 if(m_points->size())
01312 {
01313 p2=m_points->Item(0)->GetPoint();
01314 unsigned int i;
01315 for (i = 0; i < m_points->size()-1; i++)
01316 {
01317 p1=p2;
01318 p2=m_points->Item(i+1)->GetPoint();
01319 if (margin > sqrt(pow(p1.m_x-P.m_x,2)+pow(p1.m_y-P.m_y,2)))
01320 {
01321 result=true;
01322 break;
01323 }
01324 else if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
01325 {
01326 a2dLine line1(p1,p2);
01327 if (line1.PointInLine(P,distance,margin) == R_IN_AREA)
01328 {
01329 result=true;
01330 break;
01331 }
01332 }
01333 }
01334 }
01335
01336 return result;
01337 }
01338
01339 void a2dVertexCurve::OnHandleEvent(a2dHandleMouseEvent &event)
01340 {
01341 a2dIterC* ic = event.GetIterC();
01342
01343 if ( m_flags.m_editingCopy )
01344 {
01345 double xw,yw;
01346 xw = event.GetX();
01347 yw = event.GetY();
01348
01349 a2dAffineMatrix atWorld = ic->GetTransform();
01350
01351
01352
01353
01354 a2dAffineMatrix inverselocal = m_lworld;
01355 inverselocal.Invert();
01356
01357 a2dAffineMatrix inverse = ic->GetInverseParentTransform();
01358
01359 double xinternal, yinternal;
01360 inverse.TransformPoint(xw, yw, xinternal, yinternal);
01361
01362 World2Curve( xinternal, yinternal, xinternal, yinternal );
01363
01364 a2dHandle* draghandle = event.GetCanvasHandle();
01365 wxUint16 index = PROPID_Index->GetPropertyValue( draghandle );
01366
01367 wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
01368
01369 if ( editmode == 1 )
01370 {
01371 if (!(m_editmode & a2dCURVES_EDIT_NORMAL))
01372 {
01373 a2dPoint2D p1;
01374 p1 = m_points->Item(index)->GetPoint();
01375
01376 if (m_editmode & a2dCURVES_EDIT_FIXED_X)
01377 {
01378 xinternal = p1.m_x;
01379 }
01380 else if (m_editmode & a2dCURVES_EDIT_FIXED_Y)
01381 {
01382 yinternal = p1.m_y;
01383 }
01384 }
01385
01386 a2dVertexCurve* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dVertexCurve );
01387
01388 double xwi;
01389 double ywi;
01390 Curve2World( xinternal, yinternal, xwi, ywi );
01391
01392 if (event.GetMouseEvent().LeftUp() )
01393 {
01394 if ( draghandle->GetName() == wxT("__index__") )
01395 {
01396 m_root->GetCommandProcessor()->Submit(new a2dCommand_VertexCurveMovePoint( original, xinternal, yinternal, index ));
01397 }
01398 else
01399 event.Skip();
01400 }
01401 else if ( event.GetMouseEvent().Dragging() )
01402 {
01403 SetPosXYPoint( index, xinternal, yinternal );
01404 draghandle->SetPosXY( xwi, ywi );
01405 }
01406 else
01407 event.Skip();
01408 }
01409 else
01410 event.Skip();
01411 }
01412 else
01413 {
01414 event.Skip();
01415 }
01416 }
01417
01418 void a2dVertexCurve::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
01419 {
01420 a2dIterC* ic = event.GetIterC();
01421
01422 if ( m_flags.m_editingCopy )
01423 {
01424
01425 double xw,yw;
01426 xw = event.GetX();
01427 yw = event.GetY();
01428
01429 if ( event.GetMouseEvent().LeftDown() && ( m_editmode & a2dCURVES_EDIT_ALLOW_ADD ) )
01430 {
01431 if ( event.GetHow().IsEdgeHit() && !PROPID_FirstEventInObject->GetPropertyValue( this ) )
01432 {
01433 a2dAffineMatrix inverse = ic->GetInverseParentTransform();
01434
01435 double xinternal, yinternal;
01436 inverse.TransformPoint(xw, yw, xw, yw);
01437
01438 World2Curve( xw, yw, xinternal, yinternal );
01439
01440
01441 a2dVertexCurve* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dVertexCurve );
01442 double x, y;
01443 size_t i;
01444 int insertpos = -1;
01445 for (i = 0; i < GetPoints()->size(); i++)
01446 {
01447 GetPosXYPoint( i, x, y );
01448 if ( x < xinternal )
01449 insertpos = i;
01450 else
01451 break;
01452 }
01453 insertpos++;
01454
01455 original->AddPoint( xinternal, yinternal, insertpos );
01456 AddPoint( xinternal, yinternal, insertpos );
01457
01458 if ( m_childobjects != wxNullCanvasObjectList )
01459 {
01460 forEachIn( a2dCanvasObjectList, m_childobjects )
01461 {
01462 a2dCanvasObject *obj = *iter;
01463 a2dHandle* handle = wxDynamicCast( obj, a2dHandle );
01464 if ( handle && !handle->GetRelease( ) )
01465 {
01466 wxUint16 index = PROPID_Index->GetPropertyValue( handle );
01467 if ( index >= insertpos )
01468 PROPID_Index->SetPropertyToObject( handle, index + 1 );
01469 }
01470 }
01471 }
01472
01473
01474 a2dHandle* handle = new a2dHandle( this, xw, yw, wxT("__index__") );
01475 handle->SetSpecificFlags( true, a2dCanvasOFlags::EditingCopy );
01476 Append(handle);
01477
01478 handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
01479 PROPID_Index->SetPropertyToObject( handle, insertpos );
01480 ic->SetCorridorPath( true, handle );
01481 }
01482 else
01483 event.Skip();
01484 }
01485 else if ( event.GetMouseEvent().LeftDClick() )
01486 {
01487 EndEdit();
01488 }
01489 else if ( event.GetMouseEvent().Moving() )
01490 {
01491 event.Skip();
01492 }
01493 else
01494 event.Skip();
01495 }
01496 else
01497 event.Skip();
01498 }
01499
01500 void a2dVertexCurve::OnEnterObject(a2dCanvasObjectMouseEvent &event)
01501 {
01502 a2dIterC* ic = event.GetIterC();
01503
01504
01505
01506 ic->GetCanvasView()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS ) );
01507
01508 m_highlightmode = 1;
01509 SetPending( true );
01510 event.Skip();
01511 }
01512
01513 void a2dVertexCurve::OnLeaveObject(a2dCanvasObjectMouseEvent &event)
01514 {
01515
01516
01517 event.Skip();
01518
01519 m_highlightmode = 0;
01520 SetPending( true );
01521 }
01522
01523
01524
01525
01526
01527
01528 a2dSweepPoint::a2dSweepPoint( double sweep, double a, double b )
01529 {
01530 m_sweep = sweep;
01531 m_a = a;
01532 m_b = b;
01533 }
01534
01535 #include <wx/arrimpl.cpp>
01536 WX_DEFINE_OBJARRAY(a2dSweepPointArray);
01537
01538 A2D_BEGIN_EVENT_TABLE(a2dSweepCurve,a2dCurve)
01539 A2D_EVT_CANVASOBJECT_MOUSE_EVENT( a2dSweepCurve::OnCanvasObjectMouseEvent )
01540 A2D_EVT_CANVASOBJECT_ENTER_EVENT( a2dSweepCurve::OnEnterObject )
01541 A2D_EVT_CANVASOBJECT_LEAVE_EVENT( a2dSweepCurve::OnLeaveObject )
01542 A2D_EVT_CANVASHANDLE_MOUSE_EVENT( a2dSweepCurve::OnHandleEvent )
01543 A2D_END_EVENT_TABLE()
01544
01545
01546 a2dSweepCurve::a2dSweepCurve( a2dSweepPointArray* points ): a2dCurve()
01547 {
01548 m_points = points;
01549 m_spline = false;
01550 m_rendermode = a2dCURVES_RENDER_DEFAULT;
01551 m_editmode = a2dCURVES_EDIT_DEFAULT;
01552 }
01553
01554 a2dSweepCurve::a2dSweepCurve( ): a2dCurve()
01555 {
01556 m_points = new a2dSweepPointArray;
01557 m_spline = false;
01558 m_rendermode = a2dCURVES_RENDER_DEFAULT;
01559 m_editmode = a2dCURVES_EDIT_DEFAULT;
01560 }
01561
01562
01563 a2dSweepCurve::~a2dSweepCurve()
01564 {
01565 delete m_points;
01566 }
01567
01568 a2dSweepCurve::a2dSweepCurve( const a2dSweepCurve &other, CloneOptions options )
01569 :a2dCurve( other, options )
01570 {
01571 m_points = new a2dSweepPointArray;
01572 unsigned int i;
01573 for (i=0; i< other.m_points->size(); i++)
01574 m_points->push_back( new a2dSweepPoint( other.m_points->Item(i) ));
01575
01576 m_spline = other.m_spline;
01577
01578 m_rendermode = other.m_rendermode;
01579 m_editmode = other.m_editmode;
01580 }
01581
01582 a2dObject* a2dSweepCurve::Clone( CloneOptions options ) const
01583 {
01584 return new a2dSweepCurve( *this, options );
01585 };
01586
01587 bool a2dSweepCurve::EliminateMatrix()
01588 {
01589 unsigned int i;
01590 if (!m_lworld.IsIdentity())
01591 {
01592 for (i=0; i < m_points->size();i++)
01593 {
01594 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 );
01595 }
01596
01597 }
01598
01599 return a2dCanvasObject::EliminateMatrix();
01600 }
01601
01602 void a2dSweepCurve::SetPosXYPoint(int n, double x, double y )
01603 {
01604 m_points->Item(n).m_a = x;
01605 m_points->Item(n).m_b = y;
01606
01607 SetPending(true);
01608 }
01609
01610 void a2dSweepCurve::RemovePoint( double& x, double& y , int index )
01611 {
01612 if ( index == -1 )
01613 index = m_points->size();
01614
01615 x = m_points->Item( index ).m_a;
01616 y = m_points->Item( index ).m_b;
01617 m_points->RemoveAt( index );
01618 }
01619
01620 void a2dSweepCurve::RemovePointWorld( double& x, double& y , int index, bool transformed )
01621 {
01622 if ( index == -1 )
01623 index = m_points->size();
01624
01625 x = m_points->Item( index ).m_a;
01626 y = m_points->Item( index ).m_b;
01627 m_points->RemoveAt( index );
01628
01629 Curve2World( x, y, x, y );
01630
01631 if ( transformed )
01632 {
01633 m_lworld.TransformPoint( x, y, x, y );
01634 }
01635
01636 }
01637
01638 void a2dSweepCurve::AddPoint( double sweep, const a2dPoint2D& P )
01639 {
01640 AddPoint( sweep, P.m_x, P.m_y );
01641 }
01642
01643 void a2dSweepCurve::AddPoint( double sweep, double x, double y )
01644 {
01645 a2dSweepPoint* point = new a2dSweepPoint( sweep, x, y );
01646
01647 m_points->push_back( point );
01648 SetPending(true);
01649 }
01650
01651 void a2dSweepCurve::GetPosXYPoint(int index, double& x, double& y )
01652 {
01653 if ( index == -1 )
01654 index = m_points->size();
01655
01656 x = m_points->Item( index ).m_a;
01657 y = m_points->Item( index ).m_b;
01658 }
01659
01660 void a2dSweepCurve::GetPosXYPointWorld(int index, double& x, double& y, bool transform )
01661 {
01662 if ( index == -1 )
01663 index = m_points->size();
01664
01665 x = m_points->Item( index ).m_a;
01666 y = m_points->Item( index ).m_b;
01667 Curve2World( x, y, x, y );
01668
01669 if ( transform )
01670 {
01671 m_lworld.TransformPoint( x, y, x, y );
01672 }
01673 }
01674
01675 bool a2dSweepCurve::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
01676 {
01677 if ( m_flags.m_editable )
01678 {
01679 if ( editmode == 1 )
01680 {
01681 m_flags.m_draggable = false;
01682
01683 m_flags.m_visiblechilds = true;
01684 m_flags.m_childrenOnSameLayer = true;
01685
01686
01687 a2dSweepPointArray* array = GetPoints();
01688 size_t i;
01689 for ( i=0; i< array->size(); i++)
01690 {
01691 double xw, yw;
01692 Curve2World( array->Item(i).m_a, array->Item(i).m_b, xw, yw );
01693 a2dHandle* handle = new a2dHandle( this, xw, yw, wxT("__index__") );
01694 handle->SetLayer( m_layer );
01695 Append(handle);
01696 handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
01697 PROPID_Index->SetPropertyToObject( handle, i );
01698
01699
01700 }
01701 m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT("a2dHandle") );
01702
01703
01704
01705 Update( updatemask_force );
01706
01707 SetPending( true );
01708 return true;
01709 }
01710 else
01711 {
01712 PROPID_Allowrotation->SetPropertyToObject( this, true );
01713 PROPID_Allowskew->SetPropertyToObject( this, true );
01714
01715 return a2dCanvasObject::DoStartEdit( editmode, editstyle );
01716 }
01717 }
01718
01719 return false;
01720 }
01721
01722 bool a2dSweepCurve::GetXyAtSweep( double sweepValue, a2dPoint2D& point ) const
01723 {
01724 double xp,yp;
01725 if(!m_points->size())
01726 return false;
01727
01728 xp = m_points->Item(0).m_a;
01729 yp = m_points->Item(0).m_b;
01730 if ( sweepValue <= m_points->Item(0).m_a )
01731 {
01732 point.m_x = m_points->Item(0).m_a;
01733 point.m_y = m_points->Item(0).m_b;
01734 return false;
01735 }
01736
01737 unsigned int i;
01738 for (i=0; i < m_points->size(); i++)
01739 {
01740 if ( xp < sweepValue && m_points->Item(i).m_a >= sweepValue )
01741 {
01742 point.m_x = sweepValue;
01743 point.m_y = (m_points->Item(i).m_b-yp) * (sweepValue-xp)/(m_points->Item(i).m_a-xp) + yp;
01744 return true;
01745 }
01746 xp = m_points->Item(i).m_a;
01747 yp = m_points->Item(i).m_b;
01748 }
01749
01750
01751 point.m_x = m_points->Item(i-1).m_a;
01752 point.m_y = m_points->Item(i-1).m_b;
01753
01754 return false;
01755 }
01756
01757 a2dBoundingBox a2dSweepCurve::DoGetUnTransformedBbox( a2dBboxFlags flags ) const
01758 {
01759 a2dBoundingBox bbox;
01760 unsigned int i;
01761 double xw,yw;
01762 m_curveBox.SetValid(false);
01763 for (i=0; i < m_points->size();i++)
01764 {
01765 m_curveBox.Expand(m_points->Item(i).m_a, m_points->Item(i).m_b);
01766 Curve2World( m_points->Item(i).m_a, m_points->Item(i).m_b, xw, yw );
01767 bbox.Expand( xw, yw );
01768 }
01769 return bbox;
01770 }
01771
01772 bool a2dSweepCurve::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
01773 {
01774 if ( !m_bbox.GetValid() && m_points->size() )
01775 {
01776
01777 if ( m_childobjects != wxNullCanvasObjectList )
01778 m_childobjects->SetSpecificFlags( true, a2dCanvasOFlags::PENDING );
01779
01780 m_bbox = DoGetUnTransformedBbox();
01781 m_bbox.MapBbox(m_lworld);
01782
01783 if (m_clipdata.GetValid())
01784 {
01785 double xw, yw;
01786 Curve2World( m_clipdata.GetMaxX(), m_clipdata.GetMaxY(), xw, yw );
01787 a2dBoundingBox box;
01788 box.Expand( xw, yw );
01789 Curve2World( m_clipdata.GetMinX(), m_clipdata.GetMinY(), xw, yw );
01790 box.Expand( xw, yw );
01791 box.MapBbox(m_lworld);
01792
01793 m_bbox.And(&box);
01794 }
01795
01796 a2dBoundingBox box = m_curvesArea->GetGroup()->GetPlotAreaBbox();
01797 m_bbox.And( &box );
01798 return true;
01799 }
01800 return false;
01801 }
01802
01803 void a2dSweepCurve::DoRender( a2dIterC& ic, OVERLAP WXUNUSED(clipparent) )
01804 {
01805
01806
01807
01808
01809 unsigned int i = 0;
01810 double xw,yw;
01811 if (!(m_rendermode & a2dCURVES_RENDER_NO_POINTS))
01812 {
01813 a2dStroke current = ic.GetDrawer2D()->GetDrawerStroke();
01814 a2dFill fillcurrent = ic.GetDrawer2D()->GetDrawerFill();
01815
01816 a2dStroke highlight = a2dStroke(wxColour(239,2,0),3);
01817
01818 if ( m_highlightmode )
01819 {
01820 ic.GetDrawer2D()->SetDrawerStroke( highlight );
01821 ic.GetDrawer2D()->SetDrawerFill( *a2dBLACK_FILL );
01822 }
01823 else
01824 {
01825 ic.GetDrawer2D()->SetDrawerStroke( *a2dBLACK_STROKE );
01826 ic.GetDrawer2D()->SetDrawerFill( *a2dTRANSPARENT_FILL );
01827 }
01828
01829 for (i=0; i < m_points->size();i++)
01830 {
01831 Curve2World( m_points->Item(i).m_a, m_points->Item(i).m_b, xw, yw );
01832 double xd,yd;
01833 ic.GetTransform().TransformPoint( xw, yw, xd, yd );
01834
01835 int radius = 2;
01836 ic.GetDrawer2D()->PushIdentityTransform();
01837 ic.GetDrawer2D()->DrawCircle( ic.GetDrawer2D()->WorldToDeviceX( xd ), ic.GetDrawer2D()->WorldToDeviceY( yd ), radius );
01838 ic.GetDrawer2D()->PopTransform();
01839 }
01840
01841 ic.GetDrawer2D()->SetDrawerStroke( current );
01842 ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
01843 }
01844
01845 wxRasterOperationMode prevlogfunction = wxNO_OP;
01846 wxDC* aDC = NULL;
01847 if(m_logFunction != wxNO_OP)
01848 {
01849 aDC = ic.GetDrawer2D()->GetRenderDC();
01850 if(aDC)
01851 {
01852 prevlogfunction = aDC->GetLogicalFunction();
01853 aDC->SetLogicalFunction(m_logFunction);
01854 }
01855 }
01856 if (m_rendermode & a2dCURVES_RENDER_NORMAL)
01857 {
01858 double xprev = 0, yprev = 0;
01859 for (i=1; i < m_points->size(); i++)
01860 {
01861 Curve2World( m_points->Item(i).m_a, m_points->Item(i).m_b, xw, yw );
01862 Curve2World( m_points->Item(i-1).m_a, m_points->Item(i-1).m_b, xprev, yprev );
01863 ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
01864 }
01865 }
01866 else if (m_rendermode & a2dCURVES_RENDER_FILL_LINE)
01867 {
01868 double xprev = 0, yprev = 0;
01869 double yw0;
01870 Curve2World( m_points->Item(i).m_a, 0, xw, yw0 );
01871 for (i=1; i < m_points->size(); i++)
01872 {
01873 Curve2World( m_points->Item(i).m_a, m_points->Item(i).m_b, xw, yw );
01874 ic.GetDrawer2D()->DrawLine( xw, yw0, xw, yw );
01875 Curve2World( m_points->Item(i-1).m_a, m_points->Item(i-1).m_b, xprev, yprev );
01876 ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
01877 }
01878 }
01879 else if (m_rendermode & a2dCURVES_RENDER_FILL )
01880 {
01881 a2dVertexArray* cpoints = new a2dVertexArray();
01882
01883 bool first = false;
01884
01885 for (i=0; i < m_points->size(); i++)
01886 {
01887 Curve2World( m_points->Item(i).m_a, m_points->Item(i).m_b, xw, yw );
01888
01889 if ( ! first )
01890 { double xw0,yw0;
01891 Curve2World( m_points->Item(i).m_a, 0, xw0, yw0 );
01892 cpoints->push_back( new a2dLineSegment( xw0, yw0 ) );
01893 }
01894 cpoints->push_back( new a2dLineSegment( xw, yw ) );
01895 first = true;
01896 }
01897 double xw0,yw0;
01898 Curve2World( m_points->Item(i-1).m_a, 0, xw0, yw0 );
01899 cpoints->push_back( new a2dLineSegment( xw0, yw0 ) );
01900
01901 ic.GetDrawer2D()->DrawPolygon( cpoints, false, wxWINDING_RULE);
01902 delete cpoints;
01903
01904 double xprev = 0, yprev = 0;
01905 for (i=1; i < m_points->size(); i++)
01906 {
01907 Curve2World( m_points->Item(i).m_a, m_points->Item(i).m_b, xw, yw );
01908 Curve2World( m_points->Item(i-1).m_a, m_points->Item(i-1).m_b, xprev, yprev );
01909 ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
01910 }
01911 }
01912 if(aDC)
01913 aDC->SetLogicalFunction(prevlogfunction);
01914 }
01915
01916 #if wxART2D_USE_CVGIO
01917 void a2dSweepCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
01918 {
01919 a2dCurve::DoSave( parent, out, xmlparts, towrite );
01920 if ( xmlparts == a2dXmlSer_attrib )
01921 {
01922 if ( m_spline )
01923 {
01924 out.WriteAttribute( wxT("spline") , m_spline );
01925 }
01926 out.WriteAttribute( wxT("points") , m_points->size() );
01927 out.WriteAttribute( wxT("rendermode") , m_rendermode );
01928 out.WriteAttribute( wxT("editmode") , m_editmode );
01929 }
01930 else
01931 {
01932 unsigned int i;
01933 for (i = 0; i < m_points->size(); i++)
01934 {
01935 if (i%6==0)
01936 out.WriteNewLine();
01937 out.WriteStartElementAttributes( wxT("xy") );
01938 out.WriteAttribute( wxT("x") , m_points->Item(i).m_a );
01939 out.WriteAttribute( wxT("y") , m_points->Item(i).m_b );
01940 out.WriteEndAttributes( true );
01941 }
01942 }
01943 }
01944
01945 void a2dSweepCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
01946 {
01947 a2dCurve::DoLoad( parent, parser, xmlparts );
01948 if ( xmlparts == a2dXmlSer_attrib )
01949 {
01950 m_spline = parser.GetAttributeValueBool( wxT("spline"), false );
01951 m_rendermode = parser.GetAttributeValueInt( wxT("rendermode") );
01952 m_editmode = parser.GetAttributeValueInt( wxT("editmode") );
01953 }
01954 else
01955 {
01956 while( parser.GetTagName() == wxT("xy") )
01957 {
01958 double sweep = parser.GetAttributeValueDouble( wxT("sweep") );
01959 double x = parser.GetAttributeValueDouble( wxT("x") );
01960 double y = parser.GetAttributeValueDouble( wxT("y") );
01961 a2dSweepPoint* point = new a2dSweepPoint( sweep, x, y );
01962 m_points->push_back( point );
01963
01964 parser.Next();
01965 parser.Require( END_TAG, wxT("xy") );
01966 parser.Next();
01967 }
01968 }
01969 }
01970 #endif //wxART2D_USE_CVGIO
01971
01972 bool a2dSweepCurve::DoIsHitWorld( a2dIterC& ic, a2dHitEvent& hitEvent )
01973 {
01974 double xcurve, ycurve;
01975 World2Curve( hitEvent.m_relx, hitEvent.m_rely, xcurve, ycurve );
01976
01977 a2dPoint2D P = a2dPoint2D( xcurve, ycurve );
01978 double pw = ic.GetWorldStrokeExtend();
01979 double margin = ic.GetTransformedHitMargin();
01980
01981 if ( PointOnCurve(P, pw+margin) )
01982 {
01983 hitEvent.m_how = a2dHit::stock_strokeoutside;
01984 return true;
01985 }
01986 else
01987 {
01988 hitEvent.m_how = a2dHit::stock_nohit;
01989 return false;
01990 }
01991 }
01992
01993 bool a2dSweepCurve::PointOnCurve(const a2dPoint2D& P, double margin)
01994 {
01995 bool result = false;
01996 double distance;
01997 a2dPoint2D p1,p2;
01998
01999 if(m_points->size())
02000 {
02001 p2=m_points->Item(0).GetPoint();
02002 unsigned int i;
02003 for (i = 0; i < m_points->size()-1; i++)
02004 {
02005 p1=p2;
02006 p2=m_points->Item(i+1).GetPoint();
02007 if (margin > sqrt(pow(p1.m_x-P.m_x,2)+pow(p1.m_y-P.m_y,2)))
02008 {
02009 result=true;
02010 break;
02011 }
02012 else if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
02013 {
02014 a2dLine line1(p1,p2);
02015 if (line1.PointInLine(P,distance,margin) == R_IN_AREA)
02016 {
02017 result=true;
02018 break;
02019 }
02020 }
02021 }
02022 }
02023
02024 return result;
02025 }
02026
02027 void a2dSweepCurve::OnHandleEvent(a2dHandleMouseEvent &event)
02028 {
02029 a2dIterC* ic = event.GetIterC();
02030
02031 if ( m_flags.m_editingCopy )
02032 {
02033 double xw,yw;
02034 xw = event.GetX();
02035 yw = event.GetY();
02036
02037 a2dAffineMatrix atWorld = ic->GetTransform();
02038
02039
02040
02041
02042 a2dAffineMatrix inverselocal = m_lworld;
02043 inverselocal.Invert();
02044
02045 a2dAffineMatrix inverse = ic->GetInverseParentTransform();
02046
02047 double xinternal, yinternal;
02048 inverse.TransformPoint(xw, yw, xinternal, yinternal);
02049
02050 World2Curve( xinternal, yinternal, xinternal, yinternal );
02051
02052 a2dHandle* draghandle = event.GetCanvasHandle();
02053 wxUint16 index = PROPID_Index->GetPropertyValue( draghandle );
02054
02055 wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
02056
02057 if ( editmode == 1 )
02058 {
02059 if (!(m_editmode & a2dCURVES_EDIT_NORMAL))
02060 {
02061 a2dPoint2D p1;
02062 p1 = m_points->Item(index).GetPoint();
02063
02064 if (m_editmode & a2dCURVES_EDIT_FIXED_X)
02065 {
02066 xinternal = p1.m_x;
02067 }
02068 else if (m_editmode & a2dCURVES_EDIT_FIXED_Y)
02069 {
02070 yinternal = p1.m_y;
02071 }
02072 }
02073
02074 a2dSweepCurve* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dSweepCurve );
02075
02076 double xwi;
02077 double ywi;
02078 Curve2World( xinternal, yinternal, xwi, ywi );
02079
02080 if (event.GetMouseEvent().LeftUp() )
02081 {
02082 if ( draghandle->GetName() == wxT("__index__") )
02083 {
02084 m_root->GetCommandProcessor()->Submit(new a2dCommand_SweepCurveMovePoint( original, xinternal, yinternal, index ));
02085 }
02086 else
02087 event.Skip();
02088 }
02089 else if ( event.GetMouseEvent().Dragging() )
02090 {
02091 SetPosXYPoint( index, xinternal, yinternal );
02092 draghandle->SetPosXY( xwi, ywi );
02093 }
02094 else
02095 event.Skip();
02096 }
02097 else
02098 event.Skip();
02099 }
02100 else
02101 {
02102 event.Skip();
02103 }
02104 }
02105
02106 void a2dSweepCurve::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
02107 {
02108 event.Skip();
02109 }
02110
02111 void a2dSweepCurve::OnEnterObject(a2dCanvasObjectMouseEvent &event)
02112 {
02113 a2dIterC* ic = event.GetIterC();
02114
02115 ic->GetCanvasView()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS ) );
02116
02117 m_highlightmode = 1;
02118 SetPending( true );
02119 event.Skip();
02120 }
02121
02122 void a2dSweepCurve::OnLeaveObject(a2dCanvasObjectMouseEvent &event)
02123 {
02124
02125
02126 event.Skip();
02127
02128 m_highlightmode = 0;
02129 SetPending( true );
02130 }
02131
02132
02133
02134
02135
02136 IMPLEMENT_DYNAMIC_CLASS( a2dCanvasBandCurveHandle, a2dHandle )
02137
02138 a2dCanvasBandCurveHandle::a2dCanvasBandCurveHandle()
02139 : a2dHandle( NULL, 0,0, wxT("dummy"), 5, 5)
02140 {
02141 m_index = 0;
02142 m_arcMid = false;
02143 }
02144
02145 a2dCanvasBandCurveHandle::a2dCanvasBandCurveHandle( a2dBandCurve* parent,
02146 unsigned int index, bool arcMid, double xc, double yc, const wxString& name )
02147 : a2dHandle( parent, xc, yc, name )
02148 {
02149 m_index = index;
02150 m_arcMid = arcMid;
02151 }
02152
02153 a2dCanvasBandCurveHandle::a2dCanvasBandCurveHandle( const a2dCanvasBandCurveHandle &other, CloneOptions options )
02154 : a2dHandle( other, options )
02155 {
02156 m_index = other.m_index;
02157 m_arcMid = other.m_arcMid;
02158 }
02159
02160 a2dCanvasBandCurveHandle::~a2dCanvasBandCurveHandle()
02161 {
02162 }
02163
02164
02165
02166
02167
02168 A2D_BEGIN_EVENT_TABLE(a2dBandCurve,a2dCurve)
02169 A2D_EVT_CANVASOBJECT_MOUSE_EVENT( a2dBandCurve::OnCanvasObjectMouseEvent )
02170 A2D_EVT_CANVASOBJECT_ENTER_EVENT( a2dBandCurve::OnEnterObject )
02171 A2D_EVT_CANVASOBJECT_LEAVE_EVENT( a2dBandCurve::OnLeaveObject )
02172 A2D_EVT_CANVASHANDLE_MOUSE_EVENT( a2dBandCurve::OnHandleEvent )
02173 A2D_END_EVENT_TABLE()
02174
02175
02176 a2dBandCurve::a2dBandCurve( a2dSweepPointArray* points ): a2dCurve()
02177 {
02178 m_points = points;
02179 m_spline = false;
02180 m_rendermode = a2dCURVES_RENDER_DEFAULT;
02181 m_editmode = a2dCURVES_EDIT_DEFAULT;
02182 m_markerUpLow = true;
02183 }
02184
02185 a2dBandCurve::a2dBandCurve( ): a2dCurve()
02186 {
02187 m_points = new a2dSweepPointArray;
02188 m_spline = false;
02189 m_rendermode = a2dCURVES_RENDER_DEFAULT;
02190 m_editmode = a2dCURVES_EDIT_DEFAULT;
02191 m_markerUpLow = true;
02192 }
02193
02194
02195 a2dBandCurve::~a2dBandCurve()
02196 {
02197 delete m_points;
02198 }
02199
02200 a2dBandCurve::a2dBandCurve( const a2dBandCurve &other, CloneOptions options )
02201 :a2dCurve( other, options )
02202 {
02203 m_points = new a2dSweepPointArray;
02204 unsigned int i;
02205 for (i=0; i< other.m_points->size(); i++)
02206 m_points->push_back( new a2dSweepPoint( other.m_points->Item(i) ));
02207
02208 m_spline = other.m_spline;
02209
02210 m_rendermode = other.m_rendermode;
02211 m_editmode = other.m_editmode;
02212 m_markerUpLow = other.m_markerUpLow;
02213 }
02214
02215 a2dObject* a2dBandCurve::Clone( CloneOptions options ) const
02216 {
02217 return new a2dBandCurve( *this, options );
02218 };
02219
02220 bool a2dBandCurve::EliminateMatrix()
02221 {
02222 unsigned int i;
02223 if (!m_lworld.IsIdentity())
02224 {
02225 for (i=0; i < m_points->size();i++)
02226 {
02227 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 );
02228 }
02229
02230 }
02231
02232 return a2dCanvasObject::EliminateMatrix();
02233 }
02234
02235 void a2dBandCurve::SetPosXYPoint(int index, double sweep, double y, bool upper )
02236 {
02237 m_points->Item(index).m_sweep = sweep;
02238 if ( upper )
02239 m_points->Item( index ).m_b = y;
02240 else
02241 m_points->Item( index ).m_a = y;
02242
02243 SetPending(true);
02244 }
02245
02246 void a2dBandCurve::RemovePoint( double& sweep, double& y, bool upper, int index )
02247 {
02248 if ( index == -1 )
02249 index = m_points->size();
02250
02251 sweep = m_points->Item( index ).m_sweep;
02252 if ( upper )
02253 y = m_points->Item( index ).m_b;
02254 else
02255 y = m_points->Item( index ).m_a;
02256
02257 m_points->RemoveAt( index );
02258 }
02259
02260 void a2dBandCurve::RemovePointWorld( double& sweep, double& y, bool upper, int index, bool transformed )
02261 {
02262 if ( index == -1 )
02263 index = m_points->size();
02264
02265 sweep = m_points->Item( index ).m_sweep;
02266 if ( upper )
02267 y = m_points->Item( index ).m_b;
02268 else
02269 y = m_points->Item( index ).m_a;
02270
02271 m_points->RemoveAt( index );
02272
02273 Curve2World( sweep, y, sweep, y );
02274
02275 if ( transformed )
02276 {
02277 m_lworld.TransformPoint( sweep, y, sweep, y );
02278 }
02279
02280 }
02281
02282 void a2dBandCurve::AddPoint( double sweep, const a2dPoint2D& P )
02283 {
02284 AddPoint( sweep, P.m_x, P.m_y );
02285 }
02286
02287 void a2dBandCurve::AddPoint( double sweep, double x, double y )
02288 {
02289 a2dSweepPoint* point = new a2dSweepPoint( sweep, x, y );
02290
02291 m_points->push_back( point );
02292 SetPending(true);
02293 }
02294
02295 void a2dBandCurve::GetPosXYPoint(int index, double& sweep, double& y, bool upper )
02296 {
02297 if ( index == -1 )
02298 index = m_points->size();
02299
02300 sweep = m_points->Item( index ).m_sweep;
02301 if ( upper )
02302 y = m_points->Item( index ).m_b;
02303 else
02304 y = m_points->Item( index ).m_a;
02305 }
02306
02307 void a2dBandCurve::GetPosXYPointWorld(int index, double& sweep, double& y, bool transform, bool upper )
02308 {
02309 if ( index == -1 )
02310 index = m_points->size();
02311
02312 sweep = m_points->Item( index ).m_sweep;
02313 if ( upper )
02314 y = m_points->Item( index ).m_b;
02315 else
02316 y = m_points->Item( index ).m_a;
02317 Curve2World( sweep, y, sweep, y );
02318
02319 if ( transform )
02320 {
02321 m_lworld.TransformPoint( sweep, y, sweep, y );
02322 }
02323 }
02324
02325 bool a2dBandCurve::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
02326 {
02327 if ( m_flags.m_editable )
02328 {
02329 if ( editmode == 1 )
02330 {
02331 m_flags.m_draggable = false;
02332
02333 m_flags.m_visiblechilds = true;
02334 m_flags.m_childrenOnSameLayer = true;
02335
02336
02337 a2dSweepPointArray* array = GetPoints();
02338 size_t i;
02339 for ( i=0; i< array->size(); i++)
02340 {
02341 double xw, yw, yw2;
02342 Curve2World( array->Item(i).m_sweep, array->Item(i).m_a, xw, yw );
02343 a2dCanvasBandCurveHandle* handle = new a2dCanvasBandCurveHandle( this, i, false, xw, yw, wxT("__indexlow__") );
02344 handle->SetLayer( m_layer );
02345 Append(handle);
02346 Curve2World( array->Item(i).m_sweep, array->Item(i).m_b, xw, yw2 );
02347 handle = new a2dCanvasBandCurveHandle( this, i, false, xw, yw2, wxT("__indexhigh__") );
02348 Append(handle);
02349 }
02350 m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT("a2dHandle") );
02351
02352
02353
02354 Update( updatemask_force );
02355
02356 SetPending( true );
02357 return true;
02358 }
02359 else
02360 {
02361 PROPID_Allowrotation->SetPropertyToObject( this, true );
02362 PROPID_Allowskew->SetPropertyToObject( this, true );
02363
02364 return a2dCanvasObject::DoStartEdit( editmode, editstyle );
02365 }
02366 }
02367
02368 return false;
02369 }
02370
02371 void a2dBandCurve::SyncHandlesWithLineSegments()
02372 {
02373 for( a2dCanvasObjectList::iterator iter = m_childobjects->begin(); iter != m_childobjects->end(); ++iter )
02374 {
02375 a2dCanvasObject *obj = *iter;
02376
02377 a2dCanvasBandCurveHandle* handle = wxDynamicCast( obj, a2dCanvasBandCurveHandle );
02378
02379 if ( handle && !handle->GetRelease( ) )
02380 {
02381 unsigned int index = handle->GetIndex();
02382 double xw, yw;
02383 if ( handle->GetName() == wxT("__indexlow__") )
02384 {
02385 Curve2World( m_points->Item(index).m_sweep, m_points->Item(index).m_a, xw, yw );
02386 handle->SetPosXY( xw, yw );
02387 }
02388 else if ( handle->GetName() == wxT("__indexhigh__") )
02389 {
02390 Curve2World( m_points->Item(index).m_sweep, m_points->Item(index).m_b, xw, yw );
02391 handle->SetPosXY( xw, yw );
02392 }
02393 }
02394 }
02395 }
02396
02397 void a2dBandCurve::OnHandleEvent(a2dHandleMouseEvent &event)
02398 {
02399 a2dIterC* ic = event.GetIterC();
02400
02401 if ( m_flags.m_editingCopy )
02402 {
02403 double xw,yw;
02404 xw = event.GetX();
02405 yw = event.GetY();
02406
02407 a2dAffineMatrix atWorld = ic->GetTransform();
02408
02409
02410
02411
02412 a2dAffineMatrix inverselocal = m_lworld;
02413 inverselocal.Invert();
02414
02415 a2dAffineMatrix inverse = ic->GetInverseParentTransform();
02416
02417 double xinternal, yinternal;
02418 inverse.TransformPoint(xw, yw, xinternal, yinternal);
02419
02420 World2Curve( xinternal, yinternal, xinternal, yinternal );
02421
02422 a2dCanvasBandCurveHandle* draghandle = wxDynamicCast( event.GetCanvasHandle(), a2dCanvasBandCurveHandle );
02423 wxUint16 index = draghandle->GetIndex();
02424
02425 wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
02426
02427 if ( editmode == 1 )
02428 {
02429 if (!(m_editmode & a2dCURVES_EDIT_NORMAL))
02430 {
02431 if (m_editmode & a2dCURVES_EDIT_FIXED_X)
02432 {
02433 xinternal = m_points->Item(index).m_sweep;
02434 }
02435 else if (m_editmode & a2dCURVES_EDIT_FIXED_Y)
02436 {
02437 if ( draghandle->GetName() == wxT("__indexlow__") )
02438 yinternal = m_points->Item(index).m_a;
02439 else
02440 yinternal = m_points->Item(index).m_b;
02441 }
02442 }
02443
02444 a2dBandCurve* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dBandCurve );
02445
02446 double xwi;
02447 double ywi;
02448 Curve2World( xinternal, yinternal, xwi, ywi );
02449
02450 if (event.GetMouseEvent().LeftUp() )
02451 {
02452 if ( draghandle->GetName() == wxT("__indexlow__") )
02453 {
02454 m_root->GetCommandProcessor()->Submit(new a2dCommand_BandCurveMovePoint( original, xinternal, yinternal, false, index ));
02455 SyncHandlesWithLineSegments();
02456 }
02457 else if ( draghandle->GetName() == wxT("__indexhigh__") )
02458 {
02459 m_root->GetCommandProcessor()->Submit(new a2dCommand_BandCurveMovePoint( original, xinternal, yinternal, true, index ));
02460 SyncHandlesWithLineSegments();
02461 }
02462 else
02463 event.Skip();
02464 }
02465 else if ( event.GetMouseEvent().Dragging() )
02466 {
02467 if ( draghandle->GetName() == wxT("__indexlow__") )
02468 {
02469 SetPosXYPoint( index, xinternal, yinternal, false );
02470 }
02471 else if ( draghandle->GetName() == wxT("__indexhigh__") )
02472 {
02473 SetPosXYPoint( index, xinternal, yinternal, true );
02474 }
02475 draghandle->SetPosXY( xwi, ywi );
02476 }
02477 else
02478 event.Skip();
02479 }
02480 else
02481 event.Skip();
02482 }
02483 else
02484 {
02485 event.Skip();
02486 }
02487 }
02488
02489 bool a2dBandCurve::GetXyAtSweep( double sweepValue, a2dPoint2D& point ) const
02490 {
02491 double xp,yp;
02492 if(!m_points->size())
02493 return false;
02494
02495
02496 xp = m_points->Item(0).m_sweep;
02497 if ( m_markerUpLow )
02498 yp = m_points->Item(0).m_b;
02499 else
02500 yp = m_points->Item(0).m_b;
02501 if ( sweepValue <= m_points->Item(0).m_sweep )
02502 {
02503 point.m_x = m_points->Item(0).m_sweep;
02504 if ( m_markerUpLow )
02505 point.m_y = m_points->Item(0).m_b;
02506 else
02507 point.m_y = m_points->Item(0).m_a;
02508 return false;
02509 }
02510
02511 unsigned int i;
02512 for (i=0; i < m_points->size(); i++)
02513 {
02514 if ( xp < sweepValue && m_points->Item(i).m_sweep >= sweepValue )
02515 {
02516 point.m_x = sweepValue;
02517 if ( m_markerUpLow )
02518 point.m_y = (m_points->Item(i).m_b-yp) * (sweepValue-xp)/(m_points->Item(i).m_sweep-xp) + yp;
02519 else
02520 point.m_y = (m_points->Item(i).m_a-yp) * (sweepValue-xp)/(m_points->Item(i).m_sweep-xp) + yp;
02521
02522 return true;
02523 }
02524 xp = m_points->Item(i).m_sweep;
02525 if ( m_markerUpLow )
02526 yp = m_points->Item(i).m_b;
02527 else
02528 yp = m_points->Item(i).m_a;
02529 }
02530
02531
02532 point.m_x = m_points->Item(i-1).m_sweep;
02533 if ( m_markerUpLow )
02534 point.m_y = m_points->Item(i-1).m_b;
02535 else
02536 point.m_y = m_points->Item(i-1).m_a;
02537 return false;
02538 }
02539
02540 a2dBoundingBox a2dBandCurve::DoGetUnTransformedBbox( a2dBboxFlags flags ) const
02541 {
02542 a2dBoundingBox bbox;
02543 unsigned int i;
02544 double xw,yw;
02545 m_curveBox.SetValid(false);
02546 for (i=0; i < m_points->size();i++)
02547 {
02548 m_curveBox.Expand(m_points->Item(i).m_sweep, m_points->Item(i).m_a);
02549 Curve2World( m_points->Item(i).m_sweep, m_points->Item(i).m_a, xw, yw );
02550 bbox.Expand( xw, yw );
02551 m_curveBox.Expand(m_points->Item(i).m_sweep, m_points->Item(i).m_b);
02552 Curve2World( m_points->Item(i).m_sweep, m_points->Item(i).m_b, xw, yw );
02553 bbox.Expand( xw, yw );
02554 }
02555 return bbox;
02556 }
02557
02558 bool a2dBandCurve::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
02559 {
02560 if ( !m_bbox.GetValid() && m_points->size() )
02561 {
02562
02563 if ( m_childobjects != wxNullCanvasObjectList )
02564 m_childobjects->SetSpecificFlags( true, a2dCanvasOFlags::PENDING );
02565
02566 m_bbox = DoGetUnTransformedBbox();
02567 m_bbox.MapBbox(m_lworld);
02568
02569 if (m_clipdata.GetValid())
02570 {
02571 double xw, yw;
02572 Curve2World( m_clipdata.GetMaxX(), m_clipdata.GetMaxY(), xw, yw );
02573 a2dBoundingBox box;
02574 box.Expand( xw, yw );
02575 Curve2World( m_clipdata.GetMinX(), m_clipdata.GetMinY(), xw, yw );
02576 box.Expand( xw, yw );
02577 box.MapBbox(m_lworld);
02578
02579 m_bbox.And(&box);
02580 }
02581
02582 a2dBoundingBox box = m_curvesArea->GetGroup()->GetPlotAreaBbox();
02583 m_bbox.And( &box );
02584 return true;
02585 }
02586 return false;
02587 }
02588
02589 void a2dBandCurve::DoRender( a2dIterC& ic, OVERLAP WXUNUSED(clipparent) )
02590 {
02591
02592
02593 a2dBoundingBox curvebox = GetClippedCurveBoundaries();
02594 if(!curvebox.GetValid())
02595 return ;
02596
02597 unsigned int i;
02598 double xw,yw,yw2;
02599 if (!(m_rendermode & a2dCURVES_RENDER_NO_POINTS))
02600 {
02601 a2dStroke current = ic.GetDrawer2D()->GetDrawerStroke();
02602 a2dFill fillcurrent = ic.GetDrawer2D()->GetDrawerFill();
02603
02604 a2dStroke highlight = a2dStroke(wxColour(239,2,0),3);
02605
02606 if ( m_highlightmode )
02607 {
02608 ic.GetDrawer2D()->SetDrawerStroke( highlight );
02609 ic.GetDrawer2D()->SetDrawerFill( *a2dBLACK_FILL );
02610 }
02611 else
02612 {
02613 ic.GetDrawer2D()->SetDrawerStroke( *a2dBLACK_STROKE );
02614 ic.GetDrawer2D()->SetDrawerFill( *a2dTRANSPARENT_FILL );
02615 }
02616
02617 int radius = 2;
02618 for (i=0; i < m_points->size();i++)
02619 {
02620 if ( m_points->Item(i).m_sweep >= curvebox.GetMinX() )
02621 {
02622 Curve2World( m_points->Item(i).m_sweep, m_points->Item(i).m_a, xw, yw );
02623 Curve2World( m_points->Item(i).m_sweep, m_points->Item(i).m_b, xw, yw2 );
02624 double xd,yd,xd2,yd2;
02625
02626 ic.GetTransform().TransformPoint( xw, yw, xd, yd );
02627 ic.GetTransform().TransformPoint( xw, yw2, xd2, yd2 );
02628 xd = ic.GetDrawer2D()->WorldToDeviceX( xd );
02629 yd = ic.GetDrawer2D()->WorldToDeviceY( yd );
02630 xd2 = ic.GetDrawer2D()->WorldToDeviceX( xd2 );
02631 yd2 = ic.GetDrawer2D()->WorldToDeviceY( yd2 );
02632 ic.GetDrawer2D()->PushIdentityTransform();
02633 ic.GetDrawer2D()->DrawCircle( xd, yd, radius );
02634 ic.GetDrawer2D()->DrawCircle( xd2, yd2, radius );
02635 ic.GetDrawer2D()->PopTransform();
02636 }
02637 if ( m_points->Item(i).m_sweep > curvebox.GetMaxX() )
02638 break;
02639 }
02640
02641 ic.GetDrawer2D()->SetDrawerStroke( current );
02642 ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
02643 }
02644
02645 wxRasterOperationMode prevlogfunction = wxNO_OP;
02646 wxDC* aDC = NULL;
02647 if(m_logFunction != wxNO_OP)
02648 {
02649 aDC = ic.GetDrawer2D()->GetRenderDC();
02650 prevlogfunction = aDC->GetLogicalFunction();
02651 aDC->SetLogicalFunction(m_logFunction);
02652 }
02653 if (m_rendermode & a2dCURVES_RENDER_NORMAL)
02654 {
02655 bool second = false;
02656 double xprev = 0, yprev = 0;
02657 for (i=0; i < m_points->size(); i++)
02658 {
02659 if (second && m_points->Item(i).m_sweep >= curvebox.GetMinX() )
02660 {
02661 Curve2World( m_points->Item(i).m_sweep, m_points->Item(i).m_a, xw, yw );
02662 Curve2World( m_points->Item(i-1).m_sweep, m_points->Item(i-1).m_a, xprev, yprev );
02663 ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
02664 Curve2World( m_points->Item(i).m_sweep, m_points->Item(i).m_b, xw, yw2 );
02665 Curve2World( m_points->Item(i-1).m_sweep, m_points->Item(i-1).m_b, xprev, yprev );
02666 ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw2 );
02667 }
02668 if ( m_points->Item(i).m_sweep > curvebox.GetMaxX() )
02669 break;
02670 second = true;
02671 }
02672 }
02673 else if (m_rendermode & a2dCURVES_RENDER_FILL_LINE)
02674 {
02675 bool second = false;
02676 double xprev = 0, yprev = 0;
02677 for (i=0; i < m_points->size(); i++)
02678 {
02679 if (second && m_points->Item(i).m_sweep >= curvebox.GetMinX() )
02680 {
02681 Curve2World( m_points->Item(i).m_sweep, m_points->Item(i).m_a, xw, yw );
02682 Curve2World( m_points->Item(i-1).m_sweep, m_points->Item(i-1).m_a, xprev, yprev );
02683 Curve2World( m_points->Item(i).m_sweep, m_points->Item(i).m_b, xw, yw2 );
02684 ic.GetDrawer2D()->DrawLine( xw, yw, xw, yw2 );
02685 ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
02686 Curve2World( m_points->Item(i-1).m_sweep, m_points->Item(i-1).m_b, xprev, yprev );
02687 ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw2 );
02688
02689 }
02690 if ( m_points->Item(i).m_sweep > curvebox.GetMaxX() )
02691 break;
02692 second = true;
02693 }
02694 }
02695 else if (m_rendermode & a2dCURVES_RENDER_FILL )
02696 {
02697 a2dVertexArray* cpoints = new a2dVertexArray();
02698 for (i=0; i < m_points->size(); i++)
02699 {
02700 Curve2World( m_points->Item(i).m_sweep, m_points->Item(i).m_a, xw, yw );
02701 Curve2World( m_points->Item(i).m_sweep, m_points->Item(i).m_b, xw, yw2 );
02702
02703 cpoints->Insert( new a2dLineSegment( xw, yw ), 0 );
02704
02705 cpoints->push_back( new a2dLineSegment( xw, yw2 ) );
02706 }
02707
02708 ic.GetDrawer2D()->DrawPolygon( cpoints, false, wxWINDING_RULE);
02709 delete cpoints;
02710 }
02711 if(aDC)
02712 aDC->SetLogicalFunction(prevlogfunction);
02713 }
02714
02715 #if wxART2D_USE_CVGIO
02716 void a2dBandCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
02717 {
02718 a2dCurve::DoSave( parent, out, xmlparts, towrite );
02719 if ( xmlparts == a2dXmlSer_attrib )
02720 {
02721 if ( m_spline )
02722 {
02723 out.WriteAttribute( wxT("spline") , m_spline );
02724 }
02725 out.WriteAttribute( wxT("points") , m_points->size() );
02726 out.WriteAttribute( wxT("rendermode") , m_rendermode );
02727 out.WriteAttribute( wxT("editmode") , m_editmode );
02728 }
02729 else
02730 {
02731 unsigned int i;
02732 for (i = 0; i < m_points->size(); i++)
02733 {
02734 if (i%6==0)
02735 out.WriteNewLine();
02736 out.WriteStartElementAttributes( wxT("ab") );
02737 out.WriteAttribute( wxT("sweep") , m_points->Item(i).m_sweep );
02738 out.WriteAttribute( wxT("a") , m_points->Item(i).m_a );
02739 out.WriteAttribute( wxT("b") , m_points->Item(i).m_b );
02740 out.WriteEndAttributes( true );
02741 }
02742 }
02743 }
02744
02745 void a2dBandCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
02746 {
02747 a2dCurve::DoLoad( parent, parser, xmlparts );
02748 if ( xmlparts == a2dXmlSer_attrib )
02749 {
02750 m_spline = parser.GetAttributeValueBool( wxT("spline"), false );
02751 m_rendermode = parser.GetAttributeValueInt( wxT("rendermode") );
02752 m_editmode = parser.GetAttributeValueInt( wxT("editmode") );
02753 }
02754 else
02755 {
02756 while( parser.GetTagName() == wxT("ab") )
02757 {
02758 double sweep = parser.GetAttributeValueDouble( wxT("sweep") );
02759 double x = parser.GetAttributeValueDouble( wxT("a") );
02760 double y = parser.GetAttributeValueDouble( wxT("b") );
02761 a2dSweepPoint* point = new a2dSweepPoint( sweep, x, y );
02762 m_points->push_back( point );
02763
02764 parser.Next();
02765 parser.Require( END_TAG, wxT("ab") );
02766 parser.Next();
02767 }
02768 }
02769 }
02770 #endif //wxART2D_USE_CVGIO
02771
02772 bool a2dBandCurve::DoIsHitWorld( a2dIterC& ic, a2dHitEvent& hitEvent )
02773 {
02774 double xh,yh;
02775 ic.GetInverseTransform().TransformPoint(hitEvent.m_x,hitEvent.m_y,xh,yh);
02776
02777 double xcurve, ycurve;
02778 World2Curve( xh, yh, xcurve, ycurve );
02779
02780 a2dPoint2D P = a2dPoint2D( xcurve, ycurve );
02781 double pw = ic.GetWorldStrokeExtend();
02782 double margin = ic.GetTransformedHitMargin();
02783
02784 if ( PointOnCurve(P, pw+margin) )
02785 {
02786 hitEvent.m_how = a2dHit::stock_strokeoutside;
02787 return true;
02788 }
02789 else
02790 {
02791 hitEvent.m_how = a2dHit::stock_nohit;
02792 return false;
02793 }
02794 }
02795
02796 bool a2dBandCurve::PointOnCurve(const a2dPoint2D& P, double margin)
02797 {
02798 bool result = false;
02799 double distance;
02800 a2dPoint2D pup1,pup2,plow1,plow2;
02801
02802 if(m_points->size())
02803 {
02804 pup2 = m_points->Item(0).GetPoint();
02805 unsigned int i;
02806 for (i = 0; i < m_points->size()-1; i++)
02807 {
02808 R_PointStatus up = R_RIGHT_SIDE;
02809 R_PointStatus low = R_RIGHT_SIDE;
02810
02811 pup1 = pup2;
02812 pup2 = m_points->Item(i+1).GetPointUp();
02813 if (margin > sqrt(pow(pup1.m_x-P.m_x,2) + pow(pup1.m_y-P.m_y,2)))
02814 {
02815 result=true;
02816 break;
02817 }
02818 else if (!((pup1.m_x == pup2.m_x) && (pup1.m_y == pup2.m_y)))
02819 {
02820 a2dLine line1(pup1,pup2);
02821 if ( (up = line1.PointInLine(P,distance,margin)) == R_IN_AREA)
02822 {
02823 result=true;
02824 break;
02825 }
02826 }
02827 plow1 = plow2;
02828 plow2 = m_points->Item(i+1).GetPointLow();
02829 if (margin > sqrt(pow(plow1.m_x-P.m_x,2) + pow(plow1.m_y-P.m_y,2)))
02830 {
02831 result=true;
02832 break;
02833 }
02834 else if (!((plow1.m_x == plow2.m_x) && (plow1.m_y == plow2.m_y)))
02835 {
02836 a2dLine line1(pup1,pup2);
02837 if ( (low = line1.PointInLine(P,distance,margin)) == R_IN_AREA)
02838 {
02839 result=true;
02840 break;
02841 }
02842 }
02843
02844 if ( pup1.m_x > plow1.m_x && up == R_RIGHT_SIDE && low == R_LEFT_SIDE )
02845 {
02846 result=true;
02847 break;
02848 }
02849 if ( pup1.m_x < plow1.m_x && low == R_RIGHT_SIDE && up == R_LEFT_SIDE )
02850 {
02851 result=true;
02852 break;
02853 }
02854
02855 }
02856 }
02857
02858 return result;
02859 }
02860
02861 void a2dBandCurve::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
02862 {
02863 event.Skip();
02864 }
02865
02866 void a2dBandCurve::OnEnterObject(a2dCanvasObjectMouseEvent &event)
02867 {
02868 a2dIterC* ic = event.GetIterC();
02869
02870 ic->GetCanvasView()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS ) );
02871
02872 m_highlightmode = 1;
02873 SetPending( true );
02874 event.Skip();
02875 }
02876
02877 void a2dBandCurve::OnLeaveObject(a2dCanvasObjectMouseEvent &event)
02878 {
02879
02880
02881 event.Skip();
02882
02883 m_highlightmode = 0;
02884 SetPending( true );
02885 }
02886
02887
02888
02889
02890
02891
02892 const a2dPropertyIdRefObject a2dBarCurve::PROPID_extrudeFill( wxT("extrudeFill"), a2dPropertyId::flag_none, 0 );
02893
02894 void a2dBarCurve::DoWalker( wxObject* parent, a2dWalkerIOHandler& handler )
02895 {
02896 handler.WalkTask( parent, this, a2dWalker_a2dDerivedCanvasObjectStart );
02897 a2dCanvasObject::DoWalker( parent, handler );
02898
02899 handler.WalkTask( parent, this, a2dWalker_a2dDerivedCanvasObjectEnd );
02900 }
02901
02902 a2dBarCurve::a2dBarCurve( a2dVertexArray* points ): a2dVertexCurve( points )
02903 {
02904 m_barwidth = 0;
02905 m_depth = m_barwidth/2;
02906 m_angle3d = wxDegToRad(30);
02907 m_extrudeFill = *a2dBLACK_FILL;
02908 m_rendermode = a2dBAR_RENDER_NORMAL;
02909 }
02910
02911 a2dBarCurve::a2dBarCurve( ): a2dVertexCurve()
02912 {
02913 m_barwidth = 0;
02914 m_depth = m_barwidth/2;
02915 m_angle3d = wxDegToRad(30);
02916 m_extrudeFill = *a2dBLACK_FILL;
02917 m_rendermode = a2dBAR_RENDER_NORMAL;
02918 }
02919
02920
02921 a2dBarCurve::~a2dBarCurve()
02922 {
02923 }
02924
02925 a2dBarCurve::a2dBarCurve( const a2dBarCurve &other, CloneOptions options )
02926 :a2dVertexCurve( other, options )
02927 {
02928 m_barwidth = other.m_barwidth;
02929 m_depth = other.m_depth;
02930 m_angle3d = other.m_angle3d;
02931
02932 m_extrudeFill = other.m_extrudeFill;
02933
02934 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
02935
02936 CurrentSmartPointerOwner = this;
02937 #endif
02938 }
02939
02940 a2dObject* a2dBarCurve::Clone( CloneOptions options ) const
02941 {
02942 return new a2dBarCurve( *this, options );
02943 };
02944
02945 void a2dBarCurve::SetExtrudeFill( const a2dFill& fill )
02946 {
02947 m_extrudeFill = fill;
02948 }
02949
02950 void a2dBarCurve::DoRender( a2dIterC& ic, OVERLAP WXUNUSED(clipparent) )
02951 {
02952 double xw, yw;
02953 a2dStroke current = ic.GetDrawer2D()->GetDrawerStroke();
02954 a2dFill fillcurrent = ic.GetDrawer2D()->GetDrawerFill();
02955 if ( m_highlightmode )
02956 {
02957 a2dStroke tmps = a2dStroke(wxColour(239,232,0),3);
02958 ic.GetDrawer2D()->SetDrawerStroke( tmps );
02959 ic.GetDrawer2D()->SetDrawerFill( *a2dBLACK_FILL );
02960 }
02961 else
02962 {
02963 ic.GetDrawer2D()->SetDrawerStroke( *a2dBLACK_STROKE );
02964 ic.GetDrawer2D()->SetDrawerFill( *a2dTRANSPARENT_FILL );
02965 }
02966
02967 if (!(m_rendermode & a2dCURVES_RENDER_NO_POINTS))
02968 {
02969 unsigned int i;
02970 for (i=0; i < m_points->size();i++)
02971 {
02972 Curve2World( m_points->Item(i)->m_x, m_points->Item(i)->m_y, xw, yw );
02973
02974 double xd,yd;
02975 ic.GetTransform().TransformPoint( xw, yw, xd, yd );
02976 xd = ic.GetDrawer2D()->WorldToDeviceX( xd );
02977 yd = ic.GetDrawer2D()->WorldToDeviceY( yd );
02978
02979 int radius = 2;
02980 ic.GetDrawer2D()->PushIdentityTransform();
02981 ic.GetDrawer2D()->DrawCircle( xd, yd, radius );
02982 ic.GetDrawer2D()->PopTransform();
02983 }
02984 }
02985
02986 ic.GetDrawer2D()->SetDrawerStroke( current );
02987 ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
02988
02989 wxRasterOperationMode prevlogfunction = wxNO_OP;
02990 wxDC* aDC = NULL;
02991 if(m_logFunction != wxNO_OP)
02992 {
02993 aDC = ic.GetDrawer2D()->GetRenderDC();
02994 prevlogfunction = aDC->GetLogicalFunction();
02995 aDC->SetLogicalFunction(m_logFunction);
02996 }
02997
02998 double yw0;
02999 Curve2World( m_points->Item(0)->m_x, 0, xw, yw0 );
03000 switch ( m_rendermode )
03001 {
03002 default:
03003 case a2dBAR_RENDER_NORMAL:
03004 {
03005 double w2 = m_barwidth/2;
03006 unsigned int i;
03007 a2dlist< a2dFill >::iterator iter = m_pointsFill.begin();
03008 for (i=0; i < m_points->size(); i++)
03009 {
03010 if ( m_pointsFill.size() )
03011 ic.GetDrawer2D()->SetDrawerFill( *iter );
03012
03013 Curve2World( m_points->Item(i)->m_x, m_points->Item(i)->m_y, xw, yw );
03014 ic.GetDrawer2D()->DrawRoundedRectangle( xw-w2, yw0, m_barwidth, yw - yw0, 0 );
03015
03016 iter = m_pointsFill.GetNextAround( iter );
03017 }
03018 break;
03019 }
03020 case a2dBAR_RENDER_3D:
03021 {
03022 a2dVertexArray* cpoints = new a2dVertexArray;
03023 double w2 = m_barwidth/2;
03024
03025 a2dlist< a2dFill >::iterator iter = m_pointsFill.begin();
03026 unsigned int i;
03027 for (i=0; i < m_points->size(); i++)
03028 {
03029 Curve2World( m_points->Item(i)->m_x, m_points->Item(i)->m_y, xw, yw );
03030 double barx = xw;
03031 double barlow = yw0;
03032 double barheight = yw;
03033
03034 if ( barheight < 0 )
03035 {
03036 barlow = yw;
03037 barheight = 0;
03038 }
03039
03040 ic.GetDrawer2D()->SetDrawerFill( m_extrudeFill );
03041
03042
03043 cpoints->clear();
03044 cpoints->push_back( new a2dLineSegment( barx - w2, barheight) );
03045 cpoints->push_back( new a2dLineSegment( barx - w2 + cos(m_angle3d-wxPI/30)*m_depth, barheight + sin(m_angle3d-wxPI/30)*m_depth));
03046 cpoints->push_back( new a2dLineSegment( barx + w2 + cos(m_angle3d)*m_depth, barheight + sin(m_angle3d-wxPI/30)*m_depth));
03047 cpoints->push_back( new a2dLineSegment( barx + w2, barheight));
03048 ic.GetDrawer2D()->DrawPolygon( cpoints, false, wxWINDING_RULE);
03049
03050
03051 cpoints->clear();
03052 cpoints->push_back( new a2dLineSegment( barx + w2, barheight));
03053 cpoints->push_back( new a2dLineSegment( barx + w2 + cos(m_angle3d)*m_depth, barheight + sin(m_angle3d-wxPI/30)*m_depth));
03054 cpoints->push_back( new a2dLineSegment( barx + w2 + cos(m_angle3d)*m_depth, barlow + sin(m_angle3d)*m_depth));
03055 cpoints->push_back( new a2dLineSegment( barx + w2, barlow));
03056
03057 ic.GetDrawer2D()->DrawPolygon( cpoints, false, wxWINDING_RULE);
03058
03059 if ( m_pointsFill.size() )
03060 ic.GetDrawer2D()->SetDrawerFill( *iter );
03061 else
03062 ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
03063
03064 ic.GetDrawer2D()->DrawRoundedRectangle( xw-w2, yw0, m_barwidth, yw - yw0, 0 );
03065
03066 iter = m_pointsFill.GetNextAround( iter );
03067 }
03068 delete cpoints;
03069 break;
03070 }
03071 case a2dBAR_RENDER_LINE:
03072 {
03073 unsigned int i;
03074 for (i=0; i < m_points->size(); i++)
03075 {
03076 Curve2World( m_points->Item(i)->m_x, m_points->Item(i)->m_y, xw, yw );
03077 ic.GetDrawer2D()->DrawLine( xw, yw0, xw, yw );
03078 }
03079 break;
03080 }
03081 }
03082 if(aDC)
03083 aDC->SetLogicalFunction(prevlogfunction);
03084
03085 ic.GetDrawer2D()->SetDrawerStroke( current );
03086 ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
03087 }
03088
03089 #if wxART2D_USE_CVGIO
03090 void a2dBarCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
03091 {
03092 a2dVertexCurve::DoSave( parent, out, xmlparts, towrite );
03093 if ( xmlparts == a2dXmlSer_attrib )
03094 {
03095 out.WriteAttribute( wxT("barwidth") , m_barwidth );
03096 out.WriteAttribute( wxT("depth") , m_depth );
03097 out.WriteAttribute( wxT("angle3d") , m_angle3d );
03098 }
03099 else
03100 {
03101 out.WriteStartElement( wxT("derived") );
03102 m_extrudeFill.Save( this, out, towrite );
03103 out.WriteEndElement();
03104 }
03105 }
03106
03107 void a2dBarCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
03108 {
03109 a2dVertexCurve::DoLoad( parent, parser, xmlparts );
03110 if ( xmlparts == a2dXmlSer_attrib )
03111 {
03112 m_barwidth = parser.RequireAttributeValueDouble( wxT("barwidth") );
03113 m_depth = parser.RequireAttributeValueDouble( wxT("depth") );
03114 m_angle3d = parser.RequireAttributeValueDouble( wxT("angle3d") );
03115 }
03116 else
03117 {
03118 parser.Require( START_TAG, wxT("derived") );
03119 parser.Next();
03120 m_extrudeFill.Load( parent, parser );
03121 parser.Require( END_TAG, wxT("derived") );
03122 parser.Next();
03123 }
03124 }
03125 #endif //wxART2D_USE_CVGIO
03126
03127
03128
03129
03130
03131
03132 A2D_BEGIN_EVENT_TABLE(a2dVertexListCurve,a2dCurve)
03133 A2D_EVT_CANVASOBJECT_MOUSE_EVENT( a2dVertexListCurve::OnCanvasObjectMouseEvent )
03134 A2D_EVT_CANVASOBJECT_ENTER_EVENT( a2dVertexListCurve::OnEnterObject )
03135 A2D_EVT_CANVASOBJECT_LEAVE_EVENT( a2dVertexListCurve::OnLeaveObject )
03136 A2D_EVT_CANVASHANDLE_MOUSE_EVENT( a2dVertexListCurve::OnHandleEvent )
03137 A2D_END_EVENT_TABLE()
03138
03139
03140 a2dVertexListCurve::a2dVertexListCurve( a2dVertexList* points ): a2dCurve()
03141 {
03142 m_lpoints = points;
03143 m_spline = false;
03144 m_rendermode = a2dCURVES_RENDER_DEFAULT;
03145 m_editmode = a2dCURVES_EDIT_DEFAULT;
03146 }
03147
03148 a2dVertexListCurve::a2dVertexListCurve( ): a2dCurve()
03149 {
03150 m_lpoints = new a2dVertexList();
03151 m_spline=false;
03152 m_rendermode = a2dCURVES_RENDER_DEFAULT;
03153 m_editmode = a2dCURVES_EDIT_DEFAULT;
03154 }
03155
03156
03157 a2dVertexListCurve::~a2dVertexListCurve()
03158 {
03159 delete m_lpoints;
03160 }
03161
03162 a2dVertexListCurve::a2dVertexListCurve( const a2dVertexListCurve &other, CloneOptions options )
03163 :a2dCurve( other, options )
03164 {
03165 m_lpoints = new a2dVertexList();
03166 *m_lpoints = *other.m_lpoints;
03167
03168 m_spline = other.m_spline;
03169 m_rendermode = other.m_rendermode;
03170 m_editmode = other.m_editmode;
03171 }
03172
03173 a2dObject* a2dVertexListCurve::Clone( CloneOptions options ) const
03174 {
03175 return new a2dVertexListCurve( *this, options );
03176 };
03177
03178 bool a2dVertexListCurve::EliminateMatrix()
03179 {
03180 if (!m_lworld.IsIdentity())
03181 {
03182 for( a2dVertexList::iterator iter = m_lpoints->begin(); iter != m_lpoints->end(); ++iter )
03183 {
03184 a2dLineSegment* point = (*iter);
03185 m_lworld.TransformPoint(point->m_x,point->m_y, point->m_x,point->m_y );
03186 }
03187
03188 }
03189 return a2dCanvasObject::EliminateMatrix();
03190 }
03191
03192 void a2dVertexListCurve::SetPosXYPoint(int n, double x, double y, bool afterinversion )
03193 {
03194 if ( afterinversion )
03195 {
03196 a2dAffineMatrix inverse = m_lworld;
03197 inverse.Invert();
03198 inverse.TransformPoint( x, y, x, y );
03199 }
03200
03201 int i=0;
03202 for( a2dVertexList::iterator iter = m_lpoints->begin(); iter != m_lpoints->end(); ++iter )
03203 {
03204 if (i==n)
03205 {
03206 a2dLineSegment* point = (*iter);
03207 point->m_x = x;
03208 point->m_y = y;
03209 break;
03210 }
03211 i++;
03212 }
03213 SetPending(true);
03214 }
03215
03216 void a2dVertexListCurve::AddPoint( const a2dPoint2D& P, int index, bool afterinversion )
03217 {
03218 AddPoint( P.m_x, P.m_y, index, afterinversion );
03219 }
03220
03221 void a2dVertexListCurve::AddPoint( double x, double y, int index, bool afterinversion )
03222 {
03223 if ( afterinversion )
03224 {
03225 a2dAffineMatrix inverse = m_lworld;
03226 inverse.Invert();
03227 inverse.TransformPoint( x, y, x, y );
03228 }
03229
03230 a2dLineSegment* point = new a2dLineSegment( x, y );
03231
03232 if ( index == -1 )
03233 m_lpoints->push_back(point);
03234 else
03235 {
03236 a2dVertexList::iterator iter = m_lpoints->begin();
03237 int i = 0;
03238 while ( i < index ) { ++iter; i++; }
03239 m_lpoints->insert( iter, point );
03240 }
03241 SetPending(true);
03242 }
03243
03244 void a2dVertexListCurve::RemovePoint( double& x, double& y , int index, bool transformed )
03245 {
03246 if ( index == -1 )
03247 {
03248 a2dLineSegment* point;
03249 point = m_lpoints->back();
03250 x = point->m_x;
03251 y = point->m_y;
03252 m_lpoints->pop_back();
03253 }
03254 else
03255 {
03256 int i = 0;
03257 a2dVertexList::iterator iter = m_lpoints->begin();
03258 a2dLineSegment* point;
03259 while ( iter != m_lpoints->end() )
03260 {
03261 if ( i == index )
03262 {
03263 point = (*iter);
03264 x = point->m_x;
03265 y = point->m_y;
03266 m_lpoints->erase( iter );
03267 break;
03268 }
03269 i++;
03270 iter++;
03271 }
03272 }
03273
03274 if ( transformed )
03275 {
03276 m_lworld.TransformPoint( x, y, x, y );
03277 }
03278
03279 SetPending(true);
03280 }
03281
03282 void a2dVertexListCurve::GetPosXYPoint(int index, double& x, double& y, bool transform )
03283 {
03284 if ( index == -1 )
03285 {
03286 a2dLineSegment* point;
03287 point = m_lpoints->back();
03288 x = point->m_x;
03289 y = point->m_y;
03290 }
03291 else
03292 {
03293 int i = 0;
03294 a2dVertexList::iterator iter = m_lpoints->begin();
03295 a2dLineSegment* point;
03296 while ( iter != m_lpoints->end() )
03297 {
03298 if ( i == index )
03299 {
03300 point = (*iter);
03301 x = point->m_x;
03302 y = point->m_y;
03303 break;
03304 }
03305 i++;
03306 iter++;
03307 }
03308 }
03309
03310 if ( transform )
03311 {
03312 m_lworld.TransformPoint( x, y, x, y );
03313 }
03314 }
03315
03316 bool a2dVertexListCurve::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
03317 {
03318 if ( m_flags.m_editable )
03319 {
03320 if ( editmode == 1 )
03321 {
03322 m_flags.m_visiblechilds = true;
03323 m_flags.m_childrenOnSameLayer = true;
03324
03325
03326 int index = 0;
03327 forEachIn( a2dVertexList, GetPoints() )
03328 {
03329 a2dLineSegment* point = *iter;
03330
03331 a2dHandle* handle = new a2dHandle( this, point->m_x, point->m_y, wxT("__index__") );
03332 handle->SetLayer( m_layer );
03333 Append(handle);
03334 handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
03335 PROPID_Index->SetPropertyToObject( handle, index++ );
03336 }
03337
03338 m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT("a2dHandle") );
03339 m_flags.m_editingCopy = true;
03340
03341
03342
03343 Update( updatemask_force );
03344
03345 SetPending( true );
03346 return true;
03347 }
03348 else
03349 {
03350 PROPID_Allowrotation->SetPropertyToObject( this, true );
03351 PROPID_Allowskew->SetPropertyToObject( this, true );
03352
03353 return a2dCanvasObject::DoStartEdit( editmode, editstyle );
03354 }
03355 }
03356
03357 return false;
03358 }
03359
03360 bool a2dVertexListCurve::GetXyAtSweep( double sweepValue, a2dPoint2D& point ) const
03361 {
03362 double xp,yp;
03363 if(!m_lpoints->size())
03364 return false;
03365
03366 a2dVertexList::iterator iter = m_lpoints->begin();
03367 a2dPoint2D pointc = (*iter)->GetPoint();
03368 xp = pointc.m_x;
03369 yp = pointc.m_y;
03370
03371 while ( iter != m_lpoints->end() )
03372 {
03373 a2dPoint2D pointc = (*iter)->GetPoint();
03374 if ( xp < sweepValue && pointc.m_x >= sweepValue )
03375 {
03376 point.m_x = sweepValue;
03377 point.m_y = (pointc.m_y-yp) * (pointc.m_x-xp)/(pointc.m_x-xp) + yp;
03378 return true;
03379 }
03380 xp = pointc.m_x;
03381 yp = pointc.m_y;
03382 iter++;
03383 }
03384
03385
03386 point.m_x = sweepValue;
03387 point.m_y = yp;
03388
03389 return false;
03390 }
03391
03392 a2dBoundingBox a2dVertexListCurve::DoGetUnTransformedBbox( a2dBboxFlags flags ) const
03393 {
03394 a2dBoundingBox bbox;
03395 double xw,yw;
03396 m_curveBox.SetValid(false);
03397 if ( m_spline )
03398 {
03399 a2dVertexList* lpoints = new a2dVertexList();
03400 a2dLineSegment* pointo;
03401 a2dVertexList::iterator iter;
03402 for( iter = m_lpoints->begin(); iter != m_lpoints->end(); ++iter )
03403 {
03404 pointo = (*iter);
03405 a2dLineSegment* point = new a2dLineSegment(*pointo);
03406 lpoints->push_back(point);
03407 }
03408
03409 lpoints->ConvertSplinedPolygon(10);
03410 for( iter = lpoints->begin(); iter != lpoints->end(); ++iter )
03411 {
03412 a2dLineSegment* point = (*iter);
03413 m_curveBox.Expand(point->m_x,point->m_y);
03414 Curve2World( point->m_x,point->m_y, xw, yw );
03415 bbox.Expand( xw, yw );
03416 }
03417 delete lpoints;
03418 }
03419 else
03420 {
03421 for( a2dVertexList::iterator iter = m_lpoints->begin(); iter != m_lpoints->end(); ++iter )
03422 {
03423 a2dLineSegment* point = (*iter);
03424 m_curveBox.Expand(point->m_x,point->m_y);
03425 Curve2World( point->m_x,point->m_y, xw, yw );
03426 bbox.Expand( xw, yw );
03427 }
03428 }
03429 return bbox;
03430 }
03431
03432 bool a2dVertexListCurve::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
03433 {
03434 if ( !m_bbox.GetValid())
03435 {
03436
03437 if ( m_childobjects != wxNullCanvasObjectList )
03438 m_childobjects->SetSpecificFlags( true, a2dCanvasOFlags::PENDING );
03439
03440 m_bbox = DoGetUnTransformedBbox();
03441 m_bbox.MapBbox(m_lworld);
03442
03443 if ( m_flags.m_editingCopy && m_spline )
03444 {
03445 m_spline = false;
03446 a2dBoundingBox bboxs = DoGetUnTransformedBbox();
03447 bboxs.MapBbox(m_lworld);
03448 m_bbox.Expand( bboxs );
03449 m_spline = true;
03450
03451 if (m_clipdata.GetValid())
03452 {
03453 double xw, yw;
03454 Curve2World( m_clipdata.GetMaxX(), m_clipdata.GetMaxY(), xw, yw );
03455 a2dBoundingBox box;
03456 box.Expand( xw, yw );
03457 Curve2World( m_clipdata.GetMinX(), m_clipdata.GetMinY(), xw, yw );
03458 box.Expand( xw, yw );
03459 box.MapBbox(m_lworld);
03460
03461 m_bbox.And(&box);
03462 }
03463 }
03464
03465 a2dBoundingBox box = m_curvesArea->GetGroup()->GetPlotAreaBbox();
03466 m_bbox.And( &box );
03467 return true;
03468 }
03469 return false;
03470 }
03471
03472 void a2dVertexListCurve::DoRender( a2dIterC& ic, OVERLAP WXUNUSED(clipparent) )
03473 {
03474
03475
03476 a2dBoundingBox curvebox = GetClippedCurveBoundaries();
03477 if(!curvebox.GetValid())
03478 return;
03479
03480 double xw,yw;
03481 if (!(m_rendermode & a2dCURVES_RENDER_NO_POINTS))
03482 {
03483 a2dStroke current = ic.GetDrawer2D()->GetDrawerStroke();
03484 a2dFill fillcurrent = ic.GetDrawer2D()->GetDrawerFill();
03485
03486 if ( m_highlightmode )
03487 {
03488 a2dStroke tmps = a2dStroke(wxColour(239,232,0),3);
03489 ic.GetDrawer2D()->SetDrawerStroke( tmps );
03490 ic.GetDrawer2D()->SetDrawerFill( *a2dBLACK_FILL );
03491 }
03492 else
03493 {
03494 ic.GetDrawer2D()->SetDrawerStroke( *a2dBLACK_STROKE );
03495 ic.GetDrawer2D()->SetDrawerFill( *a2dTRANSPARENT_FILL );
03496 }
03497
03498 forEachIn( a2dVertexList, m_lpoints )
03499 {
03500 a2dLineSegment* point = *iter;
03501 if ( point->m_x >= curvebox.GetMinX() && point->m_x <= curvebox.GetMaxX() )
03502 {
03503 Curve2World( point->m_x, point->m_y, xw, yw );
03504
03505 double xd,yd;
03506 ic.GetTransform().TransformPoint( xw, yw, xd, yd );
03507 int radius = 2;
03508 xd = ic.GetDrawer2D()->WorldToDeviceX( xd );
03509 yd = ic.GetDrawer2D()->WorldToDeviceY( yd );
03510
03511 ic.GetDrawer2D()->PushIdentityTransform();
03512 ic.GetDrawer2D()->DrawCircle( xd, yd, radius );
03513 ic.GetDrawer2D()->PopTransform();
03514
03515 }
03516 if ( point->m_x > curvebox.GetMaxX() )
03517 break;
03518 }
03519
03520 ic.GetDrawer2D()->SetDrawerStroke( current );
03521 ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
03522 }
03523
03524 wxRasterOperationMode prevlogfunction = wxNO_OP;
03525 wxDC* aDC = NULL;
03526 if(m_logFunction != wxNO_OP)
03527 {
03528 aDC = ic.GetDrawer2D()->GetRenderDC();
03529 prevlogfunction = aDC->GetLogicalFunction();
03530 aDC->SetLogicalFunction(m_logFunction);
03531 }
03532
03533 if (m_rendermode & a2dCURVES_RENDER_NORMAL)
03534 {
03535 bool second = false;
03536 double xprev = 0, yprev = 0;
03537 a2dLineSegment* lastpoint = NULL;
03538 forEachIn( a2dVertexList, m_lpoints )
03539 {
03540 a2dLineSegment* point = *iter;
03541 if ( second && point->m_x >= curvebox.GetMinX() )
03542 {
03543 Curve2World( lastpoint->m_x, lastpoint->m_y, xprev, yprev );
03544 Curve2World( point->m_x, point->m_y, xw, yw );
03545 ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
03546 }
03547 if ( point->m_x > curvebox.GetMaxX() )
03548 break;
03549
03550 lastpoint = point;
03551
03552 second = true;
03553 }
03554 }
03555 else if (m_rendermode & a2dCURVES_RENDER_FILL_LINE)
03556 {
03557 bool second = false;
03558 double xprev = 0, yprev = 0;
03559 double yw0;
03560 a2dLineSegment* point = *(m_lpoints->begin());
03561 Curve2World( point->m_x, 0, xw, yw0 );
03562 a2dLineSegment* lastpoint = NULL;
03563 forEachIn( a2dVertexList, m_lpoints )
03564 {
03565 a2dLineSegment* point = *iter;
03566 if ( second && point->m_x >= curvebox.GetMinX() )
03567 {
03568 Curve2World( lastpoint->m_x, lastpoint->m_y, xprev, yprev );
03569 Curve2World( point->m_x, point->m_y, xw, yw );
03570 ic.GetDrawer2D()->DrawLine( xw, yw0, xw, yw );
03571 ic.GetDrawer2D()->DrawLine( xprev, yprev, xw, yw );
03572 }
03573 if ( point->m_x > curvebox.GetMaxX() )
03574 break;
03575
03576 lastpoint = point;
03577 second = true;
03578 }
03579 }
03580 if(aDC)
03581 aDC->SetLogicalFunction(prevlogfunction);
03582 }
03583
03584 #if wxART2D_USE_CVGIO
03585 void a2dVertexListCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
03586 {
03587 a2dCurve::DoSave( parent, out, xmlparts, towrite );
03588 if ( xmlparts == a2dXmlSer_attrib )
03589 {
03590 if ( m_spline )
03591 {
03592 out.WriteAttribute( wxT("spline") , m_spline );
03593 }
03594 out.WriteAttribute( wxT("points") , m_lpoints->size() );
03595 out.WriteAttribute( wxT("rendermode") , m_rendermode );
03596 out.WriteAttribute( wxT("editmode") , m_editmode );
03597 }
03598 else
03599 {
03600 unsigned int i=0;
03601 forEachIn( a2dVertexList, m_lpoints)
03602 {
03603 if (i%6==0)
03604 out.WriteNewLine();
03605 a2dLineSegment* point = *iter;
03606 out.WriteStartElementAttributes( wxT("xy") );
03607 out.WriteAttribute( wxT("x") , point->m_x );
03608 out.WriteAttribute( wxT("y") , point->m_y );
03609 out.WriteEndAttributes(true);
03610 i++;
03611 }
03612 }
03613 }
03614
03615 void a2dVertexListCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
03616 {
03617 a2dCurve::DoLoad( parent, parser, xmlparts );
03618 if ( xmlparts == a2dXmlSer_attrib )
03619 {
03620 m_spline = parser.GetAttributeValueBool( wxT("spline"), false );
03621 m_rendermode = parser.GetAttributeValueInt( wxT("rendermode") );
03622 m_editmode = parser.GetAttributeValueInt( wxT("editmode") );
03623 }
03624 else
03625 {
03626 while( parser.GetTagName() == wxT("xy") )
03627 {
03628 double x = parser.GetAttributeValueDouble( wxT("x") );
03629 double y = parser.GetAttributeValueDouble( wxT("y") );
03630 a2dLineSegment* point = new a2dLineSegment( x, y );
03631 m_lpoints->push_back(point);
03632
03633 parser.Next();
03634 parser.Require( END_TAG, wxT("xy") );
03635 parser.Next();
03636 }
03637 }
03638 }
03639 #endif //wxART2D_USE_CVGIO
03640
03641 bool a2dVertexListCurve::DoIsHitWorld( a2dIterC& ic, a2dHitEvent& hitEvent )
03642 {
03643 double xcurve, ycurve;
03644 World2Curve(hitEvent.m_relx, hitEvent.m_rely, xcurve, ycurve );
03645
03646 a2dPoint2D P = a2dPoint2D( xcurve, ycurve );
03647 double pw = ic.GetWorldStrokeExtend();
03648 double margin = ic.GetTransformedHitMargin();
03649
03650 if (PointOnCurve(P,pw+margin))
03651 {
03652 hitEvent.m_how = a2dHit::stock_strokeoutside;
03653 return true;
03654 }
03655 else
03656 {
03657 hitEvent.m_how = a2dHit::stock_nohit;
03658 return false;
03659 }
03660 }
03661
03662 bool a2dVertexListCurve::PointOnCurve(const a2dPoint2D& P, double margin)
03663 {
03664 bool result = false;
03665 double distance;
03666 a2dPoint2D p1,p2;
03667
03668 a2dVertexList* rlist;
03669 if ( m_spline )
03670 {
03671
03672 a2dVertexList* lpoints = new a2dVertexList();
03673 for( a2dVertexList::iterator iter = m_lpoints->begin(); iter != m_lpoints->end(); ++iter )
03674 {
03675 a2dLineSegment* point = new a2dLineSegment(*(*iter));
03676 lpoints->push_back(point);
03677 }
03678
03679 lpoints->ConvertSplinedPolyline(10);
03680 rlist=lpoints;
03681 }
03682 else
03683 rlist=m_lpoints;
03684
03685 if ( rlist->size() )
03686 {
03687 a2dVertexList::iterator iter = rlist->begin();
03688 p2 = (*iter)->GetPoint();
03689 while ( iter != rlist->end() && !result)
03690 {
03691 p1=p2;
03692 iter++;
03693 if ( iter != rlist->end() ) break;
03694 p2 = (*iter)->GetPoint();
03695
03696 if (margin > sqrt(pow(p1.m_x-P.m_x,2)+pow(p1.m_y-P.m_y,2)))
03697 result=true;
03698 else if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
03699 {
03700 a2dLine line1(p1,p2);
03701 if (line1.PointInLine(P,distance,margin) == R_IN_AREA)
03702 result=true;
03703 }
03704 }
03705 }
03706
03707 if ( m_spline )
03708 {
03709 for( a2dVertexList::iterator iter = rlist->begin(); iter != rlist->end(); ++iter )
03710 {
03711 a2dLineSegment* point = (*iter);
03712 GetBbox().Expand( point->m_x,point->m_y);
03713 }
03714 delete rlist;
03715 }
03716
03717 return result;
03718 }
03719
03720 void a2dVertexListCurve::OnHandleEvent(a2dHandleMouseEvent &event)
03721 {
03722 a2dIterC* ic = event.GetIterC();
03723
03724 if ( m_flags.m_editingCopy )
03725 {
03726 double xw,yw;
03727 xw = event.GetX();
03728 yw = event.GetY();
03729
03730 a2dAffineMatrix atWorld = ic->GetTransform();
03731
03732
03733
03734
03735 a2dAffineMatrix inverselocal = m_lworld;
03736 inverselocal.Invert();
03737
03738 a2dAffineMatrix inverse = ic->GetInverseParentTransform();
03739
03740 double xinternal, yinternal;
03741 inverse.TransformPoint(xw, yw, xinternal, yinternal);
03742
03743 a2dHandle* draghandle = event.GetCanvasHandle();
03744 wxUint16 index = PROPID_Index->GetPropertyValue( draghandle );
03745
03746 wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
03747
03748 if ( editmode == 1 )
03749 {
03750 a2dVertexListCurve* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dVertexListCurve );
03751
03752 double xwi;
03753 double ywi;
03754 inverselocal.TransformPoint( xinternal, yinternal, xwi, ywi );
03755
03756 if (event.GetMouseEvent().LeftUp() )
03757 {
03758 if ( draghandle->GetName() == wxT("__index__") )
03759 {
03760 m_root->GetCommandProcessor()->Submit(new a2dCommand_VertexListCurveMovePoint( original, xinternal, yinternal, index ));
03761 }
03762 else
03763 event.Skip();
03764 }
03765 else if ( event.GetMouseEvent().Dragging() )
03766 {
03767 SetPosXYPoint( index, xinternal, yinternal );
03768 draghandle->SetPosXY( xwi, ywi );
03769 }
03770 else
03771 event.Skip();
03772 }
03773 else
03774 event.Skip();
03775 }
03776 else
03777 {
03778 event.Skip();
03779 }
03780 }
03781
03782 void a2dVertexListCurve::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
03783 {
03784 event.Skip();
03785 }
03786
03787 void a2dVertexListCurve::OnEnterObject(a2dCanvasObjectMouseEvent &event)
03788 {
03789 a2dIterC* ic = event.GetIterC();
03790 ic->GetCanvasView()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS ) );
03791
03792 m_highlightmode = 1;
03793 SetPending( true );
03794 event.Skip();
03795 }
03796
03797 void a2dVertexListCurve::OnLeaveObject(a2dCanvasObjectMouseEvent &event)
03798 {
03799
03800 event.Skip();
03801
03802 m_highlightmode = 0;
03803 SetPending( true );
03804 }
03805
03806
03807
03808
03809
03810
03811 A2D_BEGIN_EVENT_TABLE(a2dPieCurve,a2dCurve)
03812 A2D_EVT_CANVASOBJECT_MOUSE_EVENT( a2dPieCurve::OnCanvasObjectMouseEvent )
03813 A2D_EVT_CANVASOBJECT_ENTER_EVENT( a2dPieCurve::OnEnterObject )
03814 A2D_EVT_CANVASOBJECT_LEAVE_EVENT( a2dPieCurve::OnLeaveObject )
03815 A2D_EVT_CANVASHANDLE_MOUSE_EVENT( a2dPieCurve::OnHandleEvent )
03816 A2D_END_EVENT_TABLE()
03817
03818
03819 a2dPieCurve::a2dPieCurve( a2dVertexArray* points ): a2dCurve()
03820 {
03821 m_points = points;
03822 m_rendermode = a2dCURVES_RENDER_DEFAULT;
03823 }
03824
03825 a2dPieCurve::a2dPieCurve( ): a2dCurve()
03826 {
03827 m_points = new a2dVertexArray;
03828 m_rendermode = a2dCURVES_RENDER_DEFAULT;
03829 }
03830
03831
03832 a2dPieCurve::~a2dPieCurve()
03833 {
03834 delete m_points;
03835 }
03836
03837 a2dPieCurve::a2dPieCurve( const a2dPieCurve &other, CloneOptions options )
03838 :a2dCurve( other, options )
03839 {
03840 m_points = new a2dVertexArray;
03841 unsigned int i;
03842 for (i=0; i< other.m_points->size(); i++)
03843 m_points->push_back( other.m_points->Item(i)->Clone() );
03844
03845
03846 m_rendermode = other.m_rendermode;
03847 }
03848
03849 a2dObject* a2dPieCurve::Clone( CloneOptions options ) const
03850 {
03851 return new a2dPieCurve( *this, options );
03852 };
03853
03854 void a2dPieCurve::RemovePointWorld( double& x, double& y , int index, bool transformed )
03855 {
03856 if ( index == -1 )
03857 index = m_points->size();
03858
03859 x = m_points->Item( index )->m_x;
03860 y = m_points->Item( index )->m_y;
03861 m_points->RemoveAt( index );
03862
03863 Curve2World( x, y, x, y );
03864
03865 if ( transformed )
03866 {
03867 m_lworld.TransformPoint( x, y, x, y );
03868 }
03869
03870 }
03871
03872 void a2dPieCurve::AddPoint( const a2dPoint2D& P, int index )
03873 {
03874 AddPoint( P.m_x, P.m_y, index );
03875 }
03876
03877 void a2dPieCurve::AddPoint( double x, double y, int index )
03878 {
03879 a2dLineSegment* point = new a2dLineSegment( x, y );
03880
03881 if ( index == -1 )
03882 m_points->push_back( point );
03883 else
03884 m_points->Insert( point, index );
03885
03886 SetPending(true);
03887 }
03888
03889 void a2dPieCurve::GetPosXYPointWorld(int index, double& x, double& y, bool transform )
03890 {
03891 if ( index == -1 )
03892 index = m_points->size();
03893
03894 x = m_points->Item( index )->m_x;
03895 y = m_points->Item( index )->m_y;
03896 Curve2World( x, y, x, y );
03897
03898 if ( transform )
03899 {
03900 m_lworld.TransformPoint( x, y, x, y );
03901 }
03902 }
03903
03904 bool a2dPieCurve::GetXyAtSweep( double sweepValue, a2dPoint2D& point ) const
03905 {
03906 double xp,yp;
03907 if(!m_points->size())
03908 return false;
03909
03910 xp = m_points->Item(0)->m_x;
03911 yp = m_points->Item(0)->m_y;
03912
03913 if ( sweepValue <= m_points->Item(0)->m_x )
03914 {
03915 point.m_x = m_points->Item(0)->m_x;
03916 point.m_y = m_points->Item(0)->m_y;
03917 return false;
03918 }
03919
03920 unsigned int i;
03921 for (i=0; i < m_points->size(); i++)
03922 {
03923 if ( xp < sweepValue && m_points->Item(i)->m_x >= sweepValue )
03924 {
03925 point.m_x = sweepValue;
03926 point.m_y = (m_points->Item(i)->m_y-yp) * (sweepValue-xp)/(m_points->Item(i)->m_x-xp) + yp;
03927 return true;
03928 }
03929 xp = m_points->Item(i)->m_x;
03930 yp = m_points->Item(i)->m_y;
03931 }
03932
03933
03934 point.m_x = m_points->Item(i-1)->m_x;
03935 point.m_y = m_points->Item(i-1)->m_y;
03936
03937 return false;
03938 }
03939
03940 a2dBoundingBox a2dPieCurve::DoGetUnTransformedBbox( a2dBboxFlags flags ) const
03941 {
03942 a2dBoundingBox box = m_curvesArea->GetGroup()->GetPlotAreaBbox();
03943 m_curveBox = box;
03944 return box;
03945 }
03946
03947 bool a2dPieCurve::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
03948 {
03949 if ( !m_bbox.GetValid() && m_points->size() )
03950 {
03951 m_bbox = DoGetUnTransformedBbox();
03952 m_bbox.MapBbox(m_lworld);
03953 m_width = m_bbox.GetWidth() * 0.95;
03954 m_height = m_bbox.GetHeight() * 0.95;
03955
03956 return true;
03957 }
03958 return false;
03959 }
03960
03961 void a2dPieCurve::DoRender( a2dIterC& ic, OVERLAP WXUNUSED(clipparent) )
03962 {
03963
03964
03965
03966 unsigned int i;
03967 double xw,yw;
03968
03969 double yt = 0;
03970 for (i=0; i < m_points->size(); i++)
03971 yt +=m_points->Item(i)->m_y;
03972
03973 double dangle = 2*wxPI/yt;
03974
03975 wxRasterOperationMode prevlogfunction = wxNO_OP;
03976 wxDC* aDC = NULL;
03977 if(m_logFunction != wxNO_OP)
03978 {
03979 aDC = ic.GetDrawer2D()->GetRenderDC();
03980 prevlogfunction = aDC->GetLogicalFunction();
03981 aDC->SetLogicalFunction(m_logFunction);
03982 }
03983
03984 if (m_rendermode & a2dCURVES_RENDER_NORMAL)
03985 {
03986 double theta = 0;
03987 double xn, yn;
03988 xn = m_width/2 * cos (theta);
03989 yn = m_height/2 * sin (theta);
03990 for (i=0; i < m_points->size(); i++)
03991 {
03992 xw = xn; yw = yn;
03993 double theta2 = theta;
03994 theta += dangle * m_points->Item(i)->m_y;
03995 ic.GetDrawer2D()->DrawLine( 0,0, xw, yw );
03996 theta2 += 0.02;
03997 xn = m_width/2 * cos (theta2);
03998 yn = m_height/2 * sin (theta2);
03999 while ( theta2 < theta )
04000 {
04001 ic.GetDrawer2D()->DrawLine( xw, yw, xn, yn );
04002 theta2 += 0.02;
04003 xw = xn; yw = yn;
04004 xn = m_width/2 * cos (theta2);
04005 yn = m_height/2 * sin (theta2);
04006 }
04007 xn = m_width/2 * cos (theta);
04008 yn = m_height/2 * sin (theta);
04009 ic.GetDrawer2D()->DrawLine( xw, yw, xn, yn );
04010 }
04011 }
04012 else
04013 {
04014 double theta = 0;
04015 double xn, yn;
04016 xn = m_width/2 * cos (theta);
04017 yn = m_height/2 * sin (theta);
04018 a2dlist< a2dFill >::iterator iter = m_pointsFill.begin();
04019 for (i=0; i < m_points->size(); i++)
04020 {
04021 if ( m_pointsFill.size() )
04022 ic.GetDrawer2D()->SetDrawerFill( *iter );
04023
04024 xw = xn; yw = yn;
04025 double theta2 = theta;
04026 theta += dangle * m_points->Item(i)->m_y;
04027
04028 a2dVertexArray* cpoints = new a2dVertexArray;
04029 cpoints->push_back( new a2dLineSegment( 0, 0 ) );
04030 cpoints->push_back( new a2dLineSegment( xw, yw ) );
04031
04032 theta2 += 0.02;
04033 xn = m_width/2 * cos (theta2);
04034 yn = m_height/2 * sin (theta2);
04035 while ( theta2 < theta )
04036 {
04037 cpoints->push_back( new a2dLineSegment( xn, yn ) );
04038 theta2 += 0.02;
04039 xw = xn; yw = yn;
04040 xn = m_width/2 * cos (theta2);
04041 yn = m_height/2 * sin (theta2);
04042 }
04043 xn = m_width/2 * cos (theta);
04044 yn = m_height/2 * sin (theta);
04045 cpoints->push_back( new a2dLineSegment( xn, yn ) );
04046
04047 ic.GetDrawer2D()->DrawPolygon( cpoints, false, wxWINDING_RULE);
04048 delete cpoints;
04049
04050 iter = m_pointsFill.GetNextAround( iter );
04051 }
04052 }
04053 if(aDC)
04054 aDC->SetLogicalFunction(prevlogfunction);
04055 }
04056
04057 #if wxART2D_USE_CVGIO
04058 void a2dPieCurve::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
04059 {
04060 a2dCurve::DoSave( parent, out, xmlparts, towrite );
04061 if ( xmlparts == a2dXmlSer_attrib )
04062 {
04063 out.WriteAttribute( wxT("points") , m_points->size() );
04064 out.WriteAttribute( wxT("rendermode") , m_rendermode );
04065 }
04066 else
04067 {
04068 unsigned int i;
04069 for (i = 0; i < m_points->size(); i++)
04070 {
04071 if (i%6==0)
04072 out.WriteNewLine();
04073 out.WriteStartElementAttributes( wxT("xy") );
04074 out.WriteAttribute( wxT("x") , m_points->Item(i)->m_x );
04075 out.WriteAttribute( wxT("y") , m_points->Item(i)->m_y );
04076 out.WriteEndAttributes( true );
04077 }
04078 }
04079 }
04080
04081 void a2dPieCurve::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
04082 {
04083 a2dCurve::DoLoad( parent, parser, xmlparts );
04084 if ( xmlparts == a2dXmlSer_attrib )
04085 {
04086 m_rendermode = parser.GetAttributeValueInt( wxT("rendermode") );
04087 }
04088 else
04089 {
04090 while( parser.GetTagName() == wxT("xy") )
04091 {
04092 double x = parser.GetAttributeValueDouble( wxT("x") );
04093 double y = parser.GetAttributeValueDouble( wxT("y") );
04094 a2dLineSegment* point = new a2dLineSegment( x, y );
04095 m_points->push_back( point );
04096
04097 parser.Next();
04098 parser.Require( END_TAG, wxT("xy") );
04099 parser.Next();
04100 }
04101 }
04102 }
04103 #endif //wxART2D_USE_CVGIO
04104
04105 bool a2dPieCurve::DoIsHitWorld( a2dIterC& ic, a2dHitEvent& hitEvent )
04106 {
04107 double xh = hitEvent.m_relx, yh = hitEvent.m_rely;
04108
04109 if ( m_height == 0 && m_width == 0 )
04110 {
04111 hitEvent.m_how = a2dHit::stock_nohit;
04112 return false;
04113 }
04114
04115 if ( m_height == 0 || m_width == 0 )
04116 {
04117 hitEvent.m_how = a2dHit::stock_nohit;
04118 return false;
04119 }
04120
04121 double pw = ic.GetWorldStrokeExtend();
04122 double margin = ic.GetTransformedHitMargin();
04123
04124 double yt = 0;
04125 size_t i;
04126 for (i=0; i < m_points->size(); i++)
04127 yt +=m_points->Item(i)->m_y;
04128
04129 double dangle = 2*wxPI/yt;
04130
04131 double a = m_width/2+pw+margin ;
04132 double b = m_height/2+pw+margin;
04133 double c = wxSqr(xh/a)+wxSqr(yh/b);
04134 if ( 1 > c)
04135 {
04136 double dx = xh;
04137 double dy = yh;
04138 double theta = 0;
04139 size_t i;
04140 for (i=0; i < m_points->size(); i++)
04141 {
04142
04143 double start,end,angle;
04144 start = theta;
04145 theta += dangle * m_points->Item(i)->m_y;
04146 end = theta;
04147
04148 double rx,ry;
04149 double c = m_height/m_width;
04150
04151 rx = sqrt( dx*dx + (dy*dy)/(c*c));
04152 ry = rx*c;
04153
04154 if (dx*ry == 0 && dy*rx == 0)
04155 angle = 0;
04156 else
04157 angle = atan2(dy*rx, dx*ry);
04158
04159 angle = angle-start;
04160 end = end-start;
04161
04162 if (angle<=0) angle += 2.0*wxPI;
04163
04164 if (end<=0) end += 2.0*wxPI;
04165 if (start<0) start += 2.0*wxPI;
04166
04167
04168 angle = angle+start;
04169 end = end+start;
04170
04171 if ( angle > start && angle < end)
04172 {
04173
04174 hitEvent.m_how = a2dHit::stock_fill;
04175 return true;
04176 }
04177 }
04178 }
04179
04180 hitEvent.m_how = a2dHit::stock_nohit;
04181 return false;
04182 }
04183
04184 bool a2dPieCurve::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
04185 {
04186 if ( m_flags.m_editable )
04187 {
04188 if ( editmode == 1 )
04189 {
04190 m_flags.m_draggable = false;
04191
04192 m_flags.m_visiblechilds = true;
04193 m_flags.m_childrenOnSameLayer = true;
04194
04195
04196 size_t i;
04197 double yt = 0;
04198 for (i=0; i < m_points->size(); i++)
04199 yt +=m_points->Item(i)->m_y;
04200
04201 double dangle = 2*wxPI/yt;
04202 double theta = 0;
04203 double xn, yn;
04204 for (i=0; i < m_points->size(); i++)
04205 {
04206 xn = m_width/2 * cos (theta);
04207 yn = m_height/2 * sin (theta);
04208 theta += dangle * m_points->Item(i)->m_y;
04209
04210
04211 a2dHandle* handle = new a2dHandle( this, xn, yn, wxT("__index__") );
04212 handle->SetLayer( m_layer );
04213 handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
04214 PROPID_Index->SetPropertyToObject( handle, i );
04215 Append(handle);
04216 }
04217 m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT("a2dHandle") );
04218
04219
04220
04221 Update( updatemask_force );
04222
04223 SetPending( true );
04224 return true;
04225 }
04226 else
04227 {
04228 PROPID_Allowrotation->SetPropertyToObject( this, true );
04229 PROPID_Allowskew->SetPropertyToObject( this, true );
04230
04231 return a2dCanvasObject::DoStartEdit( editmode, editstyle );
04232 }
04233 }
04234
04235 return false;
04236 }
04237
04238 void a2dPieCurve::OnHandleEvent(a2dHandleMouseEvent &event)
04239 {
04240 a2dIterC* ic = event.GetIterC();
04241
04242 if ( m_flags.m_editingCopy )
04243 {
04244 double xw,yw;
04245 xw = event.GetX();
04246 yw = event.GetY();
04247
04248 a2dAffineMatrix atWorld = ic->GetTransform();
04249
04250
04251
04252
04253 a2dAffineMatrix inverselocal = m_lworld;
04254 inverselocal.Invert();
04255
04256 a2dAffineMatrix inverse = ic->GetInverseParentTransform();
04257
04258 double xinternal, yinternal;
04259 inverse.TransformPoint(xw, yw, xinternal, yinternal);
04260
04261 World2Curve( xinternal, yinternal, xinternal, yinternal );
04262
04263 a2dHandle* draghandle = event.GetCanvasHandle();
04264
04265
04266 wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
04267
04268 if ( editmode == 1 )
04269 {
04270
04271
04272 double xwi;
04273 double ywi;
04274 Curve2World( xinternal, yinternal, xwi, ywi );
04275
04276 if (event.GetMouseEvent().LeftUp() )
04277 {
04278 if ( draghandle->GetName() == wxT("__index__") )
04279 {
04280
04281 }
04282 else
04283 event.Skip();
04284 }
04285 else if ( event.GetMouseEvent().Dragging() )
04286 {
04287
04288 draghandle->SetPosXY( xwi, ywi );
04289 }
04290 else
04291 event.Skip();
04292 }
04293 else
04294 event.Skip();
04295 }
04296 else
04297 {
04298 event.Skip();
04299 }
04300 }
04301
04302 void a2dPieCurve::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
04303 {
04304 event.Skip();
04305 }
04306
04307 void a2dPieCurve::OnEnterObject(a2dCanvasObjectMouseEvent &event)
04308 {
04309 a2dIterC* ic = event.GetIterC();
04310
04311 ic->GetCanvasView()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS ) );
04312
04313 m_highlightmode = 1;
04314 SetPending( true );
04315 event.Skip();
04316 }
04317
04318 void a2dPieCurve::OnLeaveObject(a2dCanvasObjectMouseEvent &event)
04319 {
04320
04321
04322 event.Skip();
04323
04324 m_highlightmode = 0;
04325 SetPending( true );
04326 }
04327
04328
04329
04330