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 "wx/canvas/wire.h"
00024
00025 #include <float.h>
00026 #include "wx/canvas/canobj.h"
00027 #include "wx/canvas/candoc.h"
00028 #include "wx/canvas/drawer.h"
00029 #include "wx/canvas/cancom.h"
00030 #include "wx/canvas/canvas.h"
00031 #include "wx/canvas/tools.h"
00032 #include "wx/canvas/canglob.h"
00033
00034
00035
00036
00037
00038
00039
00040
00041 IMPLEMENT_DYNAMIC_CLASS(a2dWirePolylineL, a2dPolylineL)
00042 IMPLEMENT_DYNAMIC_CLASS(a2dWireEnd, a2dCanvasObject)
00043 IMPLEMENT_CLASS( a2dRouteData, a2dObject );
00044
00045 double a2dRouteData::m_raster = 4;
00046
00047 a2dRouteData::BorderQueue::BorderQueue()
00048 {
00049 m_mincostindex = 0;
00050 memset( m_costring, 0, sizeof( m_costring ) );
00051 m_freelist = 0;
00052 m_memory = new AllocBlock();
00053 m_memory->m_next = 0;
00054 m_freememory = 0;
00055 #ifdef _DEBUG
00056 m_mincost = 0;
00057 #endif
00058 #ifdef PRFL_ENBL
00059 m_count = 0;
00060 #endif
00061 }
00062
00063 a2dRouteData::BorderQueue::~BorderQueue()
00064 {
00065 AllocBlock *current, *next;
00066
00067 for( current = m_memory; current; current = next )
00068 {
00069 next = current->m_next;
00070 delete current;
00071 }
00072 }
00073
00074 void a2dRouteData::BorderQueue::Add( const BorderPoint &brdr )
00075 {
00076 #ifdef PRFL_ENBL
00077 m_count++;
00078 #endif
00079
00080
00081 BorderPoint *newobjc;
00082
00083 if( m_freelist )
00084 {
00085
00086 newobjc = m_freelist;
00087 m_freelist = m_freelist->m_next;
00088 }
00089 else if( m_freememory < AllocBlock::m_pointsperblock )
00090 {
00091
00092 newobjc = m_memory->m_memory + m_freememory;
00093 m_freememory ++;
00094 }
00095 else
00096 {
00097
00098 AllocBlock *newblock = new AllocBlock();
00099 newblock->m_next = m_memory;
00100 m_memory = newblock;
00101 newobjc = m_memory->m_memory;
00102 m_freememory = 1;
00103 }
00104
00105
00106 *newobjc = brdr;
00107 #ifdef _DEBUG
00108 wxASSERT( brdr.m_cost - m_mincost < m_ncost );
00109 #endif
00110 int index = brdr.m_cost & m_costmask;
00111 newobjc->m_next = m_costring[index];
00112 m_costring[index] = newobjc;
00113
00114 if( !m_costring[ m_mincostindex ] )
00115 {
00116
00117 #ifdef _DEBUG
00118 wxASSERT( m_mincostindex == 0 && m_mincost == 0 );
00119 #endif
00120 m_mincostindex = index;
00121 #ifdef _DEBUG
00122 m_mincost = brdr.m_cost;
00123 #endif
00124 }
00125 }
00126
00127 void a2dRouteData::BorderQueue::RmvBest()
00128 {
00129 #ifdef PRFL_ENBL
00130 m_count--;
00131 #endif
00132
00133
00134 BorderPoint *obj = m_costring[ m_mincostindex ];
00135 wxASSERT( obj );
00136 m_costring[ m_mincostindex ] = obj->m_next;
00137
00138 obj->m_next = m_freelist;
00139 m_freelist = obj;
00140
00141 if( !m_costring[ m_mincostindex ] )
00142 {
00143 unsigned int i;
00144 for( i = m_mincostindex; i < m_ncost; i++ )
00145 {
00146 if( m_costring[ i ] )
00147 goto found;
00148 }
00149
00150 for( i = 0; i < m_mincostindex; i++ )
00151 {
00152 if( m_costring[ i ] )
00153 goto found;
00154 }
00155
00156
00157 m_mincostindex = 0;
00158 #ifdef _DEBUG
00159 m_mincost = 0;
00160 #endif
00161 return;
00162
00163 found:;
00164 m_mincostindex = i;
00165 #ifdef _DEBUG
00166 wxASSERT( m_costring[ m_mincostindex ] );
00167 wxASSERT( m_costring[ m_mincostindex ]->m_cost > m_mincost );
00168 wxASSERT( ( m_costring[ m_mincostindex ]->m_cost & m_costmask ) == m_mincostindex );
00169 m_mincost = m_costring[ m_mincostindex ]->m_cost;
00170 #endif
00171 }
00172 }
00173
00174 a2dRouteData::a2dRouteData( a2dCanvasObject *showobject, bool final )
00175 {
00176
00177
00178 #ifdef DUMP_FINAL
00179 m_dump = fopen("Routerdump.txt", "w");
00180 #endif
00181
00182 m_ok = true;
00183 m_showobject = showobject;
00184
00185
00186 a2dBoundingBox bbox;
00187
00188
00189 a2dCanvasObjectList::iterator iter;
00190 for( iter = m_showobject->GetChildObjectList()->begin(); iter != m_showobject->GetChildObjectList()->end(); ++iter )
00191 {
00192 a2dCanvasObject *obj = (*iter);
00193
00194
00195
00196 if( a2dCanvasObject::PROPID_ToolObject->GetPropertyValue( obj ) )
00197 continue;
00198
00199 a2dCanvasObject *editcopy = a2dCanvasObject::PROPID_Editcopy->GetPropertyValue( obj );
00200 if( !final && editcopy )
00201 obj = editcopy;
00202
00203 a2dBoundingBox objbbox = CalculateRoutingBbox( obj );
00204 bbox.Expand( objbbox );
00205
00206
00207 }
00208
00209 m_rasterborder = 20;
00210 bbox.Enlarge( m_rasterborder );
00211
00212 m_rasterinv = 1.0/m_raster;
00213 m_rasterminx = (int) floor( bbox.GetMinX() * m_rasterinv );
00214 m_rastermaxx = (int) ceil( bbox.GetMaxX() * m_rasterinv );
00215 m_rasterminy = (int) floor( bbox.GetMinY() * m_rasterinv );
00216 m_rastermaxy = (int) ceil( bbox.GetMaxY() * m_rasterinv );
00217
00218
00219
00220
00221 if( m_rastermaxx - m_rasterminx > 10000 )
00222 {
00223 m_ok = false;
00224 return;
00225 }
00226 if( m_rastermaxy - m_rasterminy > 10000 )
00227 {
00228 m_ok = false;
00229 return;
00230 }
00231
00232
00233 m_width = m_rastermaxx - m_rasterminx;
00234 m_widthp1 = m_width + 1;
00235 m_height = m_rastermaxy - m_rasterminy;
00236 m_heightp1 = m_height + 1;
00237
00238 m_verticaloccupation = new unsigned short[ m_widthp1 * m_heightp1 ];
00239 m_horizontaloccupation = new unsigned short[ m_widthp1 * m_heightp1 ];
00240 m_routepoints = new RoutePoint[ m_widthp1 * m_heightp1 * dir_count ];
00241
00242 if( !m_verticaloccupation || !m_horizontaloccupation || !m_routepoints )
00243 {
00244 m_ok = false;
00245 return;
00246 }
00247
00248 memset( m_verticaloccupation, 0, m_widthp1 * m_heightp1 * sizeof( *m_verticaloccupation ) );
00249 memset( m_horizontaloccupation, 0, m_widthp1 * m_heightp1 * sizeof( *m_horizontaloccupation ) );
00250 memset( m_routepoints, 0, m_widthp1 * m_heightp1 * dir_count * sizeof( *m_routepoints ) );
00251
00252
00253
00254
00255 for( iter = m_showobject->GetChildObjectList()->begin(); iter != m_showobject->GetChildObjectList()->end(); ++iter )
00256 {
00257 a2dCanvasObject *obj = (*iter);
00258
00259
00260 if( a2dCanvasObject::PROPID_ToolObject->GetPropertyValue( obj ) )
00261 continue;
00262
00263 a2dCanvasObject *editcopy = a2dCanvasObject::PROPID_Editcopy->GetPropertyValue( obj );
00264 if( !final && editcopy )
00265 obj = editcopy;
00266
00267
00268 if( a2dWirePolylineL::PROPID_Reroute->GetPropertyValue( obj ) )
00269 {
00270 obj->RemoveProperty( a2dWirePolylineL::PROPID_Rerouteadded );
00271 continue;
00272 }
00273
00274 if( wxDynamicCast( obj, a2dPolygonL ) )
00275 {
00276 AddOccupationPolyline( wxStaticCast( obj, a2dPolygonL )->GetSegments(), obj->GetTransformMatrix(), 1 );
00277 }
00278 else
00279 {
00280 a2dBoundingBox bbox = CalculateRoutingBbox( obj );
00281 AddOccupationRect( bbox, 1 );
00282 }
00283 }
00284
00285 #ifdef DUMP_FINAL
00286 if( final )
00287 {
00288 fprintf( m_dump, "Route init\n" );
00289 DumpOccupation( m_dump );
00290 }
00291 #endif
00292 }
00293
00294 a2dRouteData::~a2dRouteData()
00295 {
00296 delete [] m_verticaloccupation;
00297 delete [] m_horizontaloccupation;
00298 delete [] m_routepoints;
00299 #ifdef DUMP_FINAL
00300
00301 #endif
00302 }
00303
00304
00305
00306 void a2dRouteData::AddBorderPoint(
00307 BorderQueue *queue, RoutePoint *current,
00308 int nextx, int nexty,
00309 int dir, int prevdir
00310 )
00311 {
00312
00313
00314
00315 wxASSERT( nextx>=0 && nextx<=m_width );
00316 wxASSERT( nexty>=0 && nexty<=m_height );
00317 wxASSERT( dir>=dir_min && dir<=dir_max );
00318 wxASSERT( prevdir>=dir_min && prevdir<=dir_max );
00319
00320 RoutePoint *next = &GetRoutePoint( nextx, nexty, dir );
00321 if( next->m_flags & flag_reachable )
00322 {
00323 return;
00324 }
00325
00326
00327 if( ( dir^prevdir ) == dir_invxor )
00328 {
00329 return;
00330 }
00331
00332 BorderPoint border;
00333
00334 border.m_x = nextx;
00335 border.m_y = nexty;
00336 border.m_direction = dir;
00337 border.m_prevdir = prevdir;
00338
00339 border.m_cost = current->m_cost;
00340
00341 if( next->m_flags & flag_original )
00342 {
00343
00344 border.m_cost += 1;
00345 }
00346 else
00347 {
00348
00349 border.m_cost += 3;
00350 }
00351
00352
00353 if(
00354
00355 !( ( current->m_flags & flag_original ) && ( next->m_flags & flag_original ) ) &&
00356
00357 current->m_direction != border.m_direction
00358 )
00359 {
00360 border.m_cost += 10;
00361 }
00362
00363
00364 if( IsHorizontalOccupied( nextx, nexty ) || IsVerticalOccupied( nextx, nexty ) )
00365 {
00366 border.m_cost += 10;
00367 }
00368
00369 queue->Add( border );
00370 }
00371
00372 bool a2dRouteData::RerouteWire( a2dWirePolylineL *wire, a2dPin *dispin, a2dPin *startpin, bool startisbegin, bool final )
00373 {
00374
00375
00376
00377
00378
00379
00380 if( !m_ok )
00381 {
00382 return false;
00383 }
00384
00385
00386 memset( m_routepoints, 0, m_widthp1 * m_heightp1 * dir_count * sizeof( *m_routepoints ) );
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 #ifdef DUMP_FINAL
00400 if( final )
00401 {
00402 fprintf( m_dump, "Route Final 1 %p %d\n", wire, wire->GetSegments()->GetCount() );
00403 DumpOccupation( m_dump );
00404 }
00405 #endif
00406
00407
00408
00409 SetFlagPolyline( wire->GetSegments(), wire->GetTransformMatrix(), flag_original );
00410
00411
00412 if( a2dWirePolylineL::PROPID_Rerouteadded->GetPropertyValue( wire ) )
00413 {
00414 AddOccupationPolyline( wire->GetSegments(), wire->GetTransformMatrix(), -1 );
00415 }
00416
00417 a2dBoundingBox bboxStartPin;
00418 a2dBoundingBox bboxDisPin;
00419
00420
00421
00422
00423
00424
00425
00426 if ( startpin && startpin->ConnectedTo() && startpin->ConnectedTo()->IsInternal() )
00427 {
00428 a2dWireEnd* end = wxDynamicCast( startpin->ConnectedTo()->GetParent(), a2dWireEnd );
00429 if ( end )
00430 {
00431 a2dCanvasObject* org = a2dCanvasObject::PROPID_Original->GetPropertyValue( startpin->ConnectedTo()->GetParent() );
00432 bboxStartPin = CalculateRoutingBbox( org );
00433 }
00434 else
00435 {
00436 bboxStartPin = CalculateRoutingBbox( startpin->ConnectedTo()->GetParent() );
00437 }
00438 AddOccupationRect( bboxStartPin, -1 );
00439 }
00440
00441 if ( dispin->ConnectedTo() && dispin->ConnectedTo()->IsInternal() )
00442 {
00443 a2dWireEnd* end = wxDynamicCast( dispin->ConnectedTo()->GetParent(), a2dWireEnd );
00444 if ( end )
00445 {
00446 a2dCanvasObject* org = a2dCanvasObject::PROPID_Original->GetPropertyValue( dispin->ConnectedTo()->GetParent() );
00447 bboxDisPin = CalculateRoutingBbox( org );
00448 }
00449 else
00450 {
00451 bboxDisPin = CalculateRoutingBbox( dispin->ConnectedTo()->GetParent() );
00452 }
00453 AddOccupationRect( bboxDisPin, -1 );
00454 }
00455
00456
00457 if( wxDynamicCast( dispin->ConnectedTo()->GetParent(), a2dWirePolylineL ) )
00458 {
00459
00460 a2dWirePolylineL *target = wxStaticCast( dispin->ConnectedTo()->GetParent(), a2dWirePolylineL );
00461
00462 SetFlagPolyline( target->GetSegments(), target->GetTransformMatrix(), flag_targetwire );
00463 }
00464 else if( startpin && startpin->ConnectedTo() && wxDynamicCast( startpin->ConnectedTo()->GetParent(), a2dWirePolylineL ) )
00465 {
00466
00467
00468 a2dPin *h;
00469 h = dispin;
00470 dispin = startpin;
00471 startpin = h;
00472 startisbegin = !startisbegin;
00473
00474 a2dWirePolylineL *target = wxStaticCast( dispin->ConnectedTo()->GetParent(), a2dWirePolylineL );
00475
00476
00477
00478 a2dPoint2D newstartpos = startpin->ConnectedTo()->GetAbsXY();
00479 a2dAffineMatrix trns = wire->GetTransformMatrix();
00480 trns.Invert();
00481 trns.TransformPoint( &newstartpos );
00482
00483 if ( target->GetCanvasDocument()->GetCommandProcessor() )
00484 target->GetCanvasDocument()->GetCommandProcessor()->Submit(
00485 new a2dCommand_SetCanvasProperty( startpin, a2dCanvasObject::PROPID_Position, newstartpos, -1, true ), final );
00486 else
00487 startpin->SetPosXyPoint( newstartpos );
00488
00489
00490 SetFlagPolyline( target->GetSegments(), target->GetTransformMatrix(), flag_targetwire );
00491 }
00492
00493
00494 a2dPoint2D targetpos = dispin->ConnectedTo()->GetAbsXY();
00495
00496 if(
00497 floor( targetpos.m_x * m_rasterinv ) * m_raster == targetpos.m_x &&
00498 floor( targetpos.m_y * m_rasterinv ) * m_raster == targetpos.m_y
00499 )
00500 {
00501
00502 int x = (int) floor( ( targetpos.m_x + 0.5*m_raster ) * m_rasterinv ) - m_rasterminx;
00503 int y = (int) floor( ( targetpos.m_y + 0.5*m_raster ) * m_rasterinv ) - m_rasterminy;
00504 SetFlagRoutePointAllDirs( x, y, flag_targetpin );
00505 }
00506 else
00507 {
00508
00509 int x1 = (int) floor( targetpos.m_x * m_rasterinv ) - m_rasterminx;
00510 int y1 = (int) floor( targetpos.m_y * m_rasterinv ) - m_rasterminy;
00511 int x2 = (int) ceil( targetpos.m_x * m_rasterinv ) - m_rasterminx;
00512 int y2 = (int) ceil( targetpos.m_y * m_rasterinv ) - m_rasterminy;
00513 SetFlagRoutePointAllDirs(x1, y1, flag_targetapprox);
00514 SetFlagRoutePointAllDirs(x2, y1, flag_targetapprox);
00515 SetFlagRoutePointAllDirs(x1, y2, flag_targetapprox);
00516 SetFlagRoutePointAllDirs(x2, y2, flag_targetapprox);
00517 }
00518
00519 #ifdef DUMP_FINAL
00520 if( final )
00521 {
00522 fprintf( m_dump, "Route Final 2 %p %d\n", wire, wire->GetSegments()->GetCount() );
00523 DumpOccupation( m_dump );
00524 }
00525 #endif
00526
00527
00528 a2dPoint2D startpos;
00529 if( !startpin )
00530 {
00531
00532
00533 startpos = startisbegin ? wire->GetSegments()->front()->GetPoint() : wire->GetSegments()->back()->GetPoint();
00534 wire->GetTransformMatrix().TransformPoint( &startpos );
00535 }
00536 else
00537 {
00538 startpos = startpin->GetAbsXY();
00539 }
00540
00541 int startx = (int) floor( ( startpos.m_x + 0.5*m_raster ) * m_rasterinv ) - m_rasterminx;
00542 int starty = (int) floor( ( startpos.m_y + 0.5*m_raster ) * m_rasterinv ) - m_rasterminy;
00543
00544 BorderQueue queue;
00545
00546 for( int dir=dir_min; dir<=dir_max; dir++ )
00547 {
00548 BorderPoint start;
00549 start.m_x = startx;
00550 start.m_y = starty;
00551 start.m_direction = dir;
00552 start.m_prevdir = dir_start;
00553 start.m_cost = 0;
00554
00555 queue.Add( start );
00556 }
00557
00558 RoutePoint *end = 0;
00559
00560
00561
00562 while( queue.IsNotEmpty())
00563 {
00564
00565 const BorderPoint &border = queue.GetBest();
00566
00567 RoutePoint *point = &GetRoutePoint( border.m_x, border.m_y, border.m_direction );
00568
00569 if( point->m_flags & flag_reachable )
00570 {
00571
00572 queue.RmvBest();
00573 continue;
00574 }
00575
00576 point->m_x = border.m_x;
00577 point->m_y = border.m_y;
00578 point->m_direction = border.m_direction;
00579 point->m_prevdir = border.m_prevdir;
00580 point->m_cost = border.m_cost;
00581
00582
00583 if( point->m_flags & ( flag_targetwire | flag_targetpin | flag_targetapprox ) )
00584 {
00585
00586 end = point;
00587 break;
00588 }
00589
00590
00591 if( border.m_prevdir != dir_start )
00592 {
00593 switch( border.m_direction )
00594 {
00595 case dir_xminus:
00596 case dir_xplus:
00597 if( IsHorizontalOccupied( border.m_x, border.m_y ) )
00598 {
00599
00600 queue.RmvBest();
00601 continue;
00602 }
00603 break;
00604 case dir_yminus:
00605 case dir_yplus:
00606 if( IsVerticalOccupied( border.m_x, border.m_y ) )
00607 {
00608
00609 queue.RmvBest();
00610 continue;
00611 }
00612 break;
00613 }
00614 }
00615
00616
00617 point->m_flags |= flag_reachable;
00618
00619
00620
00621 if( !IsVerticalOccupied( point->m_x, point->m_y ) || border.m_prevdir == dir_start )
00622 {
00623
00624
00625 if( point->m_y > 0 )
00626 {
00627 AddBorderPoint(
00628 &queue, point,
00629 point->m_x, point->m_y-1,
00630 dir_yplus, point->m_direction
00631 );
00632 }
00633
00634
00635
00636 if( point->m_y < m_height )
00637 {
00638 AddBorderPoint(
00639 &queue, point,
00640 point->m_x, point->m_y+1,
00641 dir_yminus, point->m_direction
00642 );
00643 }
00644 }
00645
00646 if( !IsHorizontalOccupied( point->m_x, point->m_y ) || border.m_prevdir == dir_start )
00647 {
00648
00649
00650 if( point->m_x > 0 )
00651 {
00652 AddBorderPoint(
00653 &queue, point,
00654 point->m_x-1, point->m_y,
00655 dir_xplus, point->m_direction
00656 );
00657 }
00658
00659
00660
00661 if( point->m_x < m_width )
00662 {
00663 AddBorderPoint(
00664 &queue, point,
00665 point->m_x+1, point->m_y,
00666 dir_xminus, point->m_direction
00667 );
00668 }
00669 }
00670
00671
00672
00673 wxASSERT( &queue.GetBest() == &border );
00674 queue.RmvBest();
00675 }
00676
00677
00678
00679 #ifdef DUMP_FINAL
00680 if( final )
00681 {
00682 fprintf( m_dump, "Route Final 3 %p %d\n", wire, wire->GetSegments()->GetCount() );
00683 DumpOccupation( m_dump );
00684 }
00685 #endif
00686
00687 if ( bboxStartPin.GetValid() )
00688 {
00689 AddOccupationRect( bboxStartPin, 1 );
00690 }
00691
00692 if ( bboxDisPin.GetValid() )
00693 {
00694 AddOccupationRect( bboxDisPin, 1 );
00695 }
00696
00697 if( !end )
00698 {
00699
00700 a2dVertexList *newpoints = new a2dVertexList;
00701 if( startisbegin )
00702 {
00703 newpoints->push_back( new a2dLineSegment( startpos ) );
00704 newpoints->push_back( new a2dLineSegment( targetpos ) );
00705 }
00706 else
00707 {
00708 newpoints->push_back( new a2dLineSegment( targetpos ) );
00709 newpoints->push_back( new a2dLineSegment( startpos ) );
00710 }
00711
00712 if ( wire->GetCanvasDocument()->GetCommandProcessor() )
00713 wire->GetCanvasDocument()->GetCommandProcessor()->Submit( new a2dCommand_SetSegments( wire, newpoints, true ), final );
00714 else
00715 wire->SetSegments( newpoints );
00716
00717
00718 AddOccupationPolyline( wire->GetSegments(), wire->GetTransformMatrix(), 1 );
00719 a2dWirePolylineL::PROPID_Rerouteadded->SetPropertyToObject( wire, true );
00720 return false;
00721 }
00722 else
00723 {
00724
00725 a2dVertexList *newpoints = new a2dVertexList;
00726 RoutePoint *current = end;
00727 int prevdir = -1;
00728
00729 a2dPoint2D endpoint( ( current->m_x + m_rasterminx ) * m_raster, ( current->m_y + m_rasterminy ) * m_raster );
00730
00731 if( end->m_flags & flag_targetapprox )
00732 {
00733
00734 if( startisbegin )
00735 newpoints->push_front( new a2dLineSegment( targetpos ) );
00736 else
00737 newpoints->push_back( new a2dLineSegment( targetpos ) );
00738
00739
00740 a2dLineSegment *p = NULL;
00741 a2dPoint2D point( ( current->m_x + m_rasterminx ) * m_raster, ( current->m_y + m_rasterminy ) * m_raster );
00742 if (current->m_direction == dir_xminus || current->m_direction == dir_xplus )
00743 {
00744 if ( point.m_y != targetpos.m_y )
00745 p = new a2dLineSegment( targetpos.m_x, point.m_y );
00746 prevdir = current->m_direction;
00747 }
00748 else if (current->m_direction == dir_yminus || current->m_direction == dir_yplus )
00749 {
00750 if ( point.m_x != targetpos.m_x )
00751 p = new a2dLineSegment( point.m_x, targetpos.m_y );
00752 prevdir = current->m_direction;
00753 }
00754 if ( p )
00755 {
00756 if( startisbegin )
00757 newpoints->push_front( p );
00758 else
00759 newpoints->push_back( p );
00760 }
00761 }
00762 else if( end->m_flags & flag_targetwire )
00763 {
00764
00765
00766 a2dWirePolylineL *targetwire = wxStaticCast( dispin->ConnectedTo()->GetParent(), a2dWirePolylineL );
00767 targetwire->MoveDynamicPinCloseTo( dispin->ConnectedTo(), endpoint, final );
00768
00769
00770 a2dPoint2D dispinpos = dispin->ConnectedTo()->GetAbsXY();
00771
00772 if( dispinpos != endpoint )
00773 {
00774 if( startisbegin )
00775 newpoints->push_front( new a2dLineSegment( dispinpos ) );
00776 else
00777 newpoints->push_back( new a2dLineSegment( dispinpos ) );
00778
00779
00780 a2dLineSegment *p = NULL;
00781 a2dPoint2D point( ( current->m_x + m_rasterminx ) * m_raster, ( current->m_y + m_rasterminy ) * m_raster );
00782 if (current->m_direction == dir_xminus || current->m_direction == dir_xplus )
00783 {
00784 if ( point.m_y != dispinpos.m_y )
00785 p = new a2dLineSegment( dispinpos.m_x, point.m_y );
00786 prevdir = current->m_direction;
00787 }
00788 else if (current->m_direction == dir_yminus || current->m_direction == dir_yplus )
00789 {
00790 if ( point.m_x != dispinpos.m_x )
00791 p = new a2dLineSegment( point.m_x, dispinpos.m_y );
00792 prevdir = current->m_direction;
00793 }
00794 if ( p )
00795 {
00796 if( startisbegin )
00797 newpoints->push_front( p );
00798 else
00799 newpoints->push_back( p );
00800 }
00801 }
00802 }
00803
00804 for(;;)
00805 {
00806 current->m_flags |= flag_final;
00807
00808 a2dLineSegment point( ( current->m_x + m_rasterminx ) * m_raster, ( current->m_y + m_rasterminy ) * m_raster );
00809
00810 if( current->m_prevdir == dir_start )
00811 {
00812 if( startisbegin )
00813 newpoints->push_front( new a2dLineSegment( point ) );
00814 else
00815 newpoints->push_back( new a2dLineSegment( point ) );
00816
00817
00818
00819 if( startpin &&
00820 floor( point.m_x * m_rasterinv ) * m_raster == startpin->GetPosX() &&
00821 floor( point.m_y * m_rasterinv ) * m_raster == startpin->GetPosY()
00822 )
00823
00824 break;
00825 else
00826 {
00827 if( startisbegin )
00828 newpoints->push_front( new a2dLineSegment( startpin->GetPosX(), startpin->GetPosY()) );
00829 else
00830 newpoints->push_back( new a2dLineSegment( startpin->GetPosX(), startpin->GetPosY()) );
00831 }
00832
00833 break;
00834 }
00835
00836 if( current->m_direction != prevdir )
00837 {
00838 if( startisbegin )
00839 newpoints->push_front( new a2dLineSegment( point ) );
00840 else
00841 newpoints->push_back( new a2dLineSegment( point ) );
00842 prevdir = current->m_direction;
00843 }
00844
00845 int x = current->m_x;
00846 int y = current->m_y;
00847 switch( current->m_direction )
00848 {
00849 case dir_xminus:
00850 x--;
00851 break;
00852 case dir_xplus:
00853 x++;
00854 break;
00855 case dir_yminus:
00856 y--;
00857 break;
00858 case dir_yplus:
00859 y++;
00860 break;
00861 }
00862
00863 current = &GetRoutePoint( x, y, current->m_prevdir );
00864 }
00865
00866
00867 if ( wire->GetCanvasDocument()->GetCommandProcessor() )
00868 wire->GetCanvasDocument()->GetCommandProcessor()->Submit( new a2dCommand_SetSegments( wire, newpoints, true ), final );
00869 else
00870 wire->SetSegments( newpoints );
00871
00872
00873 AddOccupationPolyline( wire->GetSegments(), wire->GetTransformMatrix(), 1 );
00874 a2dWirePolylineL::PROPID_Rerouteadded->SetPropertyToObject( wire, true );
00875
00876 #ifdef DUMP_FINAL
00877 if( final )
00878 {
00879 fprintf( m_dump, "Route Final 4 %p %d\n", wire, wire->GetSegments()->GetCount() );
00880 DumpOccupation( m_dump );
00881 }
00882 #endif
00883
00884 return true;
00885 }
00886 }
00887
00888 void a2dRouteData::AddOccupationRect( const a2dBoundingBox &bbox, short incr )
00889 {
00890 int minx = (int) floor( ( bbox.GetMinX() + 0.75 * m_raster ) * m_rasterinv );
00891 int maxx = (int) ceil ( ( bbox.GetMaxX() - 0.75 * m_raster ) * m_rasterinv );
00892 int miny = (int) floor( ( bbox.GetMinY() + 0.75 * m_raster ) * m_rasterinv );
00893 int maxy = (int) ceil ( ( bbox.GetMaxY() - 0.75 * m_raster ) * m_rasterinv );
00894
00895 if( minx < m_rasterminx ) minx = m_rasterminx;
00896 if( maxx > m_rastermaxx ) maxx = m_rastermaxx;
00897 if( miny < m_rasterminy ) miny = m_rasterminy;
00898 if( maxy > m_rastermaxy ) maxy = m_rastermaxy;
00899
00900 int minxi = ( minx-m_rasterminx );
00901 int maxxi = ( maxx-m_rasterminx );
00902 int minyi = ( miny-m_rasterminy );
00903 int maxyi = ( maxy-m_rasterminy );
00904
00905 int x,y;
00906
00907 for( y=minyi; y<=maxyi; y++ )
00908 {
00909 for( x=minxi; x<=maxxi; x++ )
00910 {
00911 unsigned short& h = GetHorizontalOccupation( x, y );
00912 unsigned short& v = GetVerticalOccupation( x, y );
00913 if ( incr < 0 )
00914 {
00915 wxASSERT( h >= -incr && v >= -incr );
00916 }
00917 h += incr;
00918 v += incr;
00919 }
00920 }
00921 }
00922
00923 void a2dRouteData::AddOccupationPolyline( const a2dVertexList *points, const a2dAffineMatrix &trns, short incr )
00924 {
00925 a2dVertexList::const_iterator iter = points->begin();
00926 a2dVertexList::const_iterator prev = iter;
00927 iter++;
00928
00929 for( ; iter != points->end(); ++iter )
00930 {
00931 double x1l = (*prev)->m_x;
00932 double y1l = (*prev)->m_y;
00933 double x2l = (*iter)->m_x;
00934 double y2l = (*iter)->m_y;
00935 double x1,y1,x2,y2;
00936
00937 trns.TransformPoint( x1l, y1l, x1, y1 );
00938 trns.TransformPoint( x2l, y2l, x2, y2 );
00939
00940 int minx = (int) floor( ( wxMin( x1, x2 ) + 0.5 * m_raster ) * m_rasterinv );
00941 int maxx = (int) ceil ( ( wxMax( x1, x2 ) - 0.5 * m_raster ) * m_rasterinv );
00942 int miny = (int) floor( ( wxMin( y1, y2 ) + 0.5 * m_raster ) * m_rasterinv );
00943 int maxy = (int) ceil ( ( wxMax( y1, y2 ) - 0.5 * m_raster ) * m_rasterinv );
00944
00945 if( minx < m_rasterminx ) minx = m_rasterminx;
00946 if( maxx > m_rastermaxx ) maxx = m_rastermaxx;
00947 if( miny < m_rasterminy ) miny = m_rasterminy;
00948 if( maxy > m_rastermaxy ) maxy = m_rastermaxy;
00949
00950 int minxi = ( minx-m_rasterminx );
00951 int maxxi = ( maxx-m_rasterminx );
00952 int minyi = ( miny-m_rasterminy );
00953 int maxyi = ( maxy-m_rasterminy );
00954
00955 if( minxi == maxxi )
00956 {
00957
00958 for( int y=minyi; y<=maxyi; y++ )
00959 {
00960 GetVerticalOccupation( minxi, y ) += incr;
00961 }
00962 }
00963 else if( minyi == maxyi )
00964 {
00965
00966 for( int x=minxi; x<=maxxi; x++ )
00967 {
00968 GetHorizontalOccupation( x, minyi ) += incr;
00969 }
00970 }
00971
00972
00973 prev = iter;
00974 }
00975 }
00976
00977 void a2dRouteData::SetFlagRect( const a2dBoundingBox &bbox, RoutePointFlag flag )
00978 {
00979 int minx = (int) floor( ( bbox.GetMinX() + 0.5 * m_raster ) * m_rasterinv );
00980 int maxx = (int) ceil ( ( bbox.GetMaxX() - 0.5 * m_raster ) * m_rasterinv );
00981 int miny = (int) floor( ( bbox.GetMinY() + 0.5 * m_raster ) * m_rasterinv );
00982 int maxy = (int) ceil ( ( bbox.GetMaxY() - 0.5 * m_raster ) * m_rasterinv );
00983
00984 if( minx < m_rasterminx ) minx = m_rasterminx;
00985 if( maxx > m_rastermaxx ) maxx = m_rastermaxx;
00986 if( miny < m_rasterminy ) miny = m_rasterminy;
00987 if( maxy > m_rastermaxy ) maxy = m_rastermaxy;
00988
00989 int minxi = ( minx-m_rasterminx );
00990 int maxxi = ( maxx-m_rasterminx );
00991 int minyi = ( miny-m_rasterminy );
00992 int maxyi = ( maxy-m_rasterminy );
00993
00994 int x,y;
00995
00996 for( y=minyi; y<=maxyi; y++ )
00997 {
00998 for( x=minxi; x<=maxxi; x++ )
00999 {
01000 SetFlagRoutePointAllDirs( x, y, flag );
01001 }
01002 }
01003 }
01004
01005 void a2dRouteData::SetFlagPolyline( const a2dVertexList *points, const a2dAffineMatrix &trns, RoutePointFlag flag )
01006 {
01007 a2dVertexList::const_iterator iter = points->begin();
01008 a2dVertexList::const_iterator prev = iter;
01009 iter++;
01010
01011 for( ; iter != points->end(); ++iter )
01012 {
01013
01014
01015
01016 double x1l = (*prev)->m_x;
01017 double y1l = (*prev)->m_y;
01018 double x2l = (*iter)->m_x;
01019 double y2l = (*iter)->m_y;
01020 double x1,y1,x2,y2;
01021
01022 trns.TransformPoint( x1l, y1l, x1, y1 );
01023 trns.TransformPoint( x2l, y2l, x2, y2 );
01024
01025
01026 int minx = (int) floor( ( wxMin( x1, x2 ) + 0.5 * m_raster ) * m_rasterinv );
01027 int maxx = (int) ceil ( ( wxMax( x1, x2 ) - 0.5 * m_raster ) * m_rasterinv );
01028 int miny = (int) floor( ( wxMin( y1, y2 ) + 0.5 * m_raster ) * m_rasterinv );
01029 int maxy = (int) ceil ( ( wxMax( y1, y2 ) - 0.5 * m_raster ) * m_rasterinv );
01030
01031 if( minx < m_rasterminx ) minx = m_rasterminx;
01032 if( maxx > m_rastermaxx ) maxx = m_rastermaxx;
01033 if( miny < m_rasterminy ) miny = m_rasterminy;
01034 if( maxy > m_rastermaxy ) maxy = m_rastermaxy;
01035
01036 int minxi = ( minx-m_rasterminx );
01037 int maxxi = ( maxx-m_rasterminx );
01038 int minyi = ( miny-m_rasterminy );
01039 int maxyi = ( maxy-m_rasterminy );
01040
01041 if( minxi == maxxi )
01042 {
01043
01044 for( int y=minyi; y<=maxyi; y++ )
01045 {
01046 SetFlagRoutePointAllDirs( minxi, y, flag );
01047 }
01048 }
01049 else if( minyi == maxyi )
01050 {
01051
01052 for( int x=minxi; x<=maxxi; x++ )
01053 {
01054 SetFlagRoutePointAllDirs( x, minyi, flag );
01055 }
01056 }
01057
01058
01059 prev = iter;
01060 }
01061 }
01062
01063 a2dBoundingBox a2dRouteData::CalculateRoutingBbox( a2dCanvasObject *object )
01064 {
01065
01066
01067 a2dBoundingBox box = object->GetUnTransformedBbox( false );
01068
01069 forEachIn( a2dCanvasObjectList, object->GetChildObjectList() )
01070 {
01071 a2dCanvasObject *obj = *iter;
01072 if( !wxDynamicCast( obj, a2dPin ) )
01073 {
01074 box.Expand( obj->GetCalculatedBoundingBox( 0 ) );
01075 }
01076 }
01077
01078 box.MapBbox( object->GetTransformMatrix() );
01079
01080 return box;
01081
01082 }
01083
01084
01085 void a2dRouteData::DumpOccupation( FILE *file )
01086 {
01087 #ifdef _DEBUG
01088 if( file )
01089 fprintf( file, "\nOccupation %d x %d\n", m_width, m_height);
01090 else
01091 wxLogDebug(_T("\nOccupation %d x %d"), m_width, m_height);
01092
01093 int x,y;
01094
01095 wxChar *buffer = new wxChar [ m_widthp1*2+1 ];
01096 wxChar *pos;
01097
01098 for( y = 0; y <= m_height; y++ )
01099 {
01100
01101 pos = buffer;
01102 for( x = 0; x <= m_width; x++ )
01103 {
01104 unsigned short ho = GetHorizontalOccupation( x, y );
01105 unsigned short vo = GetVerticalOccupation( x, y );
01106 RoutePoint *point0 = &GetRoutePoint( x, y, 0 );
01107 RoutePoint *point1 = &GetRoutePoint( x, y, 1 );
01108 RoutePoint *point2 = &GetRoutePoint( x, y, 2 );
01109 RoutePoint *point3 = &GetRoutePoint( x, y, 3 );
01110
01111 if( ho==0 && vo==0 )
01112 *pos++ = wxT('.');
01113 else if( ho==1 && vo==0 )
01114 *pos++ = wxT('-');
01115 else if( ho==0 && vo==1 )
01116 *pos++ = wxT('|');
01117 else if( ho==1 && vo==1 )
01118 *pos++ = wxT('x');
01119 else if( ho==2 && vo==0 )
01120 *pos++ = wxT('=');
01121 else if( ho==0 && vo==2 )
01122 *pos++ = wxT('"');
01123 else
01124 *pos++ = wxT('X');
01125
01126 if(
01127 ( point0->m_flags & flag_final ) ||
01128 ( point1->m_flags & flag_final ) ||
01129 ( point2->m_flags & flag_final ) ||
01130 ( point3->m_flags & flag_final )
01131 )
01132 *pos++ = wxT('#');
01133 else if( point0->m_flags & flag_targetpin )
01134 *pos++ = wxT('P');
01135 else if( point0->m_flags & flag_targetapprox )
01136 *pos++ = wxT('A');
01137 else if( point0->m_flags & flag_targetwire )
01138 *pos++ = wxT('W');
01139 else if(
01140 ( point0->m_flags & flag_reachable ) ||
01141 ( point1->m_flags & flag_reachable ) ||
01142 ( point2->m_flags & flag_reachable ) ||
01143 ( point3->m_flags & flag_reachable )
01144 )
01145 *pos++ = wxT('R');
01146 else
01147 *pos++ = wxT(' ');
01148 }
01149 *pos++ = 0;
01150 if( file )
01151 fprintf( file, "%s\n", buffer );
01152 else
01153 wxLogDebug( buffer );
01154 }
01155
01156 delete [] buffer;
01157 #endif
01158 }
01159
01160 void a2dRouteData::DumpCost()
01161 {
01162 #ifdef _DEBUG
01163 wxLogDebug(_T("\nCost"));
01164 int x,y;
01165
01166 wxChar *buffer = new wxChar [ m_widthp1*3*2+1 ];
01167 wxChar *pos;
01168
01169 for( y = 0; y <= m_height; y++ )
01170 {
01171 pos = buffer;
01172 for( x = 0; x <= m_width; x++ )
01173 {
01174 RoutePoint *point = &GetRoutePoint( x, y, dir_xminus );
01175 int val = point->m_cost;
01176
01177 *pos++ = val/10%10 + wxT('0');
01178 *pos++ = val%10 + wxT('0');
01179 *pos++ = wxT(' ');
01180
01181 point = &GetRoutePoint( x, y, dir_yminus );
01182 val = point->m_cost;
01183
01184 *pos++ = val/10%10 + wxT('0');
01185 *pos++ = val%10 + wxT('0');
01186 *pos++ = wxT('|');
01187 }
01188 *pos++ = 0;
01189 wxLogDebug( buffer );
01190
01191 pos = buffer;
01192 for( x = 0; x <= m_width; x++ )
01193 {
01194 RoutePoint *point = &GetRoutePoint( x, y, dir_yplus );
01195 int val = point->m_cost;
01196
01197 *pos++ = val/10%10 + wxT('0');
01198 *pos++ = val%10 + wxT('0');
01199 *pos++ = wxT(' ');
01200
01201 point = &GetRoutePoint( x, y, dir_xplus );
01202 val = point->m_cost;
01203
01204 *pos++ = val/10%10 + wxT('0');
01205 *pos++ = val%10 + wxT('0');
01206 *pos++ = wxT('|');
01207 }
01208 *pos++ = 0;
01209 wxLogDebug( buffer );
01210 wxLogDebug( _T("") );
01211 }
01212
01213 delete [] buffer;
01214 #endif
01215 }
01216
01217 void a2dRouteData::DumpVertexList( a2dVertexList *list )
01218 {
01219 #ifdef _DEBUG
01220 wxLogDebug( wxT("VertexList") );
01221 forEachIn( a2dVertexList, list )
01222 {
01223 wxLogDebug( wxT("%12.3lf %12.3lf"), (*iter)->m_x, (*iter)->m_y );
01224 }
01225 #endif
01226 };
01227
01228
01229
01230
01231
01232
01233 a2dPropertyIdBool* a2dWirePolylineL::PROPID_Reroute = NULL;
01234 a2dPropertyIdBool* a2dWirePolylineL::PROPID_Rerouteadded = NULL;
01235
01236 A2D_BEGIN_EVENT_TABLE( a2dWirePolylineL, a2dPolylineL )
01237 A2D_END_EVENT_TABLE()
01238
01239 INITIALIZE_PROPERTIES( a2dWirePolylineL, a2dPolylineL )
01240 {
01241 A2D_PROPID_D_F( a2dPropertyIdBool, Reroute, false, a2dPropertyId::flag_temporary|a2dPropertyId::flag_listfirst );
01242 A2D_PROPID_D_F( a2dPropertyIdBool, Rerouteadded, false, a2dPropertyId::flag_temporary|a2dPropertyId::flag_listfirst );
01243
01244 return true;
01245 }
01246
01247 a2dWirePolylineL::a2dWirePolylineL()
01248 {
01249 m_inverted = false;
01250 m_objBegin = NULL;
01251 m_wireBegin = NULL;
01252 m_wireEnd = NULL;
01253 m_objEnd = NULL;
01254 m_flags.m_draggable = false;
01255 m_wasVertical = false;
01256 m_oneLine = false;
01257 }
01258
01259 a2dWirePolylineL::a2dWirePolylineL(a2dVertexList* points, bool spline )
01260 : a2dPolylineL( points, spline )
01261 {
01262 m_inverted = false;
01263 m_objBegin = NULL;
01264 m_wireBegin = NULL;
01265 m_wireEnd = NULL;
01266 m_objEnd = NULL;
01267 m_flags.m_draggable = false;
01268 m_wasVertical = false;
01269 m_oneLine = false;
01270 }
01271
01272 a2dWirePolylineL::a2dWirePolylineL( const a2dWirePolylineL& poly, CloneOptions options )
01273 : a2dPolylineL( poly, options )
01274 {
01275
01276
01277 m_flags.m_draggable = poly.m_flags.m_draggable;
01278 m_wasVertical = poly.m_wasVertical;
01279 m_inverted = poly.m_inverted;
01280 m_objBegin = poly.m_objBegin;
01281 m_wireBegin = poly.m_wireBegin;
01282 m_wireEnd = poly.m_wireEnd;
01283 m_objEnd = poly.m_objEnd;
01284 m_oneLine = poly.m_oneLine;
01285 }
01286
01287 a2dWirePolylineL::~a2dWirePolylineL()
01288 {
01289 }
01290
01291 a2dObject* a2dWirePolylineL::Clone( CloneOptions options ) const
01292 {
01293 return new a2dWirePolylineL( *this, options );
01294 }
01295
01296 void a2dWirePolylineL::SetConnectionInfo(
01297 bool inverted,
01298 a2dPinClass* objBegin,
01299 a2dPinClass* objEnd
01300 )
01301 {
01302 m_inverted = inverted;
01303 m_objBegin = objBegin;
01304 m_objEnd = objEnd;
01305 }
01306
01307 bool a2dWirePolylineL::IsConnect() const
01308 {
01309 return true;
01310 }
01311
01312 bool a2dWirePolylineL::NeedsUpdateWhenConnected() const
01313 {
01314 return true;
01315 }
01316
01317 void a2dWirePolylineL::DoUpdateImmediate( a2dDoUpdateImmediateData *data )
01318 {
01319 bool oneLine = m_oneLine || a2dCanvasGlobals->GetRouteOneLine();
01320
01321 switch ( data->m_phase )
01322 {
01323 case 0:
01324
01325 if( data->m_phase_first )
01326 {
01327
01328 data->RequestPhase( 1 );
01329
01330 if( data->m_final )
01331 break;
01332
01333
01334
01335 a2dWirePolylineL *original = wxStaticCastNull( PROPID_Original->GetPropertyValue( this ).Get(), a2dWirePolylineL );
01336 a2dWirePolylineL *target = this;
01337
01338
01339 if( !original )
01340 break;
01341
01342
01343 {
01344 a2dVertexList *newpoints = new a2dVertexList;
01345 *newpoints = *original->GetSegments();
01346 target->SetSegments( newpoints );
01347 }
01348
01349
01350 for( a2dCanvasObjectList::iterator iter = target->m_childobjects->begin(); iter != target->m_childobjects->end(); ++iter )
01351 {
01352 a2dCanvasObject *obj = *iter;
01353 a2dPin* pin = wxDynamicCast( obj, a2dPin );
01354 if( !pin ) continue;
01355
01356 a2dPin *pinori = wxStaticCast( PROPID_Original->GetPropertyValue( pin ).Get(), a2dPin );
01357
01358 pin->SetTransformMatrix( pinori->GetTransformMatrix() );
01359 }
01360
01361
01362
01363
01364 target->AdjustAfterChange( data->m_final );
01365 }
01366 break;
01367
01368 case 1:
01369
01370
01371
01372 {
01373
01374 if ( oneLine )
01375 data->RequestPhase( 3 );
01376 else
01377 data->RequestPhase( 2 );
01378
01379 data->RequestSortPriorityBeforeNextPhase();
01380
01381 a2dWirePolylineL *original = wxStaticCastNull( PROPID_Original->GetPropertyValue( this ).Get(), a2dWirePolylineL );
01382 a2dWirePolylineL *target = data->m_final && !data->m_original ? original : this;
01383
01384 int oldpriority = PROPID_UpdateImmediatePriority->GetPropertyValue( target );
01385 int priority = 0;
01386
01387
01388 for( a2dCanvasObjectList::iterator iter = target->GetChildObjectList()->begin(); iter != target->GetChildObjectList()->end(); ++iter )
01389 {
01390 a2dCanvasObject *obj = *iter;
01391 a2dPin* pin = wxDynamicCast( obj, a2dPin );
01392 if( !pin )
01393 continue;
01394
01395
01396 if( pin->GetName()!=wxT("begin") && pin->GetName()!=wxT("end") )
01397 continue;
01398
01399
01400 if( !pin->ConnectedTo() )
01401 continue;
01402
01403
01404 if( !pin->ConnectedTo()->GetParent()->IsConnect() )
01405 continue;
01406
01407 int minpriority = 1 + PROPID_UpdateImmediatePriority->GetPropertyValue( pin->ConnectedTo()->GetParent() );
01408 if( minpriority > priority )
01409 priority = minpriority;
01410
01411 }
01412
01413 PROPID_UpdateImmediatePriority->SetPropertyToObject( target, priority );
01414 PROPID_Reroute->SetPropertyToObject( target, true );
01415
01416 if( oldpriority != priority )
01417 {
01418
01419 data->RequestPhase( 1 );
01420 }
01421 }
01422 break;
01423
01424 case 2:
01425
01426
01427
01428 if( data->m_phase_first )
01429 {
01430
01431 data->RequestPhase( 3 );
01432 a2dRouteData *routedata = wxStaticCastNull( a2dCanvasObject::a2dDoUpdateImmediateData::PROPID_RouteData->GetPropertyValue( data ).Get(), a2dRouteData );
01433 if( !routedata )
01434 {
01435 routedata = new a2dRouteData( data->m_parent, data->m_final );
01436 a2dCanvasObject::a2dDoUpdateImmediateData::PROPID_RouteData->SetPropertyToObject( data, routedata );
01437 }
01438 }
01439 break;
01440
01441 case 3:
01442
01443
01444 {
01445 a2dWirePolylineL *original = wxStaticCastNull( PROPID_Original->GetPropertyValue( this ).Get(), a2dWirePolylineL );
01446 a2dWirePolylineL *target = data->m_final && !data->m_original ? original : this;
01447
01448
01449 if ( target )
01450 {
01451 target->RemoveProperty( PROPID_UpdateImmediatePriority );
01452 target->RemoveProperty( PROPID_Reroute );
01453
01454 for( a2dCanvasObjectList::iterator iter = target->GetChildObjectList()->begin(); iter != target->GetChildObjectList()->end(); ++iter )
01455 {
01456 a2dCanvasObject *obj = *iter;
01457 a2dPin* pin = wxDynamicCast( obj, a2dPin );
01458 if( !pin ) continue;
01459
01460 if( pin->IsDislocated() )
01461 {
01462 a2dPin *otherPin = pin->ConnectedTo();
01463
01464 wxASSERT( otherPin );
01465
01466 if( pin->IsDynamicPin() )
01467 {
01468 a2dPoint2D otherPos = otherPin->GetAbsXY();
01469 if( target->MoveDynamicPinCloseTo( pin, otherPos, data && data->m_final ) )
01470 {
01471
01472 if( data )
01473 data->RequestPhase( 3 );
01474 }
01475 }
01476 else
01477 {
01478
01479 if( otherPin->GetParent()->IsConnect() )
01480 {
01481 bool originalsave = data->m_original;
01482 data->m_original = true;
01483 otherPin->GetParent()->DoUpdateImmediate( data );
01484 data->m_original = originalsave;
01485
01486 }
01487
01488 if( pin->GetName() == wxT("begin") )
01489 {
01490 if( data->m_allowreconnectbegin && data->m_final )
01491 {
01492 pin->AutoConnect( data->m_parent, 1.0 );
01493 }
01494
01495 if( pin->IsDislocated() )
01496 {
01497 if ( oneLine )
01498 {
01499 a2dPoint2D otherEnd = FindEndPin()->GetAbsXY();
01500
01501 a2dVertexList *newpoints = new a2dVertexList;
01502 newpoints->push_back( new a2dLineSegment( pin->ConnectedTo()->GetAbsXY()) );
01503 newpoints->push_back( new a2dLineSegment( otherEnd ) );
01504
01505 if ( GetCanvasDocument()->GetCommandProcessor() )
01506 GetCanvasDocument()->GetCommandProcessor()->Submit( new a2dCommand_SetSegments( target, newpoints, true ), data->m_final );
01507 else
01508 target->SetSegments( newpoints );
01509 a2dWirePolylineL::PROPID_Rerouteadded->SetPropertyToObject( target, true );
01510 }
01511 else
01512 {
01513
01514 a2dRouteData *routedata = wxStaticCast( a2dCanvasObject::a2dDoUpdateImmediateData::PROPID_RouteData->GetPropertyValue( data ).Get(), a2dRouteData );
01515 routedata->RerouteWire( target, pin, FindEndPin(), false, data->m_final );
01516
01517 }
01518 }
01519
01520
01521 if( target->AdjustAfterChange( data->m_final ) )
01522 {
01523
01524 data->RequestPhase( 3 );
01525
01526 }
01527 }
01528 else if( pin->GetName() == wxT("end") )
01529 {
01530 if( data->m_allowreconnectend && data->m_final )
01531 {
01532 pin->AutoConnect( data->m_parent, 1.0 );
01533 }
01534
01535 if( pin->IsDislocated() )
01536 {
01537 if ( oneLine )
01538 {
01539 a2dPoint2D otherEnd = FindBeginPin()->GetAbsXY();
01540
01541 a2dVertexList *newpoints = new a2dVertexList;
01542 newpoints->push_back( new a2dLineSegment( otherEnd ) );
01543 newpoints->push_back( new a2dLineSegment( pin->ConnectedTo()->GetAbsXY()) );
01544
01545 if ( GetCanvasDocument()->GetCommandProcessor() )
01546 GetCanvasDocument()->GetCommandProcessor()->Submit( new a2dCommand_SetSegments( target, newpoints, true ), data->m_final );
01547 else
01548 target->SetSegments( newpoints );
01549 a2dWirePolylineL::PROPID_Rerouteadded->SetPropertyToObject( target, true );
01550 }
01551 else
01552 {
01553
01554 a2dRouteData *routedata = wxStaticCast( a2dCanvasObject::a2dDoUpdateImmediateData::PROPID_RouteData->GetPropertyValue( data ).Get(), a2dRouteData );
01555 routedata->RerouteWire( target, pin, FindBeginPin(), true, data->m_final );
01556
01557 }
01558 }
01559
01560
01561 if( target->AdjustAfterChange( data->m_final ) )
01562 {
01563
01564 data->RequestPhase( 3 );
01565
01566 }
01567 }
01568 else
01569 {
01570 wxASSERT_MSG( 0, wxT("Unknown pin type in wire") );
01571 }
01572
01573 }
01574 }
01575 else if( !pin->ConnectedTo() )
01576 {
01577
01578 if( pin->GetName() == wxT("begin") )
01579 {
01580 if( data->m_allowreconnectbegin && data->m_final )
01581 {
01582 pin->AutoConnect( data->m_parent, 1.0 );
01583 }
01584 }
01585 else if( pin->GetName() == wxT("end") )
01586 {
01587 if( data->m_allowreconnectend && data->m_final )
01588 {
01589 pin->AutoConnect( data->m_parent, 1.0 );
01590 }
01591 }
01592 }
01593 }
01594 }
01595 }
01596 break;
01597 }
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741 }
01742
01743 bool a2dWirePolylineL::AdjustAfterChange( bool final )
01744 {
01745 bool changed = false;
01746 for( a2dCanvasObjectList::iterator iter = GetChildObjectList()->begin(); iter != GetChildObjectList()->end(); ++iter )
01747 {
01748 a2dCanvasObject *obj = *iter;
01749 a2dPin* pin = wxDynamicCast( obj, a2dPin );
01750 if( !pin ) continue;
01751
01752 double xOld = pin->GetPosX();
01753 double yOld = pin->GetPosY();
01754
01755
01756
01757 if( pin->IsDynamicPin() )
01758 {
01759
01760 if( MoveDynamicPinCloseTo( pin, pin->GetAbsXY(), final ) )
01761 changed = true;
01762 }
01763 else if( pin->GetName() == wxT("begin") )
01764 {
01765
01766 double xNew, yNew;
01767 GetPosXYSegment( 0, xNew, yNew, false );
01768 if( xNew != xOld || yNew != yOld )
01769 {
01770 if ( m_root->GetCommandProcessor() )
01771 m_root->GetCommandProcessor()->Submit( new a2dCommand_SetCanvasProperty( pin, PROPID_Position, a2dPoint2D( xNew, yNew ), -1, false ), final );
01772 else
01773 pin->SetPosXY( xNew, yNew );
01774
01775 changed = true;
01776 }
01777 }
01778 else if( pin->GetName() == wxT("end") )
01779 {
01780
01781 double xNew, yNew;
01782 GetPosXYSegment( GetNumberOfSegments()-1, xNew, yNew, false );
01783 if( xNew != xOld || yNew != yOld )
01784 {
01785 if ( m_root->GetCommandProcessor() )
01786 m_root->GetCommandProcessor()->Submit( new a2dCommand_SetCanvasProperty( pin, PROPID_Position, a2dPoint2D( xNew, yNew ), -1, false ), final );
01787 else
01788 pin->SetPosXY( xNew, yNew );
01789
01790 changed = true;
01791 }
01792 }
01793 }
01794
01795 return changed;
01796 }
01797
01798 #if wxART2D_USE_CVGIO
01799 void a2dWirePolylineL::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
01800 {
01801 a2dPolylineL::DoSave( parent, out, xmlparts, towrite );
01802 if ( xmlparts == a2dXmlSer_attrib )
01803 {
01804 out.WriteAttribute( wxT("invert"), m_inverted );
01805 out.WriteAttribute( wxT("pcobjbegin"), m_objBegin->GetName() );
01806 out.WriteAttribute( wxT("pcwirebegin"), m_wireBegin->GetName() );
01807 out.WriteAttribute( wxT("pcwireend"), m_wireEnd->GetName() );
01808 }
01809 else
01810 {
01811 }
01812 }
01813 void a2dWirePolylineL::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
01814 {
01815 a2dPolylineL::DoLoad( parent, parser, xmlparts );
01816 if ( xmlparts == a2dXmlSer_attrib )
01817 {
01818 m_inverted = parser.RequireAttributeValueBool( wxT("invert") );
01819
01820 wxString pinclass;
01821
01822 pinclass = parser.RequireAttributeValue( wxT("pcobjbegin") );
01823 m_objBegin = a2dPinClass::GetClassByName( pinclass );
01824 if( !m_objBegin )
01825 {
01826 m_objBegin = a2dPinClass::Standard;
01827 wxString reference_name = GetName();
01828 a2dDocviewGlobals->ReportErrorF( a2dError_NoPinClass, _("a2dWirePolylineL with name %s \n Pin class %s not found (replaced with Standard)"), reference_name.c_str(), pinclass.c_str() );
01829 }
01830
01831 pinclass = parser.RequireAttributeValue( wxT("pcwirebegin") );
01832 m_wireBegin = a2dPinClass::GetClassByName( pinclass );
01833 if( !m_wireBegin )
01834 {
01835 m_wireBegin = a2dPinClass::Standard;
01836 wxString reference_name = GetName();
01837 a2dDocviewGlobals->ReportErrorF( a2dError_NoPinClass, _("a2dWirePolylineL with name %s \n Pin class %s not found (replaced with Standard)"), reference_name.c_str(), pinclass.c_str() );
01838 }
01839
01840 pinclass = parser.RequireAttributeValue( wxT("pcwireend") );
01841 m_wireEnd = a2dPinClass::GetClassByName( pinclass );
01842 if( !m_wireEnd )
01843 {
01844 m_wireEnd = a2dPinClass::Standard;
01845 wxString reference_name = GetName();
01846 a2dDocviewGlobals->ReportErrorF( a2dError_NoPinClass, _("a2dWirePolylineL with name %s \n Pin class %s not found (replaced with Standard)"), reference_name.c_str(), pinclass.c_str() );
01847 }
01848 }
01849 else
01850 {
01851 }
01852 }
01853 #endif //wxART2D_USE_CVGIO
01854
01855 void a2dWirePolylineL::SetEndPoint( int iEnd, int iNext, double x, double y, bool final )
01856 {
01857 double xPre, yPre;
01858 GetPosXYSegment(iEnd, xPre, yPre, true );
01859 m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( this, x, y, iEnd, true), final );
01860
01861 if( GetNumberOfSegments()>2 )
01862 {
01863 double xNext, yNext;
01864 GetPosXYSegment(iNext, xNext, yNext, true );
01865 bool isHor = fabs( yPre - yNext ) <= 1e-10 * wxMax( fabs( yPre ), fabs( yNext ) );
01866 bool isVert = fabs( xPre - xNext ) <= 1e-10 * wxMax( fabs( xPre ), fabs( xNext ) );
01867
01868
01869 if( isHor && ! isVert || isHor && isVert && !m_wasVertical )
01870 {
01871 m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( this, xNext, yNext+y-yPre, iNext, true), final );
01872 m_wasVertical = false;
01873 }
01874
01875
01876 if( isVert && ! isHor || isHor && isVert && m_wasVertical )
01877 {
01878 m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( this, xNext+x-xPre, yNext, iNext, true), final );
01879 m_wasVertical = true;
01880 }
01881 }
01882 }
01883
01884 bool a2dWirePolylineL::IsDislocated()
01885 {
01886 return FindBeginPin()->IsDislocated() || FindEndPin()->IsDislocated();
01887 }
01888
01889 void a2dWirePolylineL::EditFeedback( a2dIterC& ic, const a2dFeedbackId *id, a2dCanvasObject *currentEdit, int depth, a2dCanvasObjectFlagsMask flags, double x, double y )
01890 {
01891 a2dPolylineL::EditFeedback( ic, id, currentEdit, depth, flags, x, y );
01892 }
01893
01894 bool a2dWirePolylineL::GeneratePins( a2dPinClass* toConnectTo, a2dConnectTask task, double x, double y )
01895 {
01896 a2dPinClass* toCreate = toConnectTo->GetPinClassForTask( task, this );
01897 if ( GetGeneratePins() && ( toCreate == m_wireBegin || toCreate == m_wireEnd ) )
01898 {
01899 m_flags.m_visiblechilds = true;
01900 bool end = false;
01901 bool begin = false;
01902 if ( !HasPinNamed( wxT("begin")) )
01903 {
01904 a2dVertexList::iterator iter = m_lsegments->begin();
01905 assert( m_lsegments->size() );
01906 AddPin( wxT("begin"), (*iter)->m_x, (*iter)->m_y, a2dPin::temporary, m_wireBegin );
01907 }
01908 else
01909 begin = true;
01910
01911 if ( !HasPinNamed( wxT("end")) )
01912 {
01913 a2dVertexList::iterator iter = m_lsegments->end();
01914 assert( m_lsegments->size() );
01915 iter--;
01916 AddPin( wxT("end"), (*iter)->m_x, (*iter)->m_y, a2dPin::temporary, m_wireEnd );
01917 }
01918 else
01919 end = true;
01920
01921 if ( m_lsegments->size() > 0 )
01922 {
01923
01924 double xNear, yNear;
01925 if( FindNearPoint( &m_lworld, x, y, &xNear, &yNear ) )
01926 {
01927 a2dAffineMatrix inverse = m_lworld;
01928 inverse.Invert();
01929 double xNearLocal, yNearLocal;
01930 inverse.TransformPoint( xNear, yNear, xNearLocal, yNearLocal );
01931
01932
01933 a2dPin *pin = AddPin( wxT("dynamic"), xNearLocal, yNearLocal, a2dPin::temporary | a2dPin::dynamic, toCreate );
01934 pin->SetMode( a2dPin::sm_PinCanConnectToPinClass );
01935 pin->SetMouseInObject( true );
01936 }
01937 }
01938
01939 wxASSERT( HasPins() );
01940 m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT("a2dPin") );
01941
01942 return true;
01943 }
01944 return false;
01945 }
01946
01947
01948
01949
01950 a2dWireEnd::a2dWireEnd( double x , double y )
01951 : a2dCanvasObject( x, y )
01952 {
01953 }
01954
01955 a2dWireEnd::a2dWireEnd( const a2dWireEnd& obj, CloneOptions options )
01956 : a2dCanvasObject( obj, options )
01957 {
01958 }
01959
01960 a2dObject* a2dWireEnd::Clone( CloneOptions options ) const
01961 {
01962 return new a2dWireEnd( *this, options );
01963 }