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/canvas/polygon.h"
00022
00023 #include <float.h>
00024 #include "wx/canvas/canobj.h"
00025 #include "wx/canvas/candoc.h"
00026 #include "wx/canvas/drawer.h"
00027 #include "wx/canvas/cancom.h"
00028 #include "wx/canvas/canvas.h"
00029 #include "wx/canvas/canprim.h"
00030 #include "wx/canvas/tools.h"
00031 #include "wx/canvas/canglob.h"
00032
00033 #if defined(__WXMSW__) && defined(__MEMDEBUG__)
00034 #include <wx/msw/msvcrt.h>
00035 #endif
00036
00037
00038 IMPLEMENT_DYNAMIC_CLASS( a2dPolyHandleL, a2dHandle )
00039
00040 IMPLEMENT_DYNAMIC_CLASS(a2dPolygonL, a2dCanvasObject)
00041 IMPLEMENT_DYNAMIC_CLASS(a2dPolylineL, a2dPolygonL)
00042
00043 IMPLEMENT_DYNAMIC_CLASS(a2dPolygonLClipper, a2dPolygonL)
00044 IMPLEMENT_DYNAMIC_CLASS(a2dPolygonLClipper2, a2dPolygonL)
00045
00046 static inline double sqr( double x ) { return x*x; }
00047
00048 static double PointDistSqr( double x1, double y1, double x2, double y2 )
00049 {
00050 double dx = x1-x2;
00051 double dy = y1-y2;
00052 return sqr(dx) + sqr(dy);
00053 }
00054
00055
00056
00057
00058
00059 A2D_BEGIN_EVENT_TABLE( a2dPolygonL, a2dCanvasObject )
00060 A2D_EVT_CANVASOBJECT_MOUSE_EVENT( a2dPolygonL::OnCanvasObjectMouseEvent )
00061 A2D_EVT_CANVASHANDLE_MOUSE_EVENT( a2dPolygonL::OnHandleEvent )
00062 A2D_EVT_CHAR( a2dPolygonL::OnChar )
00063 A2D_END_EVENT_TABLE()
00064
00065 a2dPolygonL::a2dPolygonL()
00066 : a2dCanvasObject()
00067 {
00068 m_lsegments = new a2dVertexList();
00069 m_spline=false;
00070 m_contourwidth = 0;
00071 }
00072
00073 a2dPolygonL::a2dPolygonL( a2dVertexListPtr points, bool spline )
00074 : a2dCanvasObject()
00075 {
00076 m_lsegments = points;
00077 m_spline=spline;
00078 m_contourwidth = 0;
00079 }
00080
00081 a2dPolygonL::~a2dPolygonL()
00082 {
00083 }
00084
00085 void a2dPolygonL::Clear()
00086 {
00087 m_lsegments->clear();
00088 }
00089
00090 a2dPolygonL::a2dPolygonL( const a2dPolygonL& other, CloneOptions options )
00091 : a2dCanvasObject( other, options )
00092 {
00093 m_lsegments = new a2dVertexList();
00094 *m_lsegments = *other.m_lsegments;
00095 m_spline = other.m_spline;
00096 m_contourwidth = other.m_contourwidth;
00097 }
00098
00099 a2dObject* a2dPolygonL::Clone( CloneOptions options ) const
00100 {
00101 return new a2dPolygonL( *this, options );
00102 };
00103
00104 a2dCanvasObjectList* a2dPolygonL::GetAsCanvasVpaths( bool transform )
00105 {
00106 a2dVpath* segments = m_lsegments->ConvertToVpath( true, true );
00107 a2dVectorPath* canpath = new a2dVectorPath( segments );
00108 if ( transform )
00109 segments->Transform( m_lworld );
00110 canpath->SetStroke( this->GetStroke() );
00111 canpath->SetFill( this->GetFill() );
00112 canpath->SetLayer( m_layer );
00113 canpath->SetContourWidth( GetContourWidth() );
00114 a2dCanvasObjectList* canpathlist = new a2dCanvasObjectList();
00115 canpathlist->push_back( canpath );
00116 return canpathlist;
00117 }
00118
00119 a2dCanvasObjectList* a2dPolygonL::GetAsLinesArcs( bool transform )
00120 {
00121 a2dCanvasObjectList* linesAnArcs = new a2dCanvasObjectList();
00122
00123 double xp = m_lsegments->back()->m_x;
00124 double yp = m_lsegments->back()->m_y;
00125 if ( transform )
00126 m_lworld.TransformPoint( xp, yp, xp, yp );
00127 a2dCanvasObject* obj;
00128 for( a2dVertexList::iterator iter = m_lsegments->begin(); iter != m_lsegments->end(); ++iter )
00129 {
00130 double x,y,xm,ym;
00131 a2dLineSegment* seg = *iter;
00132 x = seg->m_x; y = seg->m_y;
00133 if ( transform )
00134 m_lworld.TransformPoint( x, y, x, y );
00135 if ( seg->GetArc() )
00136 {
00137 a2dArcSegment* cseg = (a2dArcSegment*) seg;
00138 xm = cseg->m_x2; ym = cseg->m_y2;
00139 if ( transform )
00140 m_lworld.TransformPoint( xm, ym, xm, ym );
00141 a2dArc* arc = new a2dArc();
00142 arc->SetChord( true );
00143 obj = arc;
00144 arc->Set( xp, yp, xm, ym, x, y );
00145 linesAnArcs->push_back( arc );
00146 }
00147 else
00148 {
00149 a2dSLine* line = new a2dSLine( xp, yp, x, y );
00150 obj = line;
00151 linesAnArcs->push_back( line );
00152 }
00153
00154 obj->SetStroke( this->GetStroke() );
00155 obj->SetFill( this->GetFill() );
00156 obj->SetLayer( m_layer );
00157 obj->SetContourWidth( GetContourWidth() );
00158 obj->SetCanvasDocument( m_root );
00159
00160 xp = x;
00161 yp = y;
00162 }
00163
00164 return linesAnArcs;
00165 }
00166
00167 bool a2dPolygonL::RestrictToObject( a2dRestrictionEngine* engine, a2dSnapToWhatMask snapToWhat )
00168 {
00169
00170 if ( !m_flags.m_snap_to )
00171 return false;
00172
00173 bool res = false;
00174 if ( snapToWhat & a2dRestrictionEngine::snapToObjectVertexes )
00175 {
00176 a2dVertexList::iterator iter = m_lsegments->begin();
00177 a2dLineSegment* seg;
00178 while ( iter != m_lsegments->end() )
00179 {
00180 seg = (*iter);
00181
00182 double x, y;
00183 m_lworld.TransformPoint( seg->m_x, seg->m_y, x, y );
00184
00185
00186 res |= engine->SetPointSnapResultIfCloser( a2dPoint2D( x, y ) );
00187 iter++;
00188 }
00189 }
00190
00191 return res || a2dCanvasObject::RestrictToObject( engine, snapToWhat );
00192 }
00193
00194 int a2dPolygonL::GetIndexSegment( a2dLineSegmentPtr seg )
00195 {
00196 if ( seg.Get() == NULL )
00197 {
00198 return m_lsegments->IndexOf( m_lsegments->back() );
00199 }
00200 else
00201 {
00202 return m_lsegments->IndexOf( seg );
00203 }
00204 }
00205
00206 a2dVertexList::iterator a2dPolygonL::GetSegmentAtIndex( unsigned int index )
00207 {
00208 return m_lsegments->item( index );
00209 }
00210
00211 a2dVertexList* a2dPolygonL::GetSegmentListAtIndex( unsigned int index )
00212 {
00213 if ( index < m_lsegments->size()+1 )
00214 {
00215 return m_lsegments;
00216 }
00217 return NULL;
00218 }
00219
00220
00221 void a2dPolygonL::AddPoint( double x, double y, a2dLineSegmentPtr seg, bool afterinversion )
00222 {
00223 if ( afterinversion )
00224 {
00225 a2dAffineMatrix inverse = m_lworld;
00226 inverse.Invert();
00227 inverse.TransformPoint( x, y, x, y );
00228 }
00229
00230 a2dLineSegment* point = new a2dLineSegment( x, y );
00231
00232 if ( seg.Get() == NULL )
00233 m_lsegments->push_back(point);
00234 else
00235 {
00236 a2dVertexList::iterator iter = m_lsegments->begin();
00237 while ( iter != m_lsegments->end() )
00238 {
00239 if ( (*iter) == seg )
00240 {
00241 m_lsegments->insert( iter, point );
00242 break;
00243 }
00244 ++iter;
00245 }
00246 }
00247
00248 SetPending(true);
00249 }
00250
00251
00252 void a2dPolygonL::AddPoint( const a2dPoint2D& P, int index, bool afterinversion )
00253 {
00254 AddPoint( P.m_x, P.m_y, index, afterinversion );
00255 }
00256
00257 void a2dPolygonL::AddPoint( double x, double y, int index, bool afterinversion )
00258 {
00259 if ( afterinversion )
00260 {
00261 a2dAffineMatrix inverse = m_lworld;
00262 inverse.Invert();
00263 inverse.TransformPoint( x, y, x, y );
00264 }
00265
00266 a2dLineSegment* point = new a2dLineSegment( x, y );
00267
00268 if ( index == -1 )
00269 m_lsegments->push_back(point);
00270 else
00271 {
00272 a2dVertexList::iterator iter = m_lsegments->begin();
00273 int i = 0;
00274 while ( i < index ) { ++iter; i++; }
00275 m_lsegments->insert( iter, point );
00276 }
00277
00278 SetPending(true);
00279 }
00280
00281 void a2dPolygonL::RemoveRedundantPoints( a2dCanvasObject *sendCommandsTo )
00282 {
00283 a2dVertexList::iterator iterp = m_lsegments->end();
00284 a2dVertexList::iterator iter = m_lsegments->begin();
00285
00286 int inode;
00287
00288
00289 iter = m_lsegments->begin();
00290 inode = 0;
00291 if( iter != m_lsegments->end() )
00292 {
00293 iterp = iter++;
00294 inode++;
00295 }
00296 while (iter != m_lsegments->end())
00297 {
00298 a2dLineSegment* line1 = *iterp;
00299 a2dLineSegment* line2 = *iter;
00300 if( line1->GetPoint() == line2->GetPoint() && !line1->GetArc() )
00301 {
00302 if( sendCommandsTo )
00303 m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( sendCommandsTo, inode ) );
00304 m_lsegments->erase( iterp );
00305 }
00306 else
00307 {
00308 inode++;
00309 }
00310
00311 iterp = iter++;
00312 }
00313
00314
00315 a2dVertexList::iterator iterpp = m_lsegments->end();
00316 iter = m_lsegments->begin();
00317 inode = 0;
00318 if( iter != m_lsegments->end() )
00319 {
00320 iterp = iter++;
00321 inode++;
00322 }
00323 if( iter != m_lsegments->end() )
00324 {
00325 iterpp = iterp;
00326 iterp = iter++;
00327 inode++;
00328 }
00329 while (iter != m_lsegments->end())
00330 {
00331 a2dLineSegment* point0 = *iterpp;
00332 a2dLineSegment* point1 = *iterp;
00333 a2dLineSegment* point2 = *iter;
00334
00335 double dx10 = point1->m_x - point0->m_x;
00336 double dy10 = point1->m_y - point0->m_y;
00337 double dx21 = point2->m_x - point1->m_x;
00338 double dy21 = point2->m_y - point1->m_y;
00339
00340 if( !point0->GetArc() && !point1->GetArc() && dx10*dy21 - dx21*dy10 == 0 )
00341 {
00342 if( sendCommandsTo )
00343 m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( sendCommandsTo, inode-1 ) );
00344 m_lsegments->erase( iterp );
00345 }
00346 else
00347 {
00348 inode++;
00349 iterpp = iterp;
00350 }
00351 iterp = iter++;
00352 }
00353 }
00354
00355 void a2dPolygonL::RemoveSegment( double& x, double& y , a2dLineSegmentPtr seg, bool transformed )
00356 {
00357 if ( seg.Get() == NULL )
00358 {
00359 a2dLineSegment* point;
00360 point = m_lsegments->back();
00361 x = point->m_x;
00362 y = point->m_y;
00363 m_lsegments->pop_back();
00364 }
00365 else
00366 {
00367 a2dVertexList::iterator iter = m_lsegments->begin();
00368 a2dLineSegment* point;
00369 while ( iter != m_lsegments->end() )
00370 {
00371 if ( *iter == seg )
00372 {
00373 point = (*iter);
00374 x = point->m_x;
00375 y = point->m_y;
00376 m_lsegments->erase( iter );
00377 break;
00378 }
00379 iter++;
00380 }
00381 }
00382
00383 if ( transformed )
00384 {
00385 m_lworld.TransformPoint( x, y, x, y );
00386 }
00387
00388 SetPending(true);
00389 }
00390
00391 void a2dPolygonL::RemoveSegment( double& x, double& y , int index, bool transformed )
00392 {
00393 if ( index == -1 )
00394 {
00395 a2dLineSegment* point;
00396 point = m_lsegments->back();
00397 x = point->m_x;
00398 y = point->m_y;
00399 m_lsegments->pop_back();
00400 }
00401 else
00402 {
00403 int i = 0;
00404 a2dVertexList::iterator iter = m_lsegments->begin();
00405 a2dLineSegment* point;
00406 while ( iter != m_lsegments->end() )
00407 {
00408 if ( i == index )
00409 {
00410 point = (*iter);
00411 x = point->m_x;
00412 y = point->m_y;
00413 m_lsegments->erase( iter );
00414 break;
00415 }
00416 i++;
00417 iter++;
00418 }
00419 }
00420
00421 if ( transformed )
00422 {
00423 m_lworld.TransformPoint( x, y, x, y );
00424 }
00425
00426 SetPending(true);
00427 }
00428
00429 void a2dPolygonL::GetPosXYSegment(int index, double& x, double& y, bool transform ) const
00430 {
00431 if ( index == -1 )
00432 {
00433 a2dLineSegment* point;
00434 point = m_lsegments->back();
00435 x = point->m_x;
00436 y = point->m_y;
00437 }
00438 else
00439 {
00440 int i = 0;
00441 a2dVertexList::iterator iter = m_lsegments->begin();
00442 a2dLineSegment* point;
00443 while ( iter != m_lsegments->end() )
00444 {
00445 if ( i == index )
00446 {
00447 point = (*iter);
00448 x = point->m_x;
00449 y = point->m_y;
00450 break;
00451 }
00452 i++;
00453 iter++;
00454 }
00455 }
00456
00457 if ( transform )
00458 {
00459 m_lworld.TransformPoint( x, y, x, y );
00460 }
00461 }
00462
00463 void a2dPolygonL::GetPosXYSegment( a2dLineSegmentPtr seg, double& x, double& y, bool transform ) const
00464 {
00465 if ( seg.Get() == NULL )
00466 {
00467 a2dLineSegment* point;
00468 point = m_lsegments->back();
00469 x = point->m_x;
00470 y = point->m_y;
00471 }
00472 else
00473 {
00474 x = seg->m_x;
00475 y = seg->m_y;
00476 }
00477
00478 if ( transform )
00479 {
00480 m_lworld.TransformPoint( x, y, x, y );
00481 }
00482 }
00483
00484 void a2dPolygonL::GetPosXYMidSegment(int index, double& x, double& y, bool transform ) const
00485 {
00486 if ( index == -1 )
00487 {
00488 a2dLineSegment* seg = m_lsegments->back();
00489 wxASSERT_MSG( seg->GetArc() , _T("this is not an arc segment.") );
00490 a2dArcSegment* cseg = (a2dArcSegment*) seg;
00491 x = cseg->m_x2;
00492 y = cseg->m_y2;
00493 }
00494 else
00495 {
00496 int i = 0;
00497 a2dVertexList::iterator iter = m_lsegments->begin();
00498 a2dLineSegment* seg;
00499 while ( iter != m_lsegments->end() )
00500 {
00501 if ( i == index )
00502 {
00503 seg = (*iter);
00504 wxASSERT_MSG( seg->GetArc() , _T("this is not an arc segment.") );
00505 a2dArcSegment* cseg = (a2dArcSegment*) seg;
00506 x = cseg->m_x2;
00507 y = cseg->m_y2;
00508 break;
00509 }
00510 i++;
00511 iter++;
00512 }
00513 }
00514
00515 if ( transform )
00516 {
00517 m_lworld.TransformPoint( x, y, x, y );
00518 }
00519 }
00520
00521 void a2dPolygonL::GetPosXYMidSegment( a2dLineSegmentPtr seg, double& x, double& y, bool transform ) const
00522 {
00523 if ( seg.Get() == NULL )
00524 {
00525 a2dLineSegment* seg = m_lsegments->back();
00526 wxASSERT_MSG( seg->GetArc() , _T("this is not an arc segment.") );
00527 a2dArcSegment* cseg = (a2dArcSegment*) seg;
00528 x = cseg->m_x2;
00529 y = cseg->m_y2;
00530 }
00531 else
00532 {
00533 wxASSERT_MSG( seg->GetArc() , _T("this is not an arc segment.") );
00534 a2dArcSegment* cseg = (a2dArcSegment*) seg.Get();
00535 x = cseg->m_x2;
00536 y = cseg->m_y2;
00537 }
00538
00539 if ( transform )
00540 {
00541 m_lworld.TransformPoint( x, y, x, y );
00542 }
00543 }
00544
00545 void a2dPolygonL::SetPosXYSegment(int n, double x, double y, bool afterinversion )
00546 {
00547 if ( afterinversion )
00548 {
00549 a2dAffineMatrix inverse = m_lworld;
00550 inverse.Invert();
00551 inverse.TransformPoint( x, y, x, y );
00552 }
00553
00554 m_lsegments->SetPointAdjustArcs( n, x, y, true );
00555 SetPending(true);
00556 }
00557
00558 void a2dPolygonL::SetPosXYSegment( a2dLineSegmentPtr seg, double x, double y, bool afterinversion )
00559 {
00560 if ( afterinversion )
00561 {
00562 a2dAffineMatrix inverse = m_lworld;
00563 inverse.Invert();
00564 inverse.TransformPoint( x, y, x, y );
00565 }
00566
00567 m_lsegments->SetPointAdjustArcs( seg, x, y, true );
00568 SetPending(true);
00569 }
00570
00571 void a2dPolygonL::SetPosXYMidSegment(int index, double x, double y, bool afterinversion )
00572 {
00573 if ( afterinversion )
00574 {
00575 a2dAffineMatrix inverse = m_lworld;
00576 inverse.Invert();
00577 inverse.TransformPoint( x, y, x, y );
00578 }
00579
00580 a2dVertexList::iterator iterp = m_lsegments->end()--;
00581 a2dVertexList::iterator iter = m_lsegments->begin();
00582 a2dLineSegment* seg;
00583 int i=0;
00584 while ( iter != m_lsegments->end() )
00585 {
00586 seg = (*iter);
00587 if ( i == index )
00588 {
00589 wxASSERT_MSG( seg->GetArc() , _T("this is not an arc segment.") );
00590 a2dArcSegment* cseg = (a2dArcSegment*) seg;
00591 cseg->SetMidPoint( *(*iterp), x, y );
00592 break;
00593 }
00594 i++;
00595 iterp = iter;
00596 iter++;
00597 }
00598 SetPending(true);
00599 }
00600
00601 void a2dPolygonL::SetPosXYMidSegment( a2dLineSegmentPtr seg, double x, double y, bool afterinversion )
00602 {
00603 if ( afterinversion )
00604 {
00605 a2dAffineMatrix inverse = m_lworld;
00606 inverse.Invert();
00607 inverse.TransformPoint( x, y, x, y );
00608 }
00609
00610 a2dVertexList::iterator iterp = m_lsegments->end()--;
00611 a2dVertexList::iterator iter = m_lsegments->begin();
00612 a2dLineSegment* segp;
00613 while ( iter != m_lsegments->end() )
00614 {
00615 segp = (*iter);
00616 if ( segp == seg )
00617 {
00618 wxASSERT_MSG( segp->GetArc() , _T("this is not an arc segment.") );
00619 a2dArcSegment* cseg = (a2dArcSegment*) segp;
00620 cseg->SetMidPoint( *(*iterp), x, y );
00621 break;
00622 }
00623 iterp = iter;
00624 iter++;
00625 }
00626 SetPending(true);
00627 }
00628
00629 bool a2dPolygonL::EliminateMatrix()
00630 {
00631 if (!m_lworld.IsIdentity())
00632 {
00633 m_lsegments->ConvertToLines();
00634 a2dVertexList::iterator iter = m_lsegments->begin();
00635
00636 while ( iter != m_lsegments->end() )
00637 {
00638 a2dLineSegment* point = (*iter);
00639 m_lworld.TransformPoint( point->m_x, point->m_y, point->m_x, point->m_y );
00640 iter++;
00641 }
00642
00643 }
00644 return a2dCanvasObject::EliminateMatrix();
00645 }
00646
00647 void a2dPolygonL::SetSegments( a2dVertexList* points )
00648 {
00649 m_lsegments = points;
00650 }
00651
00652 bool a2dPolygonL::AdjustAfterChange( bool WXUNUSED(final) )
00653 {
00654 return false;
00655 }
00656
00657 void a2dPolygonL::SetHandleToIndex( a2dPolyHandleL* handle, unsigned int index )
00658 {
00659 handle->SetNode( GetSegments()->item( index ) );
00660 a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
00661 handle->SetNodeOrg( original->GetSegments()->item( index ) );
00662 }
00663
00664 bool a2dPolygonL::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
00665 {
00666 if ( m_flags.m_editable )
00667 {
00668 a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
00669
00670 if ( editmode == 1 )
00671 {
00672 if( ! ( editstyle & wxEDITSTYLE_NOHANDLES ) )
00673 {
00674 m_flags.m_visiblechilds = true;
00675 m_flags.m_childrenOnSameLayer = true;
00676
00677
00678 a2dVertexList::iterator iter = m_lsegments->begin();
00679 a2dVertexList::iterator iterorg = original->m_lsegments->begin();
00680 a2dLineSegment* seg;
00681 while ( iter != GetSegments()->end() )
00682 {
00683 seg = (*iter);
00684
00685 a2dPolyHandleL* handle = new a2dPolyHandleL( this, iter, iterorg, m_lsegments, original->m_lsegments, wxT("__index__") );
00686 Append(handle);
00687 handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
00688 handle->SetLayer( m_layer );
00689
00690 if ( seg->GetArc() )
00691 {
00692
00693 a2dArcSegment* cseg = (a2dArcSegment*) seg;
00694
00695 handle = new a2dPolyHandleL( this, iter, iterorg, m_lsegments, original->m_lsegments, cseg->m_x2, cseg->m_y2, wxT("__indexarc__") );
00696 handle->SetArcHandle( true );
00697 handle->SetLayer( m_layer );
00698 Append(handle);
00699 handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
00700 }
00701 iter++;
00702 iterorg++;
00703 }
00704
00705 m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT("a2dPolyHandleL") );
00706 m_flags.m_editingCopy = true;
00707
00708
00709
00710 Update( updatemask_force );
00711
00712 SetPending( true );
00713 }
00714 return true;
00715 }
00716 else
00717 {
00718 PROPID_Allowrotation->SetPropertyToObject( this, true );
00719 PROPID_Allowskew->SetPropertyToObject( this, true );
00720
00721 return a2dCanvasObject::DoStartEdit( editmode, editstyle );
00722 }
00723 }
00724
00725 return false;
00726 }
00727
00728 void a2dPolygonL::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
00729 {
00730 if ( !m_flags.m_editingCopy || !m_flags.m_editable )
00731 {
00732 event.Skip();
00733 return;
00734 }
00735
00736 a2dIterC* ic = event.GetIterC();
00737
00738 a2dPolyHandleL* seghandle;
00739
00740 double xw,yw;
00741 xw = event.GetX();
00742 yw = event.GetY();
00743
00744 a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
00745
00746
00747
00748
00749
00750 if ( event.GetMouseEvent().Moving() )
00751 {
00752 if ( event.GetHow().IsStrokeHit() )
00753 {
00754 switch( event.GetHow().m_stroke2 )
00755 {
00756 case a2dHit::stroke2_edgehor:
00757 ic->GetCanvasView()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_SIZENS ) );
00758 break;
00759 case a2dHit::stroke2_edgevert:
00760 ic->GetCanvasView()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_SIZEWE ) );
00761 break;
00762 case a2dHit::stroke2_edgeother:
00763 ic->GetCanvasView()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_SIZENESW ) );
00764 break;
00765 case a2dHit::stroke2_vertex:
00766 ic->GetCanvasView()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS ) );
00767 break;
00768 default:
00769 break;
00770 }
00771 }
00772 else
00773 {
00774 ic->GetCanvasView()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_HAND ) );
00775 event.Skip();
00776 }
00777 }
00778 else if ( event.GetMouseEvent().LeftDown() )
00779 {
00780 a2dRestrictionEngine *restrictEngine = a2dCanvasGlobals->GetRestrictionEngine();
00781 if (restrictEngine )
00782 restrictEngine->SetRestrictPoint( xw, yw );
00783
00784 if ( event.GetHow().IsEdgeHit() )
00785 {
00786 a2dVertexList::iterator iterSeg = GetSegmentAtIndex( event.GetHow().m_index );
00787 a2dVertexList::iterator iterSegOrg = original->GetSegmentAtIndex( event.GetHow().m_index );
00788 a2dLineSegment* seg = *iterSeg;
00789 if ( event.GetMouseEvent().AltDown() )
00790 seghandle = new a2dPolyHandleL( this, iterSeg, iterSegOrg, m_lsegments, original->m_lsegments, wxT("__insert__") );
00791 else
00792 seghandle = new a2dPolyHandleL( this, iterSeg, iterSegOrg, m_lsegments, original->m_lsegments, wxT("__segment__") );
00793 seghandle->SetLayer( m_layer );
00794 Append(seghandle);
00795 ic->SetCorridorPath( true, seghandle );
00796 seghandle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
00797
00798 a2dHandleMouseEvent handleEvent( ic, seghandle, xw, yw, event.GetMouseEvent() );
00799 ProcessEvent( handleEvent );
00800 }
00801 else
00802 event.Skip();
00803 }
00804 else
00805 event.Skip();
00806 }
00807
00808 void a2dPolygonL::OnChar(wxKeyEvent& event)
00809 {
00810 if ( m_flags.m_editingCopy )
00811 {
00812 switch(event.GetKeyCode())
00813 {
00814 case WXK_TAB:
00815 {
00816 wxUint16* editmode = PROPID_Editmode->GetPropertyValuePtr( this );
00817 if ( editmode )
00818 {
00819 (*editmode)++;
00820 if ( (*editmode) > 1) (*editmode) = 0;
00821 ReStartEdit( (*editmode) );
00822 }
00823 break;
00824 }
00825 case WXK_DELETE:
00826 {
00827 }
00828 default:
00829 event.Skip();
00830 }
00831 }
00832 else
00833 event.Skip();
00834 }
00835
00836 void a2dPolygonL::SyncHandlesWithLineSegments()
00837 {
00838 for( a2dCanvasObjectList::iterator iter = m_childobjects->begin(); iter != m_childobjects->end(); ++iter )
00839 {
00840 a2dCanvasObject *obj = *iter;
00841
00842 a2dPolyHandleL* handle = wxDynamicCast( obj, a2dPolyHandleL );
00843
00844 if ( handle && !handle->GetRelease( ) )
00845 {
00846 a2dLineSegment* segment = *(handle->GetNode());
00847
00848 if ( segment->GetArc() && handle->GetArcHandle() )
00849 {
00850 a2dArcSegment* cseg = (a2dArcSegment*) segment;
00851
00852 handle->SetPosXyPoint( cseg->GetMidPoint() );
00853 }
00854 else
00855 handle->SetPosXY( segment->m_x, segment->m_y );
00856 }
00857 }
00858 }
00859
00860 void a2dPolygonL::OnHandleEvent(a2dHandleMouseEvent &event)
00861 {
00862 a2dIterC* ic = event.GetIterC();
00863
00864 if ( event.GetCanvasHandle()->GetRelease() )
00865 return;
00866
00867 if ( m_flags.m_editingCopy )
00868 {
00869 a2dRestrictionEngine *restrictEngine = a2dCanvasGlobals->GetRestrictionEngine();
00870 wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
00871 a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
00872
00873 if ( editmode == 1 )
00874 {
00875 double xw,yw;
00876 xw = event.GetX();
00877 yw = event.GetY();
00878 a2dAffineMatrix atWorld = ic->GetTransform();
00879
00880
00881
00882
00883 a2dAffineMatrix inverselocal = m_lworld;
00884 inverselocal.Invert();
00885
00886 a2dAffineMatrix inverse = ic->GetInverseParentTransform();
00887
00888 double xinternal, yinternal;
00889 inverse.TransformPoint(xw, yw, xinternal, yinternal);
00890
00891 a2dPolyHandleL* draghandle = wxDynamicCast( event.GetCanvasHandle(), a2dPolyHandleL );
00892 a2dVertexList::iterator iter = draghandle->GetNode();
00893 a2dLineSegment* segment = *(iter);
00894 a2dLineSegment* segmentNext = *(m_lsegments->GetNextAround( iter ));
00895 a2dVertexList::iterator iterorg = draghandle->GetNodeOrg();
00896 a2dLineSegment* segmentOrg = *(iterorg);
00897 a2dLineSegment* segmentNextOrg = *(original->m_lsegments->GetNextAround( iterorg ));
00898
00899 a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
00900
00901 double xwi;
00902 double ywi;
00903 if( m_flags.m_snap )
00904 {
00905 if (restrictEngine )
00906 restrictEngine->RestrictPoint( xinternal, yinternal );
00907 }
00908 inverselocal.TransformPoint( xinternal, yinternal, xwi, ywi );
00909 a2dAffineMatrix origworld = m_lworld;
00910
00911 if ( draghandle->GetName() == wxT("__index__") )
00912 {
00913 if ( event.GetMouseEvent().ControlDown() && event.GetMouseEvent().LeftDown() )
00914 {
00915 m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( original, segmentOrg ) );
00916
00917
00918
00919 double x, y;
00920 RemoveSegment( x, y, segment );
00921 ReleaseChild( draghandle );
00922
00923
00924
00925
00926 ic->SetCorridorPathToParent();
00927 ic->GetCanvasView()->PopCursor();
00928 }
00929 if ( event.GetMouseEvent().LeftUp() )
00930 {
00931 double x,y;
00932 x = segment->m_x; y = segment->m_y;
00933 m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( original, x, y, segmentOrg, false ) );
00934
00935 draghandle->SetPosXY( x, y );
00936
00937
00938 original->AdjustAfterChange( true );
00939 }
00940 else if ( event.GetMouseEvent().Dragging() )
00941 {
00942
00943 segment->m_x = xwi;
00944 segment->m_y = ywi;
00945 SetPending( true );
00946 draghandle->SetPosXY( xwi, ywi );
00947 SetPosXYSegment( segment, xwi, ywi, false );
00948 AdjustAfterChange( false );
00949 }
00950 else
00951 event.Skip();
00952 }
00953 else if ( draghandle->GetName() == wxT("__indexarc__") )
00954 {
00955 a2dArcSegment* csegment = (a2dArcSegment*) segment;
00956 if ( event.GetMouseEvent().LeftUp() )
00957 {
00958 double x,y;
00959 x = csegment->m_x2; y = csegment->m_y2;
00960 m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveMidSegment( original, x, y, segmentOrg, false ) );
00961
00962 draghandle->SetPosXY( x, y );
00963
00964
00965 original->AdjustAfterChange( true );
00966 }
00967 else if ( event.GetMouseEvent().Dragging() )
00968 {
00969 csegment->m_x2 = xwi; csegment->m_y2 = ywi;
00970 SetPending( true );
00971
00972
00973 draghandle->SetPosXYRestrict( xwi, ywi );
00974 SyncHandlesWithLineSegments();
00975 AdjustAfterChange( false );
00976 }
00977 else
00978 event.Skip();
00979 }
00980 else if ( draghandle->GetName() == wxT("__insert__") )
00981 {
00982
00983
00984 if (event.GetMouseEvent().LeftUp() )
00985 {
00986 double x,y;
00987 GetPosXYSegment( segmentNext, x, y, false );
00988 m_root->GetCommandProcessor()->Submit( new a2dCommand_AddPoint( original, x, y, segmentNextOrg, false ) );
00989
00990
00991 draghandle->SetPosXY( x, y );
00992 original->AdjustAfterChange( true );
00993 }
00994 else if ( event.GetMouseEvent().LeftDown() )
00995 {
00996 AddPoint( xwi, ywi, segmentNext, false );
00997 draghandle->SetPosXYRestrict( xwi, ywi );
00998 AdjustAfterChange( false );
00999 }
01000 else if ( event.GetMouseEvent().Dragging() )
01001 {
01002 SetPosXYSegment( segmentNext, xwi, ywi , false );
01003 draghandle->SetPosXYRestrict( xwi, ywi );
01004 AdjustAfterChange( false );
01005 }
01006 else
01007 event.Skip();
01008 }
01009 else if ( draghandle->GetName() == wxT("__segment__") )
01010 {
01011 if (event.GetMouseEvent().LeftUp() )
01012 {
01013 double x1,y1;
01014 double x2,y2;
01015 x1 = segment->m_x;
01016 y1 = segment->m_y;
01017
01018 x2 = segmentNext->m_x;
01019 y2 = segmentNext->m_y;
01020
01021 double xwi, ywi, dx,dy;
01022 dx = 0.5*(x2-x1);
01023 dy = 0.5*(y2-y1);
01024 xwi = x1 + dx;
01025 ywi = y1 + dy;
01026 draghandle->SetPosXYRestrict( xwi, ywi );
01027 x1 = xwi - dx; x2 = xwi + dx;
01028 y1 = ywi - dy; y2 = ywi + dy;
01029
01030 m_root->GetCommandProcessor()->Submit(new a2dCommand_MoveSegment( original, x1, y1, segmentOrg, false ));
01031 m_root->GetCommandProcessor()->Submit(
01032 new a2dCommand_MoveSegment( original, x2, y2, segmentNextOrg, false ));
01033
01034
01035
01036
01037
01038
01039
01040
01041 SyncHandlesWithLineSegments();
01042
01043
01044
01045 m_childobjects->Release( a2dCanvasOFlags::ALL, wxT("a2dPolyHandleL"), NULL, wxT("__segment__"), false );
01046 original->AdjustAfterChange( true );
01047 }
01048 else if ( event.GetMouseEvent().LeftDown() )
01049 {
01050
01051 a2dPolyHandleL::PROPID_tmpXIH->SetPropertyToObject( draghandle, xwi );
01052 a2dPolyHandleL::PROPID_tmpYIH->SetPropertyToObject( draghandle, ywi );
01053
01054 double x, y;
01055 x = segment->m_x;
01056 y = segment->m_y;
01057 a2dPolyHandleL::PROPID_tmpXIV1->SetPropertyToObject( draghandle, x );
01058 a2dPolyHandleL::PROPID_tmpYIV1->SetPropertyToObject( draghandle, y );
01059 x = segmentNext->m_x;
01060 y = segmentNext->m_y;
01061 a2dPolyHandleL::PROPID_tmpXIV2->SetPropertyToObject( draghandle, x );
01062 a2dPolyHandleL::PROPID_tmpYIV2->SetPropertyToObject( draghandle, y );
01063 }
01064 else if ( event.GetMouseEvent().Dragging() )
01065 {
01066 double xi_h = a2dPolyHandleL::PROPID_tmpXIH->GetPropertyValue( draghandle );
01067 double yi_h = a2dPolyHandleL::PROPID_tmpYIH->GetPropertyValue( draghandle );
01068 double xi_v1 = a2dPolyHandleL::PROPID_tmpXIV1->GetPropertyValue( draghandle );
01069 double yi_v1 = a2dPolyHandleL::PROPID_tmpYIV1->GetPropertyValue( draghandle );
01070 double xi_v2 = a2dPolyHandleL::PROPID_tmpXIV2->GetPropertyValue( draghandle );
01071 double yi_v2 = a2dPolyHandleL::PROPID_tmpYIV2->GetPropertyValue( draghandle );
01072
01073
01074
01075 draghandle->SetPosXYRestrict( xwi, ywi );
01076 double x1 = xi_v1+xwi-xi_h;
01077 double y1 = yi_v1+ywi-yi_h;
01078 double x2 = xi_v2+xwi-xi_h;
01079 double y2 = yi_v2+ywi-yi_h;
01080
01081 segment->m_x = x1;
01082 segment->m_y = y1;
01083 segmentNext->m_x = x2;
01084 segmentNext->m_y = y2;
01085
01086 SetPending( true );
01087 AdjustAfterChange( false );
01088 }
01089 else
01090 event.Skip();
01091 }
01092 else
01093 event.Skip();
01094 }
01095 else
01096 event.Skip();
01097 }
01098 else
01099 {
01100 event.Skip();
01101 }
01102 }
01103
01104 a2dBoundingBox a2dPolygonL::DoGetUnTransformedBbox( a2dBboxFlags WXUNUSED(flags) ) const
01105 {
01106 a2dBoundingBox bbox;
01107 if ( m_spline )
01108 {
01109 a2dVertexList* lpoints = new a2dVertexList();
01110
01111 *lpoints = *m_lsegments;
01112 lpoints->ConvertIntoSplinedPolygon(10);
01113 bbox = lpoints->GetBbox();
01114 delete lpoints;
01115 }
01116 else
01117 bbox = m_lsegments->GetBbox();
01118
01119 if (m_contourwidth > 0)
01120 bbox.Enlarge( m_contourwidth/2 );
01121
01122 return bbox;
01123 }
01124
01125 bool a2dPolygonL::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
01126 {
01127 if ( !m_bbox.GetValid())
01128 {
01129 if ( m_spline )
01130 {
01131 a2dVertexList* lpoints = new a2dVertexList();
01132
01133 *lpoints = *m_lsegments;
01134 lpoints->ConvertIntoSplinedPolygon(10);
01135 m_bbox = lpoints->GetBbox( m_lworld );
01136 delete lpoints;
01137 }
01138
01139 a2dBoundingBox bboxs = DoGetUnTransformedBbox();
01140 bboxs.MapBbox(m_lworld);
01141 m_bbox.Expand( bboxs );
01142
01143 if ( m_flags.m_editingCopy && m_spline )
01144 {
01145 m_spline = false;
01146 a2dBoundingBox bboxs = DoGetUnTransformedBbox();
01147 bboxs.MapBbox(m_lworld);
01148 m_bbox.Expand( bboxs );
01149 m_spline = true;
01150 }
01151 return true;
01152 }
01153 return false;
01154 }
01155
01156 void a2dPolygonL::DoRender( a2dIterC& ic, OVERLAP WXUNUSED(clipparent) )
01157 {
01158 if ( m_contourwidth )
01159 {
01160 a2dVertexList* contourpoints = m_lsegments->ConvertToContour( m_contourwidth/2, a2dPATH_END_ROUND, true );
01161 ic.GetDrawer2D()->DrawPolygon( contourpoints, m_spline );
01162 delete contourpoints;
01163 }
01164 else
01165 ic.GetDrawer2D()->DrawPolygon( m_lsegments, m_spline, wxWINDING_RULE);
01166
01167 if ( m_flags.m_editingCopy )
01168 {
01169 ic.GetDrawer2D()->OverRuleFixedStyle();
01170 a2dBoundingBox untrans = DoGetUnTransformedBbox();
01171 double x,y,w,h;
01172 x = untrans.GetMinX();
01173 y = untrans.GetMinY();
01174 w = untrans.GetWidth();
01175 h = untrans.GetHeight();
01176
01177 if ( m_spline )
01178 ic.GetDrawer2D()->DrawPolygon( m_lsegments, false, wxWINDING_RULE);
01179
01180 a2dSmrtPtr<a2dRect> around = new a2dRect( x, y, w, h );
01181 around->SetIgnoreSetpending();
01182 around->SetCanvasDocument(m_root);
01183 around->Update( updatemask_force );
01184 around->SetStroke( *wxRED, 0, a2dSTROKE_DOT_DASH );
01185 around->SetFill( *a2dTRANSPARENT_FILL );
01186 around->Render( ic, _ON );
01187
01188 ic.GetDrawer2D()->ReStoreFixedStyle();
01189 }
01190 }
01191
01192 #if wxART2D_USE_CVGIO
01193 void a2dPolygonL::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
01194 {
01195 a2dCanvasObject::DoSave( parent, out, xmlparts, towrite );
01196 if ( xmlparts == a2dXmlSer_attrib )
01197 {
01198 if ( m_spline )
01199 {
01200 out.WriteAttribute( wxT("spline"), m_spline );
01201 }
01202
01203 out.WriteAttribute( wxT("points"), m_lsegments->size() );
01204 out.WriteAttribute( wxT("contourwidth"), m_contourwidth );
01205 }
01206 else
01207 {
01208 unsigned int i=0;
01209 forEachIn( a2dVertexList, m_lsegments )
01210 {
01211 if (i%6==0)
01212 out.WriteNewLine();
01213 a2dLineSegment* seg = *iter;
01214 out.WriteStartElementAttributes( wxT("xy") );
01215 out.WriteAttribute( wxT("x"), seg->m_x );
01216 out.WriteAttribute( wxT("y"), seg->m_y );
01217
01218 if ( seg->GetArc() )
01219 {
01220 a2dArcSegment* arc = (a2dArcSegment*) seg;
01221 out.WriteAttribute( wxT("xm"), arc->m_x2 );
01222 out.WriteAttribute( wxT("ym"), arc->m_y2 );
01223 }
01224
01225 out.WriteEndAttributes( true );
01226 i++;
01227 }
01228 }
01229 }
01230
01231 void a2dPolygonL::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
01232 {
01233 a2dCanvasObject::DoLoad( parent, parser, xmlparts );
01234 if ( xmlparts == a2dXmlSer_attrib )
01235 {
01236 m_spline = parser.GetAttributeValueBool( wxT("spline"), false );
01237 m_contourwidth = parser.GetAttributeValueDouble( wxT("contourwidth"), 0 );
01238 }
01239 else
01240 {
01241 while( parser.GetTagName() == wxT("xy") )
01242 {
01243 double x = parser.GetAttributeValueDouble( wxT("x") );
01244 double y = parser.GetAttributeValueDouble( wxT("y") );
01245
01246 a2dLineSegment* seg;
01247 if ( parser.HasAttribute( wxT("xm") ) )
01248 {
01249 double xm = parser.GetAttributeValueDouble( wxT("xm") );
01250 double ym = parser.GetAttributeValueDouble( wxT("ym") );
01251
01252 seg = new a2dArcSegment( x, y, xm, ym );
01253 }
01254 else
01255 seg = new a2dLineSegment( x, y );
01256
01257 m_lsegments->push_back(seg);
01258
01259 parser.Next();
01260 parser.Require( END_TAG, wxT("xy") );
01261 parser.Next();
01262 }
01263 }
01264 }
01265 #endif //wxART2D_USE_CVGIO
01266
01267 bool a2dPolygonL::DoIsHitWorld( a2dIterC& ic, a2dHitEvent& hitEvent )
01268 {
01269 double xh,yh;
01270 ic.GetInverseTransform().TransformPoint(hitEvent.m_x,hitEvent.m_y,xh,yh);
01271
01272 a2dPoint2D P=a2dPoint2D(xh,yh);
01273 double pw = ic.GetWorldStrokeExtend();
01274 double margin = ic.GetTransformedHitMargin();
01275
01276 hitEvent.m_how = PointInPolygon( P, pw + margin);
01277
01278 return hitEvent.m_how.IsHit();
01279 }
01280
01281 a2dHit a2dPolygonL::PointInPolygon(const a2dPoint2D& P, double marge)
01282 {
01283 a2dVertexList* rlist;
01284 if ( m_spline )
01285 {
01286
01287 a2dVertexList* lpoints = new a2dVertexList();
01288 *lpoints = *m_lsegments;
01289 lpoints->ConvertIntoSplinedPolygon(10);
01290 rlist=lpoints;
01291 }
01292 else
01293 rlist=m_lsegments;
01294
01295 a2dHit result = rlist->HitTestPolygon( P, marge );
01296
01297 if ( m_spline )
01298 delete rlist;
01299
01300 return result;
01301 }
01302
01303
01304
01305
01306
01307 a2dPolylineL::a2dPolylineL()
01308 : a2dPolygonL()
01309 {
01310 m_xscale = m_yscale = 1;
01311 m_pathtype = a2dPATH_END_SQAURE;
01312 }
01313
01314 a2dPolylineL::a2dPolylineL( a2dVertexListPtr points, bool spline )
01315 : a2dPolygonL( points, spline )
01316 {
01317 m_xscale = m_yscale = 1;
01318 m_pathtype = a2dPATH_END_SQAURE;
01319 }
01320
01321 a2dPolylineL::a2dPolylineL( const a2dPolylineL& other, CloneOptions options )
01322 : a2dPolygonL( other, options )
01323 {
01324
01325
01326 m_begin = NULL;
01327 m_end = NULL;
01328 if ( other.m_begin )
01329 m_begin = other.m_begin->TClone( options );
01330 if ( other.m_end )
01331 m_end = other.m_end->TClone( options );
01332
01333
01334
01335
01336
01337
01338 m_xscale = other.m_xscale;
01339 m_yscale = other.m_yscale;
01340 m_pathtype = other.m_pathtype;
01341 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
01342
01343 CurrentSmartPointerOwner = this;
01344 #endif
01345 }
01346
01347 a2dPolylineL::~a2dPolylineL()
01348 {
01349 }
01350
01351 void a2dPolylineL::SetBegin(a2dCanvasObject* begin)
01352 {
01353 SetPending(true);
01354 m_begin = begin;
01355 if (m_begin && m_root )
01356 m_begin->SetCanvasDocument( m_root );
01357 }
01358
01359 void a2dPolylineL::SetEnd(a2dCanvasObject* end)
01360 {
01361 SetPending(true);
01362 m_end = end;
01363 if (m_end && m_root )
01364 m_end->SetCanvasDocument( m_root);
01365 }
01366
01367 a2dObject* a2dPolylineL::Clone( CloneOptions options ) const
01368 {
01369 return new a2dPolylineL( *this, options );
01370 }
01371
01372 a2dPolygonL* a2dPolylineL::GetAsPolygon()
01373 {
01374 if ( m_contourwidth )
01375 {
01376 a2dVertexList* contourpoints = m_lsegments->ConvertToContour( m_contourwidth/2, m_pathtype );
01377 a2dPolygonL* polygon = new a2dPolygonL( contourpoints );
01378 polygon->SetTransformMatrix( m_lworld );
01379 polygon->SetCanvasDocument( m_root );
01380 polygon->SetStroke( this->GetStroke() );
01381 polygon->SetFill( this->GetFill() );
01382 polygon->SetLayer( m_layer );
01383 return polygon;
01384 }
01385 else
01386 return NULL;
01387 }
01388
01389 a2dCanvasObjectList* a2dPolylineL::GetAsCanvasVpaths( bool transform )
01390 {
01391 a2dAffineMatrix pworld;
01392 if ( transform )
01393 pworld = m_lworld;
01394
01395 a2dVpath* segments = NULL;
01396
01397 if ( m_contourwidth )
01398 {
01399 if ( a2dGlobals->GetRoundFactor() == 0 && m_pathtype == a2dPATH_END_ROUND )
01400 {
01401 segments = new a2dVpath();
01402
01403 a2dVertexList contourpoints = *m_lsegments;
01404 contourpoints.ConvertToLines();
01405
01406 a2dLineSegment* segprev = NULL;
01407 a2dLineSegment* seg = NULL;
01408 a2dPoint2D first;
01409 a2dPoint2D second;
01410 a2dPoint2D offsetpointleft;
01411 a2dPoint2D offsetpointright;
01412
01413 a2dVertexList::iterator iter = contourpoints.begin();
01414 while( iter != contourpoints.end() )
01415 {
01416 a2dLineSegment* seg = *iter;
01417 seg = ( *iter );
01418
01419 if ( segprev )
01420 {
01421 first = a2dPoint2D( segprev->m_x, segprev->m_y );
01422 second = a2dPoint2D( seg->m_x, seg->m_y );
01423 offsetpointleft = first;
01424 offsetpointright = first;
01425 a2dLine line1( first, second );
01426 line1.CalculateLineParameters();
01427 line1.Virtual_Point( offsetpointleft, m_contourwidth/2 );
01428 line1.Virtual_Point( offsetpointright, -m_contourwidth/2 );
01429
01430 a2dVpathSegment* segv = new a2dVpathSegment( offsetpointright.m_x, offsetpointright.m_y, a2dPATHSEG_MOVETO );
01431 segments->Add(segv);
01432
01433 a2dLine lineoffset( offsetpointright, offsetpointleft );
01434 lineoffset.CalculateLineParameters();
01435 a2dPoint2D offsetpointfirst;
01436 offsetpointfirst = first;
01437 lineoffset.Virtual_Point( offsetpointfirst, m_contourwidth/2 );
01438 segments->Add( new a2dVpathArcSegment( offsetpointleft.m_x, offsetpointleft.m_y,
01439 offsetpointfirst.m_x, offsetpointfirst.m_y,
01440 a2dPATHSEG_ARCTO, a2dPATHSEG_END_OPEN ) );
01441
01442 offsetpointright = second;
01443 line1.Virtual_Point( offsetpointright, -m_contourwidth/2 );
01444 offsetpointleft = second;
01445 line1.Virtual_Point( offsetpointleft, m_contourwidth/2 );
01446
01447 segv = new a2dVpathSegment( offsetpointleft.m_x, offsetpointleft.m_y, a2dPATHSEG_LINETO, a2dPATHSEG_END_OPEN );
01448 segments->Add(segv);
01449
01450 a2dLine lineoffset2( offsetpointleft, offsetpointright );
01451 lineoffset2.CalculateLineParameters();
01452 a2dPoint2D offsetpointend;
01453 offsetpointend = second;
01454 lineoffset2.Virtual_Point( offsetpointend, m_contourwidth/2 );
01455 segments->Add( new a2dVpathArcSegment( offsetpointright.m_x, offsetpointright.m_y,
01456 offsetpointend.m_x, offsetpointend.m_y,
01457 a2dPATHSEG_ARCTO, a2dPATHSEG_END_OPEN ) );
01458
01459 segv = new a2dVpathSegment( offsetpointright.m_x, offsetpointright.m_y, a2dPATHSEG_LINETO, a2dPATHSEG_END_CLOSED );
01460 segments->Add(segv);
01461 }
01462 iter++;
01463 segprev = seg;
01464 }
01465 }
01466 else
01467 {
01468 segments = new a2dVpath( *m_lsegments, true );
01469 segments->Contour( m_contourwidth/2, m_pathtype );
01470 }
01471 }
01472 else
01473 {
01474 a2dVertexList contourpoints = *m_lsegments;
01475 segments = new a2dVpath( contourpoints, true, false );
01476 }
01477 if ( transform )
01478 segments->Transform( pworld );
01479
01480 a2dVectorPath* canpath = new a2dVectorPath( segments );
01481 canpath->SetCanvasDocument( m_root );
01482 canpath->SetStroke( this->GetStroke() );
01483 canpath->SetFill( this->GetFill() );
01484 canpath->SetLayer( m_layer );
01485 a2dCanvasObjectList* canpathlist = new a2dCanvasObjectList();
01486 canpathlist->push_back( canpath );
01487 return canpathlist;
01488 }
01489
01490 a2dCanvasObjectList* a2dPolylineL::GetAsLinesArcs( bool transform )
01491 {
01492 a2dCanvasObjectList* linesAnArcs = new a2dCanvasObjectList();
01493
01494 double xp = m_lsegments->front()->m_x;
01495 double yp = m_lsegments->front()->m_y;
01496 if ( transform )
01497 m_lworld.TransformPoint( xp, yp, xp, yp );
01498 a2dCanvasObject* obj;
01499 a2dVertexList::iterator iter = m_lsegments->begin();
01500 iter++;
01501 while( iter != m_lsegments->end() )
01502 {
01503 double x,y,xm,ym;
01504 a2dLineSegment* seg = *iter;
01505 x = seg->m_x; y = seg->m_y;
01506 if ( transform )
01507 m_lworld.TransformPoint( x, y, x, y );
01508 if ( seg->GetArc() )
01509 {
01510 a2dArcSegment* cseg = (a2dArcSegment*) seg;
01511 xm = cseg->m_x2; ym = cseg->m_y2;
01512 if ( transform )
01513 m_lworld.TransformPoint( xm, ym, xm, ym );
01514 a2dArc* arc = new a2dArc();
01515 arc->SetChord( true );
01516 obj = arc;
01517 arc->Set( xp, yp, xm, ym, x, y );
01518 linesAnArcs->push_back( arc );
01519 }
01520 else
01521 {
01522 a2dSLine* line = new a2dSLine( xp, yp, x, y );
01523 obj = line;
01524 linesAnArcs->push_back( line );
01525 }
01526
01527 obj->SetStroke( this->GetStroke() );
01528 obj->SetFill( this->GetFill() );
01529 obj->SetLayer( m_layer );
01530 obj->SetContourWidth( GetContourWidth() );
01531 obj->SetCanvasDocument( m_root );
01532
01533 xp = x;
01534 yp = y;
01535 ++iter;
01536 }
01537
01538 return linesAnArcs;
01539 }
01540
01541 a2dBoundingBox a2dPolylineL::DoGetUnTransformedBbox( a2dBboxFlags WXUNUSED(flags) ) const
01542 {
01543 a2dBoundingBox bbox;
01544 if ( m_spline )
01545 {
01546 a2dVertexList* lpoints = new a2dVertexList();
01547
01548 *lpoints = *m_lsegments;
01549 lpoints->ConvertIntoSplinedPolygon(10);
01550 bbox = lpoints->GetBbox();
01551 delete lpoints;
01552 }
01553 else
01554 bbox = m_lsegments->GetBbox();
01555
01556 if (m_contourwidth > 0)
01557 bbox.Enlarge( m_contourwidth/2 );
01558
01559 if (m_begin )
01560 {
01561 a2dVertexList::iterator iter = m_lsegments->begin();
01562 a2dPoint2D point1 = GetPosXY();
01563 a2dPoint2D point2 = GetPosXY();
01564 if ( iter != m_lsegments->end() )
01565 {
01566 point1 = (*iter)->GetPoint();
01567 iter++;
01568 if ( iter != m_lsegments->end() )
01569 point2 = (*iter)->GetPoint();
01570 else
01571 point2 = point1;
01572 }
01573
01574 double dx, dy;
01575 dx = point2.m_x - point1.m_x;
01576 dy = point2.m_y - point1.m_y;
01577 double ang1;
01578 if (!dx && !dy)
01579 ang1=0;
01580 else
01581 ang1 = wxRadToDeg(atan2(dy,dx));
01582
01583 a2dAffineMatrix lworld;
01584
01585 lworld.Scale(m_xscale,m_yscale,0,0);
01586 lworld.Rotate(-ang1);
01587 lworld.Translate(point1.m_x,point1.m_y);
01588
01589 bbox.Expand( m_begin->GetMappedBbox( lworld) );
01590
01591 }
01592
01593 if (m_end )
01594 {
01595 double dx = 0;
01596 double dy = 0;
01597 a2dVertexList::reverse_iterator iter = m_lsegments->rbegin();
01598 a2dPoint2D point1 = GetPosXY();
01599 a2dPoint2D point2 = GetPosXY();
01600 if ( iter != m_lsegments->rend() )
01601 {
01602 point1 = (*iter)->GetPoint();
01603 while (!dx && !dy && iter != m_lsegments->rend() )
01604 {
01605 point1 = (*iter)->GetPoint();
01606 iter++;
01607 if ( iter != m_lsegments->rend() )
01608 point2 = (*iter)->GetPoint();
01609 else
01610 point2 = point1;
01611 dx = point2.m_x - point1.m_x;
01612 dy = point2.m_y - point1.m_y;
01613 }
01614 }
01615
01616 double ang2;
01617 if (!dx && !dy)
01618 ang2=0;
01619 else
01620 ang2 = wxRadToDeg(atan2(dy,dx));
01621
01622 a2dAffineMatrix tworld;
01623
01624 tworld.Scale(m_xscale,m_yscale,0,0);
01625 tworld.Rotate(-ang2);
01626 tworld.Translate(point1.m_x,point1.m_y);
01627
01628 bbox.Expand( m_end->GetMappedBbox(tworld) );
01629
01630 }
01631
01632 return bbox;
01633 }
01634
01635 bool a2dPolylineL::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
01636 {
01637 bool calc=false;
01638 if (m_begin)
01639 {
01640 calc = m_begin->Update( mode );
01641 }
01642 if (m_end)
01643 {
01644 calc = m_end->Update( mode );
01645 }
01646
01647 if ( !m_bbox.GetValid() || calc)
01648 {
01649
01650 if ( m_spline )
01651 {
01652 a2dVertexList* lpoints = new a2dVertexList();
01653
01654 *lpoints = *m_lsegments;
01655 lpoints->ConvertIntoSplinedPolygon(10);
01656 m_bbox = lpoints->GetBbox( m_lworld );
01657 delete lpoints;
01658 }
01659
01660 a2dBoundingBox bboxs = DoGetUnTransformedBbox();
01661 bboxs.MapBbox(m_lworld);
01662 m_bbox.Expand( bboxs );
01663
01664 if ( m_flags.m_editingCopy && m_spline )
01665 {
01666 m_spline = false;
01667 a2dBoundingBox bboxs = DoGetUnTransformedBbox();
01668 bboxs.MapBbox(m_lworld);
01669 m_bbox.Expand( bboxs );
01670 m_spline = true;
01671 }
01672
01673 return true;
01674 }
01675 return false;
01676 }
01677
01678 void a2dPolylineL::DoRender( a2dIterC& ic, OVERLAP clipparent )
01679 {
01680 if ( m_contourwidth )
01681 {
01682
01683 if ( m_pathtype == a2dPATH_END_ROUND )
01684 {
01685 a2dVertexList contourpoints = *m_lsegments;
01686 contourpoints.ConvertToLines();
01687
01688 a2dLineSegment* segprev = NULL;
01689 a2dLineSegment* seg = NULL;
01690 a2dPoint2D first;
01691 a2dPoint2D second;
01692 a2dPoint2D offsetpoint;
01693
01694 a2dVertexList::iterator iter = contourpoints.begin();
01695 while( iter != contourpoints.end() )
01696 {
01697 a2dVertexArray poly;
01698 a2dLineSegment* seg = *iter;
01699 seg = ( *iter );
01700
01701 if ( segprev )
01702 {
01703 first = a2dPoint2D( segprev->m_x, segprev->m_y );
01704 second = a2dPoint2D( seg->m_x, seg->m_y );
01705
01706 if ( first != second )
01707 {
01708 ic.GetDrawer2D()->DrawCircle( first.m_x, first.m_y, m_contourwidth/2 );
01709 a2dLine line1( first, second );
01710 line1.CalculateLineParameters();
01711 offsetpoint = first;
01712 line1.Virtual_Point( offsetpoint, -m_contourwidth/2 );
01713 poly.push_back( new a2dLineSegment( offsetpoint ) );
01714 offsetpoint = first;
01715 line1.Virtual_Point( offsetpoint, m_contourwidth/2 );
01716 poly.push_back( new a2dLineSegment( offsetpoint ) );
01717 offsetpoint = second;
01718 line1.Virtual_Point( offsetpoint, m_contourwidth/2 );
01719 poly.push_back( new a2dLineSegment( offsetpoint ) );
01720 offsetpoint = second;
01721 line1.Virtual_Point( offsetpoint, -m_contourwidth/2 );
01722 poly.push_back( new a2dLineSegment( offsetpoint ) );
01723 ic.GetDrawer2D()->DrawPolygon( &poly );
01724 }
01725 }
01726 iter++;
01727 segprev = seg;
01728 }
01729 ic.GetDrawer2D()->DrawCircle( second.m_x, second.m_y, m_contourwidth/2 );
01730 }
01731 else
01732 {
01733 a2dVertexList* contourpoints = m_lsegments->ConvertToContour( m_contourwidth/2, m_pathtype );
01734 ic.GetDrawer2D()->DrawPolygon( contourpoints, m_spline );
01735 delete contourpoints;
01736 }
01737 }
01738 else
01739 ic.GetDrawer2D()->DrawLines( m_lsegments, m_spline );
01740
01741 if ( m_flags.m_editingCopy && m_spline )
01742 {
01743 ic.GetDrawer2D()->OverRuleFixedStyle();
01744
01745 a2dBoundingBox untrans = DoGetUnTransformedBbox();
01746 double x,y,w,h;
01747 x = untrans.GetMinX();
01748 y = untrans.GetMinY();
01749 w = untrans.GetWidth();
01750 h = untrans.GetHeight();
01751
01752 ic.GetDrawer2D()->DrawLines( m_lsegments, false );
01753
01754 a2dSmrtPtr<a2dRect> around = new a2dRect( x, y, w, h );
01755 around->SetIgnoreSetpending();
01756 around->SetCanvasDocument(m_root);
01757 around->Update( updatemask_force );
01758 around->SetStroke( *wxRED, 0, a2dSTROKE_DOT_DASH );
01759 around->SetFill( *a2dTRANSPARENT_FILL );
01760 around->Render( ic, _ON );
01761
01762 ic.GetDrawer2D()->ReStoreFixedStyle();
01763 }
01764
01765 if (m_begin)
01766 {
01767 a2dVertexList::iterator iter = m_lsegments->begin();
01768 a2dPoint2D point1 = GetPosXY();
01769 a2dPoint2D point2 = GetPosXY();
01770 if ( iter != m_lsegments->end() )
01771 {
01772 point1 = (*iter)->GetPoint();
01773 iter++;
01774 if ( iter != m_lsegments->end() )
01775 point2 = (*iter)->GetPoint();
01776 else
01777 point2 = point1;
01778 }
01779
01780 double dx, dy;
01781 dx = point2.m_x - point1.m_x;
01782 dy = point2.m_y - point1.m_y;
01783 double ang1;
01784 if (!dx && !dy)
01785 ang1=0;
01786 else
01787 ang1 = wxRadToDeg(atan2(dy,dx));
01788
01789 a2dAffineMatrix lworld;
01790
01791 lworld.Scale(m_xscale,m_yscale,0,0);
01792 lworld.Rotate(-ang1);
01793 lworld.Translate(point1.m_x,point1.m_y);
01794
01795 a2dIterCU cu( ic, lworld );
01796
01797 m_begin->Render( ic, clipparent );
01798 }
01799
01800 if (m_end)
01801 {
01802 double dx = 0;
01803 double dy = 0;
01804 a2dVertexList::reverse_iterator iter = m_lsegments->rbegin();
01805 a2dPoint2D point1 = GetPosXY();
01806 a2dPoint2D point2 = GetPosXY();
01807 if ( iter != m_lsegments->rend() )
01808 {
01809 point1 = (*iter)->GetPoint();
01810 while (!dx && !dy && iter != m_lsegments->rend() )
01811 {
01812 point1 = (*iter)->GetPoint();
01813 iter++;
01814 if ( iter != m_lsegments->rend() )
01815 point2 = (*iter)->GetPoint();
01816 else
01817 point2 = point1;
01818 dx = point2.m_x - point1.m_x;
01819 dy = point2.m_y - point1.m_y;
01820 }
01821 }
01822
01823 double ang2;
01824 if (!dx && !dy)
01825 ang2=0;
01826 else
01827 ang2 = wxRadToDeg(atan2(dy,dx));
01828
01829 a2dAffineMatrix tworld;
01830
01831 tworld.Scale(m_xscale,m_yscale,0,0);
01832 tworld.Rotate(-ang2);
01833 tworld.Translate(point1.m_x,point1.m_y);
01834
01835 a2dIterCU cu( ic, tworld );
01836
01837 m_end->Render( ic, clipparent );
01838 }
01839
01840 }
01841
01842 #if wxART2D_USE_CVGIO
01843 void a2dPolylineL::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
01844 {
01845 a2dPolygonL::DoSave( parent, out, xmlparts, towrite );
01846 if ( xmlparts == a2dXmlSer_attrib )
01847 {
01848 if (m_begin || m_end )
01849 {
01850 out.WriteAttribute( wxT("xscale"), m_xscale );
01851 out.WriteAttribute( wxT("yscale"), m_yscale );
01852 if ( m_begin )
01853 out.WriteAttribute( wxT("begin"), m_begin->GetUniqueSerializationId() );
01854 if ( m_end )
01855 out.WriteAttribute( wxT("end"), m_end->GetUniqueSerializationId() );
01856 }
01857 }
01858 else
01859 {
01860 if ( (m_begin && !m_begin->GetCheck()) ||
01861 (m_end && !m_end->GetCheck())
01862 )
01863 {
01864
01865 a2dCanvasObjectPtr begin = m_begin;
01866 a2dCanvasObjectPtr end = m_end;
01867
01868 out.WriteStartElement( wxT("derived") );
01869
01870 if ( m_begin && !m_begin->GetCheck() )
01871 m_begin->Save( this, out, towrite);
01872 if (m_end && !m_end->GetCheck() )
01873 m_end->Save( this, out, towrite);
01874
01875 out.WriteEndElement();
01876 }
01877 }
01878 }
01879
01880 void a2dPolylineL::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
01881 {
01882 a2dPolygonL::DoLoad( parent, parser, xmlparts );
01883 if ( xmlparts == a2dXmlSer_attrib )
01884 {
01885 m_xscale = parser.GetAttributeValueDouble( wxT("xscale") );
01886 m_yscale = parser.GetAttributeValueDouble( wxT("yscale") );
01887
01888 wxString resolveKey;
01889 if ( parser.HasAttribute( wxT("begin") ) )
01890 {
01891 parser.ResolveOrAdd( (a2dSmrtPtr<class a2dObject>*) &m_begin, parser.GetAttributeValue( wxT("begin") ) );
01892 }
01893 if ( parser.HasAttribute( wxT("end") ) )
01894 {
01895 parser.ResolveOrAdd( (a2dSmrtPtr<class a2dObject>*) &m_end, parser.GetAttributeValue( wxT("end") ) );
01896 }
01897 }
01898 else
01899 {
01900 if ( parser.GetTagName() != wxT("derived") )
01901 return;
01902
01903 parser.Require( START_TAG, wxT("derived") );
01904 parser.Next();
01905
01906 DoLoadOneObject( this, parser, xmlparts );
01907 DoLoadOneObject( this, parser, xmlparts );
01908
01909 parser.Require( END_TAG, wxT("derived") );
01910 parser.Next();
01911 }
01912 }
01913 #endif //wxART2D_USE_CVGIO
01914
01915 void a2dPolylineL::DoWalker( wxObject* parent, a2dWalkerIOHandler& handler )
01916 {
01917 handler.WalkTask( parent, this, a2dWalker_a2dDerivedCanvasObjectStart );
01918 a2dPolygonL::DoWalker( parent, handler );
01919 if (m_begin)
01920 m_begin->Walker( this, handler );
01921
01922 if (m_end)
01923 m_end->Walker( this, handler );
01924
01925 handler.WalkTask( parent, this, a2dWalker_a2dDerivedCanvasObjectEnd );
01926 }
01927
01928 bool a2dPolylineL::DoIsHitWorld( a2dIterC& ic, a2dHitEvent& hitEvent )
01929 {
01930 a2dPoint2D P=a2dPoint2D(hitEvent.m_relx, hitEvent.m_rely);
01931 double pw = ic.GetWorldStrokeExtend();
01932 double margin = ic.GetTransformedHitMargin();
01933
01934 hitEvent.m_how = PointOnPolyline( P, pw + margin + m_contourwidth/2 );
01935
01936 if( hitEvent.m_how.IsHit() )
01937 return true;
01938
01939 bool ishit = false;
01940
01941 if (m_begin)
01942 {
01943 a2dVertexList::iterator iter = m_lsegments->begin();
01944 a2dPoint2D point1;
01945 a2dPoint2D point2;
01946 if ( iter != m_lsegments->end() )
01947 {
01948 point1 = (*iter)->GetPoint();
01949 iter++;
01950 if ( iter != m_lsegments->end() )
01951 point2 = (*iter)->GetPoint();
01952 else
01953 point2 = point1;
01954 }
01955
01956 double dx, dy;
01957 dx=point2.m_x - point1.m_x;
01958 dy=point2.m_y - point1.m_y;
01959 double ang1;
01960 if (!dx && !dy)
01961 ang1=0;
01962 else
01963 ang1 = wxRadToDeg(atan2(dy,dx));
01964
01965 a2dAffineMatrix lworld;
01966
01967 lworld.Scale(m_xscale,m_yscale,0,0);
01968 lworld.Rotate(-ang1);
01969 lworld.Translate(point1.m_x, point1.m_y);
01970 a2dIterCU cu( ic, lworld );
01971 if( m_begin->IsHitWorld( ic, hitEvent ) != 0 )
01972 {
01973
01974
01975 hitEvent.m_how.m_hit = hitEvent.m_how.m_hit | a2dHit::hit_member;
01976 hitEvent.m_how.m_stroke1 = a2dHit::stroke1_outside;
01977 hitEvent.m_how.m_stroke2 = a2dHit::stroke2_vertex;
01978 hitEvent.m_how.m_index = 0;
01979 ishit = true;
01980 }
01981 }
01982
01983 if (m_end && ( !ishit || ( hitEvent.m_option & a2dCANOBJHITOPTION_ALL ) ) )
01984 {
01985 a2dVertexList::reverse_iterator iter = m_lsegments->rbegin();
01986 a2dPoint2D point1 = GetPosXY();
01987 a2dPoint2D point2 = GetPosXY();
01988 double dx = 0;
01989 double dy = 0;
01990 if ( iter != m_lsegments->rend() )
01991 {
01992 point1 = (*iter)->GetPoint();
01993 while (!dx && !dy && iter != m_lsegments->rend() )
01994 {
01995 point1 = (*iter)->GetPoint();
01996 iter++;
01997 if ( iter != m_lsegments->rend() )
01998 point2 = (*iter)->GetPoint();
01999 else
02000 point2 = point1;
02001 dx=point2.m_x - point1.m_x;
02002 dy=point2.m_y - point1.m_y;
02003 }
02004 }
02005 double ang2;
02006 if (!dx && !dy)
02007 ang2=0;
02008 else
02009 ang2 = wxRadToDeg(atan2(dy,dx));
02010
02011 a2dAffineMatrix tworld;
02012
02013 tworld.Scale(m_xscale,m_yscale,0,0);
02014 tworld.Rotate(-ang2);
02015 tworld.Translate(point1.m_x, point1.m_y);
02016 a2dIterCU cu( ic, tworld );
02017 if ( m_end->IsHitWorld( ic, hitEvent ) != 0 )
02018 {
02019
02020 hitEvent.m_how.m_hit = hitEvent.m_how.m_hit | a2dHit::hit_member;
02021 hitEvent.m_how.m_stroke1 = a2dHit::stroke1_outside;
02022 hitEvent.m_how.m_stroke2 = a2dHit::stroke2_vertex;
02023 hitEvent.m_how.m_index = m_lsegments->size()-1;
02024 ishit = true;
02025 }
02026 }
02027
02028 return hitEvent.m_how.IsHit();
02029 }
02030
02031 a2dHit a2dPolylineL::PointOnPolyline(const a2dPoint2D& P, double margin)
02032 {
02033 a2dVertexList* rlist;
02034 if ( m_spline )
02035 {
02036
02037 a2dVertexList* lpoints = new a2dVertexList();
02038 a2dVertexList::iterator iter = m_lsegments->begin();
02039 while ( iter != m_lsegments->end() )
02040 {
02041 a2dLineSegment* point = (*iter)->Clone();
02042 lpoints->push_back(point);
02043 iter++;
02044 }
02045
02046 lpoints->ConvertIntoSplinedPolyline(10);
02047 rlist=lpoints;
02048 }
02049 else
02050 rlist=m_lsegments;
02051
02052 a2dHit result = rlist->HitTestPolyline( P, margin );
02053
02054 if ( m_spline )
02055 delete rlist;
02056
02057 return result;
02058 }
02059
02060 bool a2dPolylineL::DoCanConnectWith( a2dIterC &ic, a2dPin* pin, double WXUNUSED(margin), bool autocreate )
02061 {
02062 RemovePins( true, true );
02063
02064
02065 if( pin->GetParent() == this )
02066 return false;
02067
02068
02069 if ( a2dCanvasObject::PROPID_Editcopy->GetPropertyValue( this ) )
02070 return false;
02071
02072 if ( autocreate )
02073 {
02074
02075
02076 a2dHitEvent hitevent = a2dHitEvent( pin->GetAbsX(), pin->GetAbsY(), false );
02077 if( IsHitWorld( ic, hitevent ) )
02078 {
02079 bool found = false;
02080
02081 found = GeneratePins( pin->GetPinClass(), a2d_ObjectPinClass_ToConnectPinClassWire_InOut, pin->GetPosX(), pin->GetPosY() ) || found;
02082 return found;
02083 }
02084 }
02085 return false;
02086 }
02087
02088 bool a2dPolylineL::GeneratePins( a2dPinClass* toConnectTo, a2dConnectTask task, double x, double y )
02089 {
02090 a2dPinClass* toCreate;
02091 if ( GetGeneratePins() && (toCreate = toConnectTo->GetPinClassForTask( task, this )) )
02092 {
02093 m_flags.m_visiblechilds = true;
02094 bool end = false;
02095 bool begin = false;
02096 if ( !HasPinNamed( wxT("begin")) )
02097 {
02098 a2dVertexList::iterator iter = m_lsegments->begin();
02099 assert( m_lsegments->size() );
02100 AddPin( wxT("begin"), (*iter)->m_x, (*iter)->m_y, a2dPin::temporaryObjectPin, toCreate );
02101 }
02102 else
02103 begin = true;
02104
02105 if ( !HasPinNamed( wxT("end")) )
02106 {
02107 a2dVertexList::iterator iter = m_lsegments->end();
02108 assert( m_lsegments->size() );
02109 iter--;
02110 AddPin( wxT("end"), (*iter)->m_x, (*iter)->m_y, a2dPin::temporaryObjectPin, toCreate );
02111 }
02112 else
02113 end = true;
02114
02115 if ( m_lsegments->size() > 0 )
02116 {
02117
02118 double xNear, yNear;
02119 if( FindNearPoint( &m_lworld, x, y, &xNear, &yNear ) )
02120 {
02121 a2dAffineMatrix inverse = m_lworld;
02122 inverse.Invert();
02123 double xNearLocal, yNearLocal;
02124 inverse.TransformPoint( xNear, yNear, xNearLocal, yNearLocal );
02125
02126
02127 a2dPin *pin = AddPin( wxT("dynamic"), xNearLocal, yNearLocal, a2dPin::temporaryObjectPin | a2dPin::dynamic, toCreate );
02128 pin->SetMode( a2dPin::sm_PinCanConnectToPinClass );
02129 pin->SetMouseInObject( true );
02130 }
02131 }
02132
02133 wxASSERT( HasPins() );
02134 m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT("a2dPin") );
02135
02136 return true;
02137 }
02138 return false;
02139 }
02140
02141 bool a2dPolylineL::FindNearPoint( const a2dAffineMatrix *cworld, double xIn, double yIn, double *xOut, double *yOut )
02142 {
02143 if( GetNumberOfSegments()<2 )
02144 return false;
02145
02146 a2dAffineMatrix tworld;
02147 if( cworld )
02148 {
02149 tworld = *cworld;
02150 tworld *= m_lworld;
02151 }
02152 a2dAffineMatrix inverse = tworld;
02153 inverse.Invert();
02154
02155 double xh,yh;
02156 inverse.TransformPoint( xIn, yIn, xh, yh );
02157
02158 double dist;
02159 double minDist = DBL_MAX;
02160
02161 a2dPoint2D p=a2dPoint2D( xh, yh );
02162 a2dPoint2D p1,p2,pBest;
02163
02164
02165 a2dVertexList* rlist;
02166 if( m_spline )
02167 rlist = m_lsegments->ConvertSplinedPolyline(10);
02168 else
02169 rlist=m_lsegments;
02170
02171
02172 a2dVertexList::iterator iter = rlist->begin();
02173 p2 = (*iter)->GetPoint();
02174 while( iter != rlist->end() )
02175 {
02176 p1 = p2;
02177 iter++;
02178 if ( iter == rlist->end() ) break;
02179 p2 = (*iter)->GetPoint();
02180
02181 a2dLine line(p1,p2);
02182 a2dPoint2D pBestLine;
02183 dist = line.PointDistance( p, &pBestLine );
02184 if( dist < minDist )
02185 {
02186 minDist = dist;
02187 pBest = pBestLine;
02188 }
02189 }
02190
02191
02192 if ( m_spline )
02193 delete rlist;
02194
02195
02196 tworld.TransformPoint( pBest.m_x, pBest.m_y, *xOut, *yOut );
02197
02198 return true;
02199 }
02200
02201 bool a2dPolylineL::FindNearPointOrtho( const a2dAffineMatrix *cworld, double xIn, double yIn, double *xOut, double *yOut )
02202 {
02203 if( GetNumberOfSegments()<2 )
02204 return false;
02205
02206 bool result = false;
02207
02208 a2dAffineMatrix tworld;
02209 if( cworld )
02210 {
02211 tworld = *cworld;
02212 tworld *= m_lworld;
02213 }
02214 a2dAffineMatrix inverse = tworld;
02215 inverse.Invert();
02216
02217 double xh,yh;
02218 inverse.TransformPoint( xIn, yIn, xh, yh );
02219
02220 double dist;
02221 double minDist = DBL_MAX;
02222
02223 a2dPoint2D p=a2dPoint2D( xh, yh );
02224 a2dPoint2D p1,p2,pBest;
02225
02226
02227 a2dVertexList* rlist;
02228 if( m_spline )
02229 rlist = m_lsegments->ConvertSplinedPolyline(10);
02230 else
02231 rlist=m_lsegments;
02232
02233
02234 a2dVertexList::iterator iter = rlist->begin();
02235 p2 = (*iter)->GetPoint();
02236 while( iter != rlist->end() )
02237 {
02238 p1 = p2;
02239 iter++;
02240 if ( iter == rlist->end() ) break;
02241 p2 = (*iter)->GetPoint();
02242
02243 a2dLine line(p1,p2);
02244 a2dPoint2D pBestLine;
02245 dist = line.PointDistanceOrhto( p, &pBestLine );
02246 if( dist < minDist )
02247 {
02248 minDist = dist;
02249 pBest = pBestLine;
02250 result = true;
02251 }
02252 }
02253
02254
02255 if ( m_spline )
02256 delete rlist;
02257
02258
02259 tworld.TransformPoint( pBest.m_x, pBest.m_y, *xOut, *yOut );
02260
02261 return result;
02262 }
02263
02264 bool a2dPolylineL::MoveDynamicPinCloseTo( a2dPin *pin, const a2dPoint2D &point, bool final )
02265 {
02266 wxASSERT( pin );
02267 wxASSERT( pin->IsDynamicPin() );
02268 wxASSERT( pin->GetParent() == this );
02269
02270 a2dPoint2D pointLocal;
02271 a2dAffineMatrix trns = pin->GetParent()->GetTransformMatrix();
02272 trns.Invert();
02273 trns.TransformPoint( point, &pointLocal );
02274
02275 double xNew, yNew, xNewO, yNewO;
02276 bool orthook = FindNearPointOrtho( 0, pointLocal.m_x, pointLocal.m_y, &xNewO, &yNewO );
02277 bool straightok = FindNearPoint( 0, pointLocal.m_x, pointLocal.m_y, &xNew, &yNew );
02278
02279 if(
02280 orthook && PointDistSqr( pointLocal.m_x, pointLocal.m_y, xNewO, yNewO ) < PointDistSqr( pointLocal.m_x, pointLocal.m_y, xNew, yNew )*4 ||
02281 orthook && !straightok
02282 )
02283 {
02284 xNew = xNewO;
02285 yNew = yNewO;
02286 }
02287
02288 a2dPoint2D pos = pin->GetPosXY();
02289
02290 if( ( xNew != pos.m_x || yNew != pos.m_y ) && ( orthook || straightok ) )
02291 {
02292 m_root->GetCommandProcessor()->Submit( new a2dCommand_SetCanvasProperty( pin, PROPID_Position, a2dPoint2D( xNew, yNew ), -1, false ), final );
02293 return true;
02294 }
02295 return false;
02296 }
02297
02298 a2dPin *a2dPolylineL::FindBeginPin()
02299 {
02300 return HasPinNamed( wxT("begin") );
02301 }
02302
02303 a2dPin *a2dPolylineL::FindEndPin()
02304 {
02305 return HasPinNamed( wxT("end") );
02306 }
02307
02308 a2dPin *a2dPolylineL::FindPin( int *i )
02309 {
02310 switch(*i)
02311 {
02312 case 0:
02313 {
02314 a2dPin *pin = FindBeginPin();
02315 (*i)++;
02316 if( pin ) return pin;
02317 }
02318
02319 case 1:
02320 {
02321 a2dPin *pin = FindEndPin();
02322 (*i)++;
02323 if( pin ) return pin;
02324 }
02325
02326 default:
02327 return 0;
02328 }
02329 }
02330
02331
02332
02333
02334
02335 a2dPolygonLClipper::a2dPolygonLClipper( a2dBoundingBox& bbox )
02336 : a2dPolygonL()
02337 {
02338 if ( &bbox != &wxNonValidBbox )
02339 {
02340 AddPoint( bbox.GetMinX(), bbox.GetMinY() );
02341 AddPoint( bbox.GetMinX(), bbox.GetMaxY() );
02342 AddPoint( bbox.GetMaxX(), bbox.GetMaxY() );
02343 AddPoint( bbox.GetMaxX(), bbox.GetMinY() );
02344 }
02345
02346 m_spline = false;
02347 }
02348
02349 a2dPolygonLClipper::a2dPolygonLClipper( a2dVertexList* points, bool spline )
02350 : a2dPolygonL( points, spline )
02351 {
02352 }
02353
02354 a2dPolygonLClipper::~a2dPolygonLClipper()
02355 {
02356 }
02357
02358 void a2dPolygonLClipper::SetClippingFromBox( a2dBoundingBox& bbox )
02359 {
02360 Clear();
02361 if ( &bbox != &wxNonValidBbox )
02362 {
02363 AddPoint( bbox.GetMinX(), bbox.GetMinY() );
02364 AddPoint( bbox.GetMinX(), bbox.GetMaxY() );
02365 AddPoint( bbox.GetMaxX(), bbox.GetMaxY() );
02366 AddPoint( bbox.GetMaxX(), bbox.GetMinY() );
02367 }
02368 }
02369
02370 a2dObject* a2dPolygonLClipper::Clone( CloneOptions options ) const
02371 {
02372 return new a2dPolygonLClipper( *this, options );
02373 };
02374
02375 a2dPolygonLClipper::a2dPolygonLClipper( const a2dPolygonLClipper &other, CloneOptions options )
02376 : a2dPolygonL(other, options)
02377 {
02378 }
02379
02380 void a2dPolygonLClipper::Render( a2dIterC& ic, OVERLAP clipparent )
02381 {
02382 if ( m_lsegments->size() )
02383 {
02384 a2dIterCU cu( ic, m_ClipLworld );
02385
02386
02387 ic.GetDrawer2D()->DrawPolygon( m_lsegments, m_spline, wxWINDING_RULE);
02388 ic.GetDrawer2D()->ExtendAndPushClippingRegion( m_lsegments, m_spline, wxWINDING_RULE, a2dCLIP_AND );
02389 }
02390
02391 a2dCanvasObject::Render( ic, clipparent );
02392
02393 if ( m_lsegments->size() )
02394 ic.GetDrawer2D()->PopClippingRegion();
02395 }
02396
02397 bool a2dPolygonLClipper::Update( UpdateMode mode )
02398 {
02399 a2dCanvasObject::Update( mode );
02400
02401 m_bbox = DoGetUnTransformedBbox();
02402 m_bbox.MapBbox(m_ClipLworld);
02403
02404 if ( m_flags.m_editingCopy && m_spline )
02405 {
02406 m_spline = false;
02407 a2dBoundingBox bboxs = DoGetUnTransformedBbox();
02408 bboxs.MapBbox(m_ClipLworld);
02409 m_bbox.Expand( bboxs );
02410 m_spline = true;
02411 }
02412
02413 return false;
02414 }
02415
02416 void a2dPolygonLClipper::DoRender( a2dIterC& WXUNUSED(ic), OVERLAP WXUNUSED(clipparent) )
02417 {
02418 if ( m_flags.m_editingCopy )
02419 {
02420
02421 }
02422 }
02423
02424 void a2dPolygonLClipper::SetClippingTransformMatrix( const a2dAffineMatrix& mat )
02425 {
02426 m_ClipLworld = mat; SetPending(true);
02427 }
02428
02429
02430
02431
02432
02433 a2dPolygonLClipper2::a2dPolygonLClipper2( a2dBoundingBox& bbox )
02434 : a2dPolygonL()
02435 {
02436 if ( &bbox != &wxNonValidBbox )
02437 {
02438 AddPoint( bbox.GetMinX(), bbox.GetMinY() );
02439 AddPoint( bbox.GetMinX(), bbox.GetMaxY() );
02440 AddPoint( bbox.GetMaxX(), bbox.GetMaxY() );
02441 AddPoint( bbox.GetMaxX(), bbox.GetMinY() );
02442 }
02443
02444 m_spline = false;
02445 }
02446
02447 a2dPolygonLClipper2::a2dPolygonLClipper2( a2dVertexList* points, bool spline )
02448 : a2dPolygonL( points, spline )
02449 {
02450 }
02451
02452 a2dPolygonLClipper2::~a2dPolygonLClipper2()
02453 {
02454 }
02455
02456 a2dObject* a2dPolygonLClipper2::Clone( CloneOptions options ) const
02457 {
02458 return new a2dPolygonLClipper2( *this, options );
02459 };
02460
02461 a2dPolygonLClipper2::a2dPolygonLClipper2( const a2dPolygonLClipper2 &other, CloneOptions options )
02462 : a2dPolygonL(other, options)
02463 {
02464 }
02465
02466 void a2dPolygonLClipper2::Render( a2dIterC& ic, OVERLAP clipparent )
02467 {
02468 if ( m_lsegments->size() )
02469 {
02470 a2dIterCU cu( ic, this );
02471
02472 if ( !m_flags.m_editingCopy )
02473 ic.GetDrawer2D()->ExtendAndPushClippingRegion( m_lsegments, m_spline, wxWINDING_RULE, a2dCLIP_AND );
02474 }
02475
02476 a2dCanvasObject::Render( ic, clipparent );
02477
02478 if ( m_lsegments->size() )
02479 if ( !m_flags.m_editingCopy )
02480 ic.GetDrawer2D()->PopClippingRegion();
02481 }
02482
02483 bool a2dPolygonLClipper2::Update( UpdateMode mode )
02484 {
02485 a2dCanvasObject::Update( mode );
02486
02487 m_bbox = DoGetUnTransformedBbox();
02488 m_bbox.MapBbox(m_lworld);
02489
02490 if ( m_flags.m_editingCopy && m_spline )
02491 {
02492 m_spline = false;
02493 a2dBoundingBox bboxs = DoGetUnTransformedBbox();
02494 bboxs.MapBbox(m_lworld);
02495 m_bbox.Expand( bboxs );
02496 m_spline = true;
02497 }
02498
02499 return false;
02500 }
02501
02502 void a2dPolygonLClipper2::DoRender( a2dIterC& ic, OVERLAP WXUNUSED(clipparent) )
02503 {
02504
02505 {
02506 ic.GetDrawer2D()->DrawPolygon( m_lsegments, m_spline, wxWINDING_RULE);
02507 }
02508 }
02509
02510
02511
02512
02513
02514 a2dPropertyIdDouble* a2dPolyHandleL::PROPID_tmpXIH = NULL;
02515 a2dPropertyIdDouble* a2dPolyHandleL::PROPID_tmpYIH = NULL;
02516 a2dPropertyIdDouble* a2dPolyHandleL::PROPID_tmpXIV1 = NULL;
02517 a2dPropertyIdDouble* a2dPolyHandleL::PROPID_tmpYIV1 = NULL;
02518 a2dPropertyIdDouble* a2dPolyHandleL::PROPID_tmpXIV2 = NULL;
02519 a2dPropertyIdDouble* a2dPolyHandleL::PROPID_tmpYIV2 = NULL;
02520
02521 INITIALIZE_PROPERTIES( a2dPolyHandleL, a2dHandle )
02522 {
02523 A2D_PROPID_D_F( a2dPropertyIdDouble, tmpXIH, 0, a2dPropertyId::flag_temporary );
02524 A2D_PROPID_D_F( a2dPropertyIdDouble, tmpYIH, 0, a2dPropertyId::flag_temporary );
02525 A2D_PROPID_D_F( a2dPropertyIdDouble, tmpXIV1, 0, a2dPropertyId::flag_temporary );
02526 A2D_PROPID_D_F( a2dPropertyIdDouble, tmpYIV1, 0, a2dPropertyId::flag_temporary );
02527 A2D_PROPID_D_F( a2dPropertyIdDouble, tmpXIV2, 0, a2dPropertyId::flag_temporary );
02528 A2D_PROPID_D_F( a2dPropertyIdDouble, tmpYIV2, 0, a2dPropertyId::flag_temporary );
02529 return true;
02530 }
02531
02532 a2dPolyHandleL::a2dPolyHandleL()
02533 : a2dHandle( NULL, 0,0, wxT("dummy"), a2dCanvasGlobals->GetHandle()->GetWidth(), a2dCanvasGlobals->GetHandle()->GetHeight())
02534 {
02535 m_arcHandle = false;
02536 m_lsegments = NULL;
02537 m_lsegmentsOrg = NULL;
02538 }
02539
02540 a2dPolyHandleL::a2dPolyHandleL( a2dPolygonL* parent, a2dVertexList::iterator segNode, a2dVertexList::iterator segNodeOrg,
02541 a2dSmrtPtr<a2dVertexList> lsegments,
02542 a2dSmrtPtr<a2dVertexList> lsegmentsOrg,
02543 const wxString& name )
02544 : a2dHandle( parent, (*segNode)->m_x, (*segNode)->m_y, name )
02545 {
02546 m_segNode = segNode;
02547 m_segNodeOrg = segNodeOrg;
02548 m_lsegments = lsegments;
02549 m_lsegmentsOrg = lsegmentsOrg;
02550 m_arcHandle = false;
02551 }
02552
02553 a2dPolyHandleL::a2dPolyHandleL( a2dPolygonL* parent, a2dVertexList::iterator segNode, a2dVertexList::iterator segNodeOrg,
02554 a2dSmrtPtr<a2dVertexList> lsegments,
02555 a2dSmrtPtr<a2dVertexList> lsegmentsOrg,
02556 double xc, double yc, const wxString& name )
02557 : a2dHandle( parent, xc, yc, name )
02558 {
02559 m_segNode = segNode;
02560 m_segNodeOrg = segNodeOrg;
02561 m_lsegments = lsegments;
02562 m_lsegmentsOrg = lsegmentsOrg;
02563 m_arcHandle = false;
02564 }
02565
02566 a2dPolyHandleL::a2dPolyHandleL( const a2dPolyHandleL &other, CloneOptions options )
02567 : a2dHandle( other, options )
02568 {
02569 m_segNode = other.m_segNode;
02570 m_segNodeOrg = other.m_segNodeOrg;
02571 m_arcHandle = other.m_arcHandle;
02572 m_lsegments = other.m_lsegments;
02573 m_lsegmentsOrg = other.m_lsegmentsOrg;
02574 }
02575
02576 a2dPolyHandleL::~a2dPolyHandleL()
02577 {
02578 }
02579
02580
02581
02582
02583 IMPLEMENT_DYNAMIC_CLASS(a2dSurface, a2dPolygonL)
02584
02585 A2D_BEGIN_EVENT_TABLE( a2dSurface, a2dPolygonL )
02586 A2D_EVT_CANVASOBJECT_MOUSE_EVENT( a2dSurface::OnCanvasObjectMouseEvent )
02587 A2D_EVT_CANVASHANDLE_MOUSE_EVENT( a2dSurface::OnHandleEvent )
02588 A2D_EVT_CHAR( a2dSurface::OnChar )
02589 A2D_END_EVENT_TABLE()
02590
02591 a2dSurface::a2dSurface()
02592 : a2dPolygonL()
02593 {
02594 m_lsegments = new a2dVertexList();
02595 }
02596
02597 a2dSurface::a2dSurface( a2dVertexListPtr points, bool spline )
02598 : a2dPolygonL( points, spline )
02599 {
02600 }
02601
02602 a2dSurface::~a2dSurface()
02603 {
02604 }
02605
02606 void a2dSurface::Clear()
02607 {
02608 m_lsegments->clear();
02609 m_holes.clear();
02610 }
02611
02612 a2dSurface::a2dSurface( const a2dSurface& other, CloneOptions options )
02613 : a2dPolygonL( other, options )
02614 {
02615 for( a2dListOfa2dVertexList::const_iterator iterp = other.m_holes.begin(); iterp != other.m_holes.end(); iterp++ )
02616 {
02617 a2dVertexListPtr vlist = (*iterp);
02618 a2dVertexListPtr holepoints = new a2dVertexList();
02619 *holepoints = *vlist;
02620 m_holes.push_back( holepoints );
02621
02622 }
02623 }
02624
02625 a2dObject* a2dSurface::Clone( CloneOptions options ) const
02626 {
02627 return new a2dSurface( *this, options );
02628 };
02629
02630 a2dCanvasObjectList* a2dSurface::GetAsCanvasVpaths( bool transform )
02631 {
02632 a2dVpath* segments = m_lsegments->ConvertToVpath( true, true );
02633
02634 a2dVpathSegment* lastseg = &segments->Last();
02635 lastseg->SetClose( a2dPATHSEG_END_OPEN );
02636 a2dVpathSegment* segvec;
02637 for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
02638 {
02639 a2dVertexListPtr vlist = (*iterp);
02640 if ( vlist->size() > 1 )
02641 {
02642 a2dVertexList::iterator iter = vlist->begin();
02643 a2dLineSegmentPtr seg = *iter;
02644 segvec = new a2dVpathSegment( seg->m_x, seg->m_y, a2dPATHSEG_LINETO_NOSTROKE );
02645 segments->push_back(segvec);
02646
02647 while ( iter != vlist->end() )
02648 {
02649 a2dLineSegmentPtr seg = *iter;
02650 segvec = new a2dVpathSegment( seg->m_x, seg->m_y, a2dPATHSEG_LINETO );
02651 segments->push_back(segvec);
02652 iter++;
02653 }
02654 seg = *(vlist->begin());
02655 segvec = new a2dVpathSegment( seg->m_x, seg->m_y, a2dPATHSEG_LINETO );
02656 segments->push_back(segvec);
02657 segvec = new a2dVpathSegment( lastseg->m_x1, lastseg->m_y1, a2dPATHSEG_LINETO_NOSTROKE );
02658 segments->push_back(segvec);
02659 }
02660 }
02661 segvec->SetClose( a2dPATHSEG_END_CLOSED );
02662
02663 a2dVectorPath* canpath = new a2dVectorPath( segments );
02664 if ( transform )
02665 segments->Transform( m_lworld );
02666 canpath->SetStroke( this->GetStroke() );
02667 canpath->SetFill( this->GetFill() );
02668 canpath->SetLayer( m_layer );
02669 canpath->SetContourWidth( GetContourWidth() );
02670 a2dCanvasObjectList* canpathlist = new a2dCanvasObjectList();
02671 canpathlist->push_back( canpath );
02672
02673 return canpathlist;
02674 }
02675
02676 a2dCanvasObjectList* a2dSurface::GetAsLinesArcs( bool transform )
02677 {
02678 a2dCanvasObjectList* linesAnArcs = new a2dCanvasObjectList();
02679
02680 double xp = m_lsegments->back()->m_x;
02681 double yp = m_lsegments->back()->m_y;
02682 if ( transform )
02683 m_lworld.TransformPoint( xp, yp, xp, yp );
02684 a2dCanvasObject* obj;
02685 for( a2dVertexList::iterator iter = m_lsegments->begin(); iter != m_lsegments->end(); ++iter )
02686 {
02687 double x,y,xm,ym;
02688 a2dLineSegment* seg = *iter;
02689 x = seg->m_x; y = seg->m_y;
02690 if ( transform )
02691 m_lworld.TransformPoint( x, y, x, y );
02692 if ( seg->GetArc() )
02693 {
02694 a2dArcSegment* cseg = (a2dArcSegment*) seg;
02695 xm = cseg->m_x2; ym = cseg->m_y2;
02696 if ( transform )
02697 m_lworld.TransformPoint( xm, ym, xm, ym );
02698 a2dArc* arc = new a2dArc();
02699 arc->SetChord( true );
02700 obj = arc;
02701 arc->Set( xp, yp, xm, ym, x, y );
02702 linesAnArcs->push_back( arc );
02703 }
02704 else
02705 {
02706 a2dSLine* line = new a2dSLine( xp, yp, x, y );
02707 obj = line;
02708 linesAnArcs->push_back( line );
02709 }
02710
02711 obj->SetStroke( this->GetStroke() );
02712 obj->SetFill( this->GetFill() );
02713 obj->SetLayer( m_layer );
02714 obj->SetContourWidth( GetContourWidth() );
02715 obj->SetCanvasDocument( m_root );
02716
02717 xp = x;
02718 yp = y;
02719 }
02720
02721 return linesAnArcs;
02722 }
02723
02724 void a2dSurface::AddHole( a2dVertexListPtr holepoints )
02725 {
02726 m_holes.push_back( holepoints );
02727 }
02728
02729 void a2dSurface::RemoveRedundantPoints( a2dCanvasObject *sendCommandsTo )
02730 {
02731 a2dPolygonL::RemoveRedundantPoints( sendCommandsTo );
02732 }
02733
02734 bool a2dSurface::EliminateMatrix()
02735 {
02736 a2dPolygonL::EliminateMatrix();
02737 return a2dCanvasObject::EliminateMatrix();
02738 }
02739
02740 a2dBoundingBox a2dSurface::DoGetUnTransformedBbox( a2dBboxFlags WXUNUSED(flags) ) const
02741 {
02742 a2dBoundingBox bbox;
02743 if ( m_spline )
02744 {
02745 a2dVertexList* lpoints = new a2dVertexList();
02746
02747 *lpoints = *m_lsegments;
02748 lpoints->ConvertIntoSplinedPolygon(10);
02749 bbox = lpoints->GetBbox();
02750 delete lpoints;
02751 }
02752 else
02753 bbox = m_lsegments->GetBbox();
02754
02755 if (m_contourwidth > 0)
02756 bbox.Enlarge( m_contourwidth/2 );
02757
02758 return bbox;
02759 }
02760
02761 bool a2dSurface::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
02762 {
02763 if ( !m_bbox.GetValid())
02764 {
02765 if ( m_spline )
02766 {
02767 a2dVertexList* lpoints = new a2dVertexList();
02768
02769 *lpoints = *m_lsegments;
02770 lpoints->ConvertIntoSplinedPolygon(10);
02771 m_bbox = lpoints->GetBbox( m_lworld );
02772 delete lpoints;
02773 }
02774
02775 a2dBoundingBox bboxs = DoGetUnTransformedBbox();
02776 bboxs.MapBbox(m_lworld);
02777 m_bbox.Expand( bboxs );
02778
02779 if ( m_flags.m_editingCopy && m_spline )
02780 {
02781 m_spline = false;
02782 a2dBoundingBox bboxs = DoGetUnTransformedBbox();
02783 bboxs.MapBbox(m_lworld);
02784 m_bbox.Expand( bboxs );
02785 m_spline = true;
02786 }
02787 return true;
02788 }
02789 return false;
02790 }
02791
02792 void a2dSurface::DoRender( a2dIterC& ic, OVERLAP clipparent )
02793 {
02794
02795 a2dListOfa2dVertexList drawable;
02796 a2dLineSegmentPtr last = m_lsegments->front();
02797 m_lsegments->push_back( last );
02798 drawable.push_back( m_lsegments );
02799 for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
02800 {
02801 a2dVertexListPtr vlist = (*iterp);
02802 if ( vlist->size() > 1 )
02803 {
02804 a2dLineSegmentPtr last = vlist->front();
02805 vlist->push_back( last );
02806 drawable.push_back( vlist );
02807 }
02808 }
02809 ic.GetDrawer2D()->DrawPolyPolygon( drawable, wxWINDING_RULE );
02810 m_lsegments->pop_back();
02811 for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
02812 {
02813 a2dVertexListPtr vlist = (*iterp);
02814 if ( vlist->size() > 1 )
02815 {
02816 vlist->pop_back();
02817 }
02818 }
02819 }
02820
02821 #if wxART2D_USE_CVGIO
02822 void a2dSurface::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
02823 {
02824 a2dPolygonL::DoSave( parent, out, xmlparts, towrite );
02825 if ( xmlparts == a2dXmlSer_attrib )
02826 {
02827 out.WriteAttribute( wxT("holes"), m_holes.size() );
02828 }
02829 else
02830 {
02831 unsigned int i=0;
02832 for( a2dListOfa2dVertexList::iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
02833 {
02834 out.WriteStartElement( wxT("hole") );
02835 forEachIn( a2dVertexList, (*iterp).Get() )
02836 {
02837 if (i%6==0)
02838 out.WriteNewLine();
02839 a2dLineSegment* seg = *iter;
02840 out.WriteStartElementAttributes( wxT("xy") );
02841 out.WriteAttribute( wxT("x"), seg->m_x );
02842 out.WriteAttribute( wxT("y"), seg->m_y );
02843
02844 if ( seg->GetArc() )
02845 {
02846 a2dArcSegment* arc = (a2dArcSegment*) seg;
02847 out.WriteAttribute( wxT("xm"), arc->m_x2 );
02848 out.WriteAttribute( wxT("ym"), arc->m_y2 );
02849 }
02850
02851 out.WriteEndAttributes( true );
02852 i++;
02853 }
02854 out.WriteEndElement();
02855 }
02856
02857 }
02858 }
02859
02860 void a2dSurface::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
02861 {
02862 a2dPolygonL::DoLoad( parent, parser, xmlparts );
02863 if ( xmlparts == a2dXmlSer_attrib )
02864 {
02865 int holes = parser.GetAttributeValueBool( wxT("holes"), false );
02866 }
02867 else
02868 {
02869 while( parser.GetTagName() == wxT("hole") )
02870 {
02871 a2dVertexListPtr holepoints = new a2dVertexList();
02872 parser.Next();
02873 while( parser.GetTagName() == wxT("xy") )
02874 {
02875 double x = parser.GetAttributeValueDouble( wxT("x") );
02876 double y = parser.GetAttributeValueDouble( wxT("y") );
02877
02878 a2dLineSegment* seg;
02879 if ( parser.HasAttribute( wxT("xm") ) )
02880 {
02881 double xm = parser.GetAttributeValueDouble( wxT("xm") );
02882 double ym = parser.GetAttributeValueDouble( wxT("ym") );
02883
02884 seg = new a2dArcSegment( x, y, xm, ym );
02885 }
02886 else
02887 seg = new a2dLineSegment( x, y );
02888
02889 holepoints->push_back(seg);
02890
02891 parser.Next();
02892 parser.Require( END_TAG, wxT("xy") );
02893 parser.Next();
02894
02895 }
02896 parser.Require( END_TAG, wxT("hole") );
02897 parser.Next();
02898 AddHole( holepoints );
02899 }
02900 }
02901 }
02902 #endif //wxART2D_USE_CVGIO
02903
02904 bool a2dSurface::DoIsHitWorld( a2dIterC& ic, a2dHitEvent& hitEvent )
02905 {
02906 double xh,yh;
02907 ic.GetInverseTransform().TransformPoint(hitEvent.m_x,hitEvent.m_y,xh,yh);
02908
02909 a2dPoint2D P=a2dPoint2D(xh,yh);
02910 double pw = ic.GetWorldStrokeExtend();
02911 double margin = ic.GetTransformedHitMargin();
02912
02913 unsigned int indexn = m_lsegments->size() + 1;
02914 for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
02915 {
02916 a2dVertexListPtr vlist = (*iterp);
02917 hitEvent.m_how = vlist->HitTestPolygon( P, margin );
02918 if ( hitEvent.m_how.IsHit() )
02919 {
02920 hitEvent.m_how.m_index += indexn;
02921 return true;
02922 }
02923 indexn += vlist->size();
02924 indexn++;
02925 }
02926 if ( !hitEvent.m_how.IsHit() )
02927 hitEvent.m_how = PointInPolygon( P, pw + margin);
02928 return hitEvent.m_how.IsHit();
02929 }
02930
02931 bool a2dSurface::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
02932 {
02933 a2dPolygonL::DoStartEdit( editmode, editstyle );
02934 if ( m_flags.m_editable )
02935 {
02936 if ( editmode == 1 )
02937 {
02938 if( ! ( editstyle & wxEDITSTYLE_NOHANDLES ) )
02939 {
02940 m_flags.m_visiblechilds = true;
02941 m_flags.m_childrenOnSameLayer = true;
02942 a2dSurface* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dSurface );
02943
02944
02945 int index = 0;
02946 a2dListOfa2dVertexList::const_iterator iterporg = original->m_holes.begin();
02947 for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
02948 {
02949 a2dVertexListPtr vlist = (*iterp);
02950 a2dVertexListPtr vlistorg = (*iterporg);
02951 a2dVertexList::iterator iter = vlist->begin();
02952 a2dVertexList::iterator iterorg = vlistorg->begin();
02953 a2dLineSegment* seg;
02954 a2dLineSegment* nextseg;
02955 while ( iter != vlist->end() )
02956 {
02957 seg = (*iter);
02958 iter++;
02959 if ( iter != vlist->end() )
02960 nextseg = (*iter);
02961 else
02962 nextseg = vlist->front();
02963 iter--;
02964
02965
02966 a2dPolyHandleL* handle = new a2dPolyHandleL( this, iter, iterorg, vlist, vlistorg, wxT("__indexhole__") );
02967 Append(handle);
02968 handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
02969 handle->SetLayer( m_layer );
02970 if ( seg->GetArc() )
02971 {
02972
02973 a2dArcSegment* cseg = (a2dArcSegment*) seg;
02974
02975 handle = new a2dPolyHandleL( this, iter, iterorg, vlist, vlistorg, cseg->m_x2, cseg->m_y2, wxT("__indexhole_arc__") );
02976 handle->SetLayer( m_layer );
02977 Append(handle);
02978 handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
02979 }
02980 index++;
02981 iter++;
02982 iterorg++;
02983 }
02984 iterporg++;
02985 }
02986
02987 m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT("a2dPolyHandleL") );
02988 m_flags.m_editingCopy = true;
02989
02990
02991
02992 Update( updatemask_force );
02993
02994 SetPending( true );
02995 }
02996 return true;
02997 }
02998 else
02999 {
03000 PROPID_Allowrotation->SetPropertyToObject( this, true );
03001 PROPID_Allowskew->SetPropertyToObject( this, true );
03002
03003 return a2dCanvasObject::DoStartEdit( editmode, editstyle );
03004 }
03005 }
03006
03007 return false;
03008 }
03009
03010 void a2dSurface::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
03011 {
03012 if ( !m_flags.m_editingCopy || !m_flags.m_editable )
03013 {
03014 event.Skip();
03015 return;
03016 }
03017
03018 a2dIterC* ic = event.GetIterC();
03019
03020 a2dPolyHandleL* seghandle;
03021
03022 double xw,yw;
03023 xw = event.GetX();
03024 yw = event.GetY();
03025
03026 a2dSurface* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dSurface );
03027
03028 if ( event.GetMouseEvent().LeftDown() )
03029 {
03030 a2dRestrictionEngine *restrictEngine = a2dCanvasGlobals->GetRestrictionEngine();
03031 if (restrictEngine )
03032 restrictEngine->SetRestrictPoint( xw, yw );
03033
03034 if ( event.GetHow().IsEdgeHit() )
03035 {
03036 int index = event.GetHow().m_index;
03037 a2dVertexList::iterator iterSeg = GetSegmentAtIndex( index );
03038 a2dVertexList::iterator iterSegOrg = original->GetSegmentAtIndex( index );
03039 a2dVertexList* vlist = GetSegmentListAtIndex( index );
03040 if ( vlist == m_lsegments )
03041 {
03042 event.Skip();
03043 return;
03044 }
03045 a2dVertexList* vlistorg = original->GetSegmentListAtIndex( index );
03046 if ( event.GetMouseEvent().AltDown() )
03047 seghandle = new a2dPolyHandleL( this, iterSeg, iterSegOrg, vlist, vlistorg, wxT("__inserthole__") );
03048 else
03049 seghandle = new a2dPolyHandleL( this, iterSeg, iterSegOrg, vlist, vlistorg, wxT("__segmenthole__") );
03050 seghandle->SetLayer( m_layer );
03051 Append(seghandle);
03052 ic->SetCorridorPath( true, seghandle );
03053 seghandle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
03054
03055 a2dHandleMouseEvent handleEvent( ic, seghandle, xw, yw, event.GetMouseEvent() );
03056 ProcessEvent( handleEvent );
03057 }
03058 else
03059 event.Skip();
03060 }
03061 else
03062 event.Skip();
03063 }
03064
03065 void a2dSurface::OnHandleEvent(a2dHandleMouseEvent &event)
03066 {
03067 a2dIterC* ic = event.GetIterC();
03068
03069 if ( event.GetCanvasHandle()->GetRelease() )
03070 return;
03071
03072 if ( m_flags.m_editingCopy )
03073 {
03074 a2dPolyHandleL* draghandle = wxDynamicCast( event.GetCanvasHandle(), a2dPolyHandleL );
03075 if ( draghandle->GetName() != wxT("__indexhole__") &&
03076 draghandle->GetName() != wxT("__indexhole_arc__") &&
03077 draghandle->GetName() != wxT("__inserthole__") &&
03078 draghandle->GetName() != wxT("__segmenthole__")
03079 )
03080 {
03081 event.Skip();
03082 return;
03083 }
03084
03085 a2dRestrictionEngine *restrictEngine = a2dCanvasGlobals->GetRestrictionEngine();
03086 wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
03087
03088 if ( editmode == 1 )
03089 {
03090 double xw,yw;
03091 xw = event.GetX();
03092 yw = event.GetY();
03093 a2dAffineMatrix atWorld = ic->GetTransform();
03094
03095
03096
03097
03098 a2dAffineMatrix inverselocal = m_lworld;
03099 inverselocal.Invert();
03100
03101 a2dAffineMatrix inverse = ic->GetInverseParentTransform();
03102
03103 double xinternal, yinternal;
03104 inverse.TransformPoint(xw, yw, xinternal, yinternal);
03105
03106 a2dPolyHandleL* draghandle = wxDynamicCast( event.GetCanvasHandle(), a2dPolyHandleL );
03107 a2dVertexListPtr holevlist = draghandle->GetSegments();
03108 a2dVertexListPtr holevlistorg = draghandle->GetSegmentsOrg();
03109
03110
03111 a2dLineSegment* segment = *(draghandle->GetNode());
03112 a2dLineSegment* nextsegment = *(holevlist->GetNextAround( draghandle->GetNode() ));
03113 a2dLineSegment* segmentorg = *(draghandle->GetNodeOrg());
03114 a2dLineSegment* nextsegmentorg = *(holevlistorg->GetNextAround( draghandle->GetNodeOrg() ));
03115
03116 a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
03117
03118 double xwi;
03119 double ywi;
03120 if( m_flags.m_snap )
03121 {
03122 if (restrictEngine )
03123 restrictEngine->RestrictPoint( xinternal, yinternal );
03124 }
03125 inverselocal.TransformPoint( xinternal, yinternal, xwi, ywi );
03126 a2dAffineMatrix origworld = m_lworld;
03127
03128 if ( draghandle->GetName() == wxT("__indexhole__") )
03129 {
03130 if ( event.GetMouseEvent().ControlDown() && event.GetMouseEvent().LeftDown() )
03131 {
03132 m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( original, segmentorg ) );
03133 double x, y;
03134 RemoveSegment( x, y, segment );
03135 ReleaseChild( draghandle );
03136
03137
03138
03139
03140 ic->SetCorridorPathToParent();
03141 ic->GetCanvasView()->PopCursor();
03142 }
03143 if ( event.GetMouseEvent().LeftUp() )
03144 {
03145 double x,y;
03146 x = segment->m_x; y = segment->m_y;
03147 m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( original, x, y, segmentorg, false ) );
03148
03149 draghandle->SetPosXY( x, y );
03150
03151
03152 original->AdjustAfterChange( true );
03153 }
03154 else if ( event.GetMouseEvent().Dragging() )
03155 {
03156
03157 segment->m_x = xwi;
03158 segment->m_y = ywi;
03159 SetPending( true );
03160 draghandle->SetPosXY( xwi, ywi );
03161 SetPosXYSegment( segmentorg, xwi, ywi, false );
03162 AdjustAfterChange( false );
03163 }
03164 }
03165 else if ( draghandle->GetName() == wxT("__indexhole_arc__") )
03166 {
03167 a2dArcSegment* csegment = (a2dArcSegment*) segment;
03168 a2dArcSegment* csegmentorg = (a2dArcSegment*) segmentorg;
03169 if ( event.GetMouseEvent().LeftUp() )
03170 {
03171 double x,y;
03172 x = csegment->m_x2; y = csegment->m_y2;
03173 m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveMidSegment( original, x, y, csegmentorg, false ) );
03174
03175 draghandle->SetPosXY( x, y );
03176
03177
03178 original->AdjustAfterChange( true );
03179 }
03180 else if ( event.GetMouseEvent().Dragging() )
03181 {
03182 csegment->m_x2 = xwi; csegment->m_y2 = ywi;
03183 SetPending( true );
03184
03185
03186 draghandle->SetPosXYRestrict( xwi, ywi );
03187 SyncHandlesWithLineSegments();
03188 AdjustAfterChange( false );
03189 }
03190 else
03191 event.Skip();
03192 }
03193 else if ( draghandle->GetName() == wxT("__inserthole__") )
03194 {
03195
03196
03197 if (event.GetMouseEvent().LeftUp() )
03198 {
03199 double x,y;
03200 x = nextsegment->m_x;
03201 y = nextsegment->m_y;
03202 m_root->GetCommandProcessor()->Submit( new a2dCommand_AddPoint( original, x, y, nextsegmentorg, false ) );
03203
03204
03205 draghandle->SetPosXY( x, y );
03206 original->AdjustAfterChange( true );
03207 }
03208 else if ( event.GetMouseEvent().LeftDown() )
03209 {
03210 AddPoint( xwi, ywi, nextsegment, false );
03211 draghandle->SetPosXYRestrict( xwi, ywi );
03212 AdjustAfterChange( false );
03213 }
03214 else if ( event.GetMouseEvent().Dragging() )
03215 {
03216 SetPosXYSegment( nextsegment, xwi, ywi , false );
03217 draghandle->SetPosXYRestrict( xwi, ywi );
03218 AdjustAfterChange( false );
03219 }
03220 else
03221 event.Skip();
03222 }
03223 else if ( draghandle->GetName() == wxT("__segmenthole__") )
03224 {
03225 if (event.GetMouseEvent().LeftUp() )
03226 {
03227 double x1,y1;
03228 double x2,y2;
03229 x1 = segment->m_x;
03230 y1 = segment->m_y;
03231
03232 x2 = nextsegment->m_x;
03233 y2 = nextsegment->m_y;
03234
03235 double xwi, ywi, dx,dy;
03236 dx = 0.5*(x2-x1);
03237 dy = 0.5*(y2-y1);
03238 xwi = x1 + dx;
03239 ywi = y1 + dy;
03240 draghandle->SetPosXYRestrict( xwi, ywi );
03241 x1 = xwi - dx; x2 = xwi + dx;
03242 y1 = ywi - dy; y2 = ywi + dy;
03243
03244 m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( original, x1, y1, segmentorg, false ) );
03245 m_root->GetCommandProcessor()->Submit(
03246 new a2dCommand_MoveSegment( original, x2, y2, nextsegmentorg, false ));
03247
03248
03249
03250
03251
03252
03253
03254
03255 SyncHandlesWithLineSegments();
03256
03257
03258
03259 m_childobjects->Release( a2dCanvasOFlags::ALL, wxT("a2dPolyHandleL"), NULL, wxT("__segmenthole__"), false );
03260 original->AdjustAfterChange( true );
03261 }
03262 else if ( event.GetMouseEvent().LeftDown() )
03263 {
03264
03265 a2dPolyHandleL::PROPID_tmpXIH->SetPropertyToObject( draghandle, xwi );
03266 a2dPolyHandleL::PROPID_tmpYIH->SetPropertyToObject( draghandle, ywi );
03267
03268 double x, y;
03269 x = segment->m_x;
03270 y = segment->m_y;
03271 a2dPolyHandleL::PROPID_tmpXIV1->SetPropertyToObject( draghandle, x );
03272 a2dPolyHandleL::PROPID_tmpYIV1->SetPropertyToObject( draghandle, y );
03273 x = nextsegment->m_x;
03274 y = nextsegment->m_y;
03275 a2dPolyHandleL::PROPID_tmpXIV2->SetPropertyToObject( draghandle, x );
03276 a2dPolyHandleL::PROPID_tmpYIV2->SetPropertyToObject( draghandle, y );
03277 }
03278 else if ( event.GetMouseEvent().Dragging() )
03279 {
03280 double xi_h = a2dPolyHandleL::PROPID_tmpXIH->GetPropertyValue( draghandle );
03281 double yi_h = a2dPolyHandleL::PROPID_tmpYIH->GetPropertyValue( draghandle );
03282 double xi_v1 = a2dPolyHandleL::PROPID_tmpXIV1->GetPropertyValue( draghandle );
03283 double yi_v1 = a2dPolyHandleL::PROPID_tmpYIV1->GetPropertyValue( draghandle );
03284 double xi_v2 = a2dPolyHandleL::PROPID_tmpXIV2->GetPropertyValue( draghandle );
03285 double yi_v2 = a2dPolyHandleL::PROPID_tmpYIV2->GetPropertyValue( draghandle );
03286
03287
03288
03289 draghandle->SetPosXYRestrict( xwi, ywi );
03290 double x1 = xi_v1+xwi-xi_h;
03291 double y1 = yi_v1+ywi-yi_h;
03292 double x2 = xi_v2+xwi-xi_h;
03293 double y2 = yi_v2+ywi-yi_h;
03294
03295 segment->m_x = x1;
03296 segment->m_y = y1;
03297 nextsegment->m_x = x2;
03298 nextsegment->m_y = y2;
03299
03300 SetPending( true );
03301 AdjustAfterChange( false );
03302 }
03303 else
03304 event.Skip();
03305 }
03306 else
03307 event.Skip();
03308 }
03309 else
03310 event.Skip();
03311 }
03312 else
03313 {
03314 event.Skip();
03315 }
03316 }
03317
03318 void a2dSurface::SetHandleToIndex( a2dPolyHandleL* handle, unsigned int index )
03319 {
03320 handle->SetNode( GetSegmentAtIndex( index ) );
03321 a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
03322 handle->SetNodeOrg( original->GetSegmentAtIndex( index ) );
03323 }
03324
03325 int a2dSurface::GetIndexSegment( a2dLineSegmentPtr seg )
03326 {
03327 int index = -1;
03328 if ( seg.Get() == NULL )
03329 {
03330 return m_lsegments->IndexOf( m_lsegments->back() );
03331 }
03332
03333 index = m_lsegments->IndexOf( seg );
03334 if ( index != -1 )
03335 return index;
03336
03337 index = m_lsegments->size();
03338 index++;
03339 for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
03340 {
03341 a2dVertexListPtr vlist = (*iterp);
03342 a2dVertexList::iterator iter = vlist->begin();
03343 while ( iter != vlist->end() )
03344 {
03345 if ( *iter == seg )
03346 {
03347 return index;
03348 }
03349 index++;
03350 iter++;
03351 }
03352 index++;
03353 }
03354 return -1;
03355 }
03356
03357 a2dVertexList::iterator a2dSurface::GetSegmentAtIndex( unsigned int index )
03358 {
03359 if ( index < m_lsegments->size()+1 )
03360 {
03361 return m_lsegments->item( index );
03362 }
03363 unsigned int indexn = m_lsegments->size();
03364 indexn++;
03365 for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
03366 {
03367 a2dVertexListPtr vlist = (*iterp);
03368 a2dVertexList::iterator iter = vlist->begin();
03369 while ( iter != vlist->end() )
03370 {
03371 if ( indexn == index )
03372 {
03373 return iter;
03374 }
03375 indexn++;
03376 iter++;
03377 }
03378 if( indexn == index )
03379 {
03380 return iter;
03381 }
03382 indexn++;
03383 }
03384 return m_lsegments->end();
03385 }
03386
03387 a2dVertexList* a2dSurface::GetSegmentListAtIndex( unsigned int index )
03388 {
03389 if ( index < m_lsegments->size()+1 )
03390 {
03391 return m_lsegments;
03392 }
03393 unsigned int indexn = m_lsegments->size();
03394 indexn++;
03395 for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
03396 {
03397 a2dVertexListPtr vlist = (*iterp);
03398 a2dVertexList::iterator iter = vlist->begin();
03399 while ( iter != vlist->end() )
03400 {
03401 if ( indexn == index )
03402 {
03403 return vlist;
03404 }
03405 indexn++;
03406 iter++;
03407 }
03408 if( indexn == index )
03409 {
03410 return vlist;
03411 }
03412 indexn++;
03413 }
03414 return NULL;
03415 }
03416
03417
03418 void a2dSurface::RemoveSegment( double& x, double& y , a2dLineSegmentPtr seg, bool transformed )
03419 {
03420 if ( seg.Get() == NULL )
03421 {
03422 a2dLineSegment* point;
03423 point = m_lsegments->back();
03424 x = point->m_x;
03425 y = point->m_y;
03426 m_lsegments->pop_back();
03427 }
03428 else
03429 {
03430 a2dVertexList::iterator iter = m_lsegments->begin();
03431 a2dLineSegment* point;
03432 while ( iter != m_lsegments->end() )
03433 {
03434 if ( *iter == seg )
03435 {
03436 point = (*iter);
03437 x = point->m_x;
03438 y = point->m_y;
03439 m_lsegments->erase( iter );
03440 break;
03441 }
03442 iter++;
03443 }
03444 }
03445
03446 a2dLineSegment* point;
03447 for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
03448 {
03449 a2dVertexListPtr vlist = (*iterp);
03450 a2dVertexList::iterator iter = vlist->begin();
03451 while ( iter != vlist->end() )
03452 {
03453 if ( *iter == seg )
03454 {
03455 point = (*iter);
03456 x = point->m_x;
03457 y = point->m_y;
03458 vlist->erase( iter );
03459 break;
03460 }
03461 iter++;
03462 }
03463 }
03464
03465 if ( transformed )
03466 {
03467 m_lworld.TransformPoint( x, y, x, y );
03468 }
03469
03470 SetPending(true);
03471 }
03472
03473 void a2dSurface::InsertSegment( unsigned int index, a2dLineSegmentPtr segin )
03474 {
03475 if ( index < m_lsegments->size()+1 )
03476 {
03477 m_lsegments->Insert( index, segin );
03478 return;
03479 }
03480 unsigned int indexn = m_lsegments->size();
03481 indexn++;
03482 for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
03483 {
03484 a2dVertexListPtr vlist = (*iterp);
03485 a2dVertexList::iterator iter = vlist->begin();
03486 while ( iter != vlist->end() )
03487 {
03488 if ( indexn == index )
03489 {
03490 vlist->insert( iter, segin );
03491 return;
03492 }
03493 indexn++;
03494 iter++;
03495 }
03496 if( indexn == index )
03497 {
03498 vlist->insert( iter, segin );
03499 return;
03500 }
03501 indexn++;
03502 }
03503
03504 }
03505
03506 void a2dSurface::GetPosXYSegment( a2dLineSegmentPtr seg, double& x, double& y, bool transform ) const
03507 {
03508 if ( seg.Get() == NULL )
03509 {
03510 a2dLineSegment* point;
03511 point = m_lsegments->back();
03512 x = point->m_x;
03513 y = point->m_y;
03514 }
03515 else
03516 {
03517 x = seg->m_x;
03518 y = seg->m_y;
03519 }
03520
03521 if ( transform )
03522 {
03523 m_lworld.TransformPoint( x, y, x, y );
03524 }
03525 }
03526
03527 void a2dSurface::SetPosXYSegment( a2dLineSegmentPtr seg, double x, double y, bool afterinversion )
03528 {
03529 if ( afterinversion )
03530 {
03531 a2dAffineMatrix inverse = m_lworld;
03532 inverse.Invert();
03533 inverse.TransformPoint( x, y, x, y );
03534 }
03535
03536 m_lsegments->SetPointAdjustArcs( seg, x, y, true );
03537
03538 for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
03539 {
03540 a2dVertexListPtr vlist = (*iterp);
03541 vlist->SetPointAdjustArcs( seg, x, y, true );
03542 }
03543
03544 SetPending(true);
03545 }