Update procedures
[shapes.git] / source / pathtypes.cc
bloba0dfb7b1cf8fc452a97eea45fc83c6b615e59152
1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * any later version.
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008, 2009, 2014 Henrik Tidefelt
19 #include <cmath>
21 #include "shapestypes.h"
22 #include "shapesexceptions.h"
23 #include "astexpr.h"
24 #include "consts.h"
25 #include "globals.h"
26 #include "angleselect.h"
27 #include "astvar.h"
28 #include "astclass.h"
29 #include "continuations.h"
30 #include "dynamicenvironment.h"
32 #include <complex>
33 #include <ctype.h>
34 #include <stack>
36 using namespace Shapes;
37 using namespace std;
40 Concrete::Time
41 Shapes::computeDt( Concrete::Length segLength )
43 double dt = Computation::the_arcdelta / segLength;
44 if( dt < Computation::the_dtMin )
46 if( Computation::dtMinIsError )
48 throw Exceptions::DtMinError( dt );
50 dt = Computation::the_dtMin;
52 return dt;
55 Concrete::Time
56 Shapes::straightLineArcTime( double fraction )
58 typedef std::complex< double > Complex;
59 Complex s( fraction, 0 );
60 const Complex add1iSqrt3( 1, sqrt( 3 ) );
61 const Complex sub1iSqrt3( 1, -sqrt( 3 ) );
62 const Complex tmp = pow( Complex( -1, 0 ) + Complex( 2, 0 ) * ( s + sqrt( ( Complex( -1, 0 ) + s ) * s ) ), 1./3 );
63 return 0.5 + 0.25 * ( (sub1iSqrt3 / tmp ).real( ) + ( add1iSqrt3 * tmp ).real( ) );
64 // const Complex cRes = Complex( 0.5, 0 ) + Complex( 0.25, 0 ) * ( sub1iSqrt3 / tmp + add1iSqrt3 * tmp );
65 // return cRes.real( );
68 Kernel::PolarHandlePromise::PolarHandlePromise( )
69 { }
71 Kernel::PolarHandlePromise::~PolarHandlePromise( )
72 { }
75 Kernel::PolarHandleEmptyPromise::PolarHandleEmptyPromise( )
76 { }
78 Kernel::PolarHandleEmptyPromise::~PolarHandleEmptyPromise( )
79 { }
81 double
82 Kernel::PolarHandleEmptyPromise::force( const Concrete::PathPoint2D * specialUnitP0, const Concrete::PathPoint2D * specialUnitP1, bool reverse ) const
84 std::ostringstream msg;
85 msg << "The empty promise must be replaced before use. Probably related to " ;
86 Lang::DYNAMIC_VARIABLE_ID_DEFAULT_UNIT.show( msg, Ast::Identifier::DYNAMIC_VARIABLE );
87 msg << "." ;
88 throw Exceptions::MiscellaneousRequirement( strrefdup( msg ) );
91 void
92 Kernel::PolarHandleEmptyPromise::gcMark( Kernel::GCMarkedSet & marked ) const
97 void
98 Kernel::PolarHandleEmptyPromise::show( std::ostream & os ) const
100 os << "< undefined >" ;
104 Kernel::PolarHandleTruePromise::PolarHandleTruePromise( Kernel::Thunk * thunk )
105 : thunk_( thunk )
108 Kernel::PolarHandleTruePromise::~PolarHandleTruePromise( )
110 delete thunk_;
114 double
115 Kernel::PolarHandleTruePromise::force( const Concrete::PathPoint2D * specialUnitP0, const Concrete::PathPoint2D * specialUnitP1, bool reverse ) const
117 Kernel::ValueRef valUntyped = NullPtr< const Lang::Value >( );
119 /* Note that the use of a StoreValueContinuation relies on valUntyped being alive at the time the continuation is invoked.
121 bool done = false;
122 Kernel::EvalState evalState( 0,
124 NullPtr< Kernel::DynamicEnvironment >( ),
125 Kernel::ContRef( new Kernel::StoreValueContinuation( & valUntyped,
126 Kernel::ContRef( new Kernel::ExitContinuation( & done, thunk_->getExpr( )->loc( ) ) ),
127 thunk_->getExpr( )->loc( ) ) ) );
129 thunk_->force( & evalState, false ); /* note that the dynamic environment is set below, before evaluation begins. "false" means that the thunk may be forced repeatedly */
131 Kernel::SpecialUnitVariables * dynVars = new Kernel::SpecialUnitVariables;
132 dynVars->reverseDirection_ = reverse;
133 dynVars->p0_ = specialUnitP0;
134 dynVars->p1_ = specialUnitP1;
135 evalState.dyn_ = Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState.dyn_, dynVars ) );
137 while( ! done )
139 evalState.expr_->eval( & evalState );
142 typedef const Lang::Length ArgType;
143 ArgType * valPtr = dynamic_cast< ArgType * >( valUntyped.getPtr( ) );
144 if( valPtr == 0 )
146 throw Exceptions::TypeMismatch( thunk_->getExpr( )->loc( ), valUntyped->getTypeName( ), ArgType::staticTypeName( ) );
149 return valPtr->getScalar( );
152 void
153 Kernel::PolarHandleTruePromise::gcMark( Kernel::GCMarkedSet & marked ) const
155 if( thunk_ != 0 )
157 thunk_->gcMark( marked );
161 void
162 Kernel::PolarHandleTruePromise::show( std::ostream & os ) const
164 os << "Dynamic expression at " << thunk_->getExpr( )->loc( ) ;
168 Lang::PolarHandleBase::PolarHandleBase( )
171 DISPATCHIMPL( PolarHandleBase );
173 Lang::PolarHandleBase::~PolarHandleBase( )
176 RefCountPtr< const Lang::Class > Lang::PolarHandleBase::TypeID( new Lang::SystemFinalClass( strrefdup( "PolarHandle" ) ) );
177 TYPEINFOIMPL( PolarHandleBase );
180 Lang::PolarHandle2D::PolarHandle2D( const RefCountPtr< const Kernel::PolarHandlePromise > & rPromise, double a )
181 : rPromise_( rPromise ), a_( a )
184 DISPATCHIMPL( PolarHandle2D );
186 Lang::PolarHandle2D::~PolarHandle2D( )
189 void
190 Lang::PolarHandle2D::show( std::ostream & os ) const
192 os << "Completely specified" ;
195 void
196 Lang::PolarHandle2D::gcMark( Kernel::GCMarkedSet & marked )
198 rPromise_->gcMark( marked );
202 Lang::PolarHandle2DFree_a::PolarHandle2DFree_a( const RefCountPtr< const Kernel::PolarHandlePromise > & rPromise )
203 : rPromise_( rPromise )
206 DISPATCHIMPL( PolarHandle2DFree_a );
208 Lang::PolarHandle2DFree_a::~PolarHandle2DFree_a( )
211 void
212 Lang::PolarHandle2DFree_a::show( std::ostream & os ) const
214 os << "Free angle, promise pointer: " << rPromise_.getPtr( ) ;
217 void
218 Lang::PolarHandle2DFree_a::gcMark( Kernel::GCMarkedSet & marked )
220 rPromise_->gcMark( marked );
224 Lang::PolarHandle2DFree_r::PolarHandle2DFree_r( const RefCountPtr< const Kernel::PolarHandlePromise > & defaultModulus, double a )
225 : defaultModulus_( defaultModulus ), a_( a )
228 DISPATCHIMPL( PolarHandle2DFree_r );
230 Lang::PolarHandle2DFree_r::~PolarHandle2DFree_r( )
233 void
234 Lang::PolarHandle2DFree_r::show( std::ostream & os ) const
236 os << "Free modulus, angle = " << a_ ;
239 void
240 Lang::PolarHandle2DFree_r::gcMark( Kernel::GCMarkedSet & marked )
242 defaultModulus_->gcMark( marked );
246 Lang::PolarHandle2DFree_ra::PolarHandle2DFree_ra( const RefCountPtr< const Kernel::PolarHandlePromise > & defaultModulus )
247 : defaultModulus_( defaultModulus )
250 DISPATCHIMPL( PolarHandle2DFree_ra );
252 Lang::PolarHandle2DFree_ra::~PolarHandle2DFree_ra( )
255 void
256 Lang::PolarHandle2DFree_ra::show( std::ostream & os ) const
258 os << "Completely free" ;
261 void
262 Lang::PolarHandle2DFree_ra::gcMark( Kernel::GCMarkedSet & marked )
264 defaultModulus_->gcMark( marked );
268 Concrete::PathPoint2D::PathPoint2D( const Concrete::PathPoint2D & orig )
269 : rearState_( orig.rearState_ ), rearAngle_( orig.rearAngle_ ), rearModulus_( orig.rearModulus_ ),
270 rearModulusPromise_( NullPtr< Kernel::PolarHandlePromise >( ) ),
271 frontState_( orig.frontState_ ), frontAngle_( orig.frontAngle_ ), frontModulus_( orig.frontModulus_ ),
272 frontModulusPromise_( NullPtr< Kernel::PolarHandlePromise >( ) ),
273 defaultAngle_( orig.defaultAngle_ )
275 mid_ = new Concrete::Coords2D( *orig.mid_ );
277 if( orig.rear_ != orig.mid_ )
279 rear_ = new Concrete::Coords2D( *orig.rear_ );
281 else
283 rear_ = mid_;
285 if( orig.front_ != orig.mid_ )
287 front_ = new Concrete::Coords2D( *orig.front_ );
289 else
291 front_ = mid_;
295 /* The initial state is set to COMPLETE, even though theoretically, the angle towards the neighboring pathpoints should be computed.
296 * However, by setting the default rearAngle_ and frontAngle_ to NaN, we can replace an atan2 computation by an IS_NAN test.
298 Concrete::PathPoint2D::PathPoint2D( Concrete::Coords2D * mid )
299 : rearState_( COMPLETE ), rearAngle_( std::numeric_limits< double >::signaling_NaN( ) ), rearModulusPromise_( NullPtr< Kernel::PolarHandlePromise >( ) ),
300 frontState_( COMPLETE ), frontAngle_( std::numeric_limits< double >::signaling_NaN( ) ), frontModulusPromise_( NullPtr< Kernel::PolarHandlePromise >( ) ),
301 defaultAngle_( 0 ),
302 rear_( mid ), mid_( mid ), front_( mid )
305 Concrete::PathPoint2D::PathPoint2D( Concrete::Length midx, Concrete::Length midy )
306 : rearState_( COMPLETE ), rearAngle_( std::numeric_limits< double >::signaling_NaN( ) ), rearModulusPromise_( NullPtr< Kernel::PolarHandlePromise >( ) ),
307 frontState_( COMPLETE ), frontAngle_( std::numeric_limits< double >::signaling_NaN( ) ), frontModulusPromise_( NullPtr< Kernel::PolarHandlePromise >( ) ),
308 defaultAngle_( 0 ),
309 rear_( new Concrete::Coords2D( midx, midy ) ), mid_( rear_ ), front_( rear_ )
312 Concrete::PathPoint2D::~PathPoint2D( )
314 if( rear_ != 0 && rear_ != mid_ )
316 delete rear_;
318 if( mid_ != 0 )
320 delete mid_;
322 if( front_ != 0 && front_ != mid_ )
324 delete front_;
328 Concrete::PathPoint2D *
329 Concrete::PathPoint2D::transformed( const Lang::Transform2D & tf ) const
331 Concrete::PathPoint2D * res = new Concrete::PathPoint2D( mid_->transformedPtr( tf ) );
332 if( rear_ != mid_ )
334 res->rear_ = rear_->transformedPtr( tf );
336 if( front_ != mid_ )
338 res->front_ = front_->transformedPtr( tf );
340 return res;
343 Concrete::PathPoint3D *
344 Concrete::PathPoint2D::transformed( const Lang::Transform3D & tf ) const
346 Concrete::PathPoint3D * res = new Concrete::PathPoint3D( mid_->transformedPtr( tf ) );
347 if( rear_ != mid_ )
349 res->rear_ = rear_->transformedPtr( tf );
351 if( front_ != mid_ )
353 res->front_ = front_->transformedPtr( tf );
355 return res;
358 Concrete::PathPoint3D *
359 Concrete::PathPoint2D::typed_to3D( ) const
361 Concrete::PathPoint3D * res = new Concrete::PathPoint3D( *mid_ );
362 if( rear_ != mid_ )
364 res->rear_ = new Concrete::Coords3D( *rear_ );
366 if( front_ != mid_ )
368 res->front_ = new Concrete::Coords3D( *front_ );
370 return res;
374 Concrete::PathPoint3D::PathPoint3D( const Concrete::PathPoint3D & orig )
375 : mid_( new Concrete::Coords3D( *orig.mid_ ) )
377 if( orig.rear_ != orig.mid_ )
379 rear_ = new Concrete::Coords3D( *orig.rear_ );
381 else
383 rear_ = mid_;
386 if( orig.front_ != orig.mid_ )
388 front_ = new Concrete::Coords3D( *orig.front_ );
390 else
392 front_ = mid_;
396 Concrete::PathPoint3D::PathPoint3D( Concrete::Coords3D * mid )
397 : rear_( mid ), mid_( mid ), front_( mid )
400 Concrete::PathPoint3D::PathPoint3D( const Concrete::Coords2D & mid )
401 : rear_( new Concrete::Coords3D( mid ) ), mid_( rear_ ), front_( rear_ )
404 Concrete::PathPoint3D::PathPoint3D( Concrete::Length midx, Concrete::Length midy, Concrete::Length midz )
405 : rear_( new Concrete::Coords3D( midx, midy, midz ) ), mid_( rear_ ), front_( rear_ )
408 Concrete::PathPoint3D::~PathPoint3D( )
410 if( rear_ != 0 && rear_ != mid_ )
412 delete rear_;
414 if( mid_ != 0 )
416 delete mid_;
418 if( front_ != 0 && front_ != mid_ )
420 delete front_;
424 Concrete::PathPoint3D *
425 Concrete::PathPoint3D::transformed( const Lang::Transform3D & tf ) const
427 Concrete::PathPoint3D * res = new Concrete::PathPoint3D( mid_->transformedPtr( tf ) );
428 if( rear_ != mid_ )
430 res->rear_ = rear_->transformedPtr( tf );
432 if( front_ != mid_ )
434 res->front_ = front_->transformedPtr( tf );
436 return res;
439 Concrete::PathPoint2D *
440 Concrete::PathPoint3D::make2D( Concrete::Length eyez ) const
442 Concrete::PathPoint2D * res = new Concrete::PathPoint2D( mid_->make2D( eyez ) );
443 if( rear_ != mid_ )
445 res->rear_ = rear_->make2D( eyez );
447 if( front_ != mid_ )
449 res->front_ = front_->make2D( eyez );
451 return res;
454 Lang::PathPoint2D::PathPoint2D( const Lang::PathPoint2D & orig )
455 : rear_( orig.rear_ ), mid_( orig.mid_ ), front_( orig.front_ )
458 DISPATCHIMPL( PathPoint2D );
460 Lang::PathPoint2D::PathPoint2D( RefCountPtr< const Lang::Coords2D > mid )
461 : rear_( NullPtr< Lang::Value >( ) ), mid_( mid ), front_( NullPtr< Lang::Value >( ) )
464 Kernel::VariableHandle
465 Lang::PathPoint2D::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
467 if( strcmp( fieldID, "mid" ) == 0 )
469 return Kernel::VariableHandle( new Kernel::Variable( mid_ ) );
471 if( strcmp( fieldID, "rear" ) == 0 )
473 return Kernel::VariableHandle( new Kernel::Variable( rear_ ) );
475 if( strcmp( fieldID, "front" ) == 0 )
477 return Kernel::VariableHandle( new Kernel::Variable( front_ ) );
479 throw Exceptions::NonExistentMember( getTypeName( ), fieldID );
482 RefCountPtr< const Lang::Geometric2D >
483 Lang::PathPoint2D::transformed( const Lang::Transform2D & tf, const RefCountPtr< const Lang::Geometric2D > & self ) const
485 throw Exceptions::MiscellaneousRequirement( strrefdup( "A pathpoint by itself cannot be transformed." ) );
488 RefCountPtr< const Lang::Geometric3D >
489 Lang::PathPoint2D::to3D( const RefCountPtr< const Lang::Geometric2D > & self ) const
491 throw Exceptions::MiscellaneousRequirement( strrefdup( "A 2D pathpoint by itself cannot go 3D." ) );
494 void
495 Lang::PathPoint2D::gcMark( Kernel::GCMarkedSet & marked )
498 Lang::Value * tmp = const_cast< Lang::Value * >( rear_.getPtr( ) );
499 if( tmp != 0 )
501 tmp->gcMark( marked );
505 const_cast< Lang::Coords2D * >( mid_.getPtr( ) )->gcMark( marked );
508 Lang::Value * tmp = const_cast< Lang::Value * >( front_.getPtr( ) );
509 if( tmp != 0 )
511 tmp->gcMark( marked );
517 RefCountPtr< const Lang::Class > Lang::PathPoint2D::TypeID( new Lang::SystemFinalClass( strrefdup( "PathPoint" ) ) );
518 TYPEINFOIMPL( PathPoint2D );
521 Lang::PathPoint3D::PathPoint3D( const Lang::PathPoint3D & orig )
522 : rear_( orig.rear_ ), mid_( orig.mid_ ), front_( orig.front_ )
525 DISPATCHIMPL( PathPoint3D );
527 Lang::PathPoint3D::PathPoint3D( const RefCountPtr< const Lang::Coords3D > & mid )
528 : rear_( NullPtr< Lang::Coords3D >( ) ), mid_( mid ), front_( NullPtr< Lang::Coords3D >( ) )
531 Kernel::VariableHandle
532 Lang::PathPoint3D::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
534 if( strcmp( fieldID, "mid" ) == 0 )
536 return Kernel::VariableHandle( new Kernel::Variable( mid_ ) );
538 if( strcmp( fieldID, "rear" ) == 0 )
540 return Kernel::VariableHandle( new Kernel::Variable( rear_ ) );
542 if( strcmp( fieldID, "front" ) == 0 )
544 return Kernel::VariableHandle( new Kernel::Variable( front_ ) );
546 throw Exceptions::NonExistentMember( getTypeName( ), fieldID );
549 void
550 Lang::PathPoint3D::elementaryJob( Lang::ElementaryPath3D * pth, Concrete::Coords3D * basePoint ) const
552 Concrete::Coords3D * newMid = new Concrete::Coords3D( *basePoint, *mid_ );
553 *basePoint = *newMid;
554 Concrete::PathPoint3D * newPoint = new Concrete::PathPoint3D( newMid );
556 if( rear_ != NullPtr< const Lang::Coords3D >( ) )
558 newPoint->rear_ = new Concrete::Coords3D( *basePoint, *rear_ );
561 if( front_ != NullPtr< const Lang::Coords3D >( ) )
563 newPoint->front_ = new Concrete::Coords3D( *basePoint, *front_ );
566 pth->push_back( newPoint );
569 RefCountPtr< const Lang::Geometric3D >
570 Lang::PathPoint3D::transformed( const Lang::Transform3D & tf, const RefCountPtr< const Lang::Geometric3D > & self ) const
572 PathPoint3D * res = new Lang::PathPoint3D( RefCountPtr< const Lang::Coords3D >( mid_->transformedPtr( tf ) ) );
574 if( rear_ != NullPtr< const Lang::Coords3D >( ) )
576 res->rear_ = RefCountPtr< const Lang::Coords3D >( rear_->transformedPtr( tf ) );
579 if( front_ != NullPtr< const Lang::Coords3D >( ) )
581 res->front_ = RefCountPtr< const Lang::Coords3D >( front_->transformedPtr( tf ) );
584 return RefCountPtr< const Lang::Geometric3D >( res );
587 RefCountPtr< const Lang::Geometric2D >
588 Lang::PathPoint3D::to2D( const Kernel::PassedDyn & dyn, const RefCountPtr< const Lang::Geometric3D > & self ) const
590 Concrete::Length eyez = dyn->getEyeZ( );
591 PathPoint2D * res = new Lang::PathPoint2D( mid_->make2D( eyez ) );
593 if( rear_ != NullPtr< const Lang::Coords3D >( ) )
595 res->rear_ = rear_->make2D( eyez );
598 if( front_ != NullPtr< const Lang::Coords3D >( ) )
600 res->front_ = front_->make2D( eyez );
603 return RefCountPtr< const Lang::Geometric2D >( res );
606 void
607 Lang::PathPoint3D::gcMark( Kernel::GCMarkedSet & marked )
610 Lang::Coords3D * tmp = const_cast< Lang::Coords3D * >( rear_.getPtr( ) );
611 if( tmp != 0 )
613 tmp->gcMark( marked );
617 const_cast< Lang::Coords3D * >( mid_.getPtr( ) )->gcMark( marked );
620 Lang::Coords3D * tmp = const_cast< Lang::Coords3D * >( front_.getPtr( ) );
621 if( tmp != 0 )
623 tmp->gcMark( marked );
628 RefCountPtr< const Lang::Class > Lang::PathPoint3D::TypeID( new Lang::SystemFinalClass( strrefdup( "PathPoint" ) ) );
629 TYPEINFOIMPL( PathPoint3D );
632 Lang::Path2D::Path2D( )
633 : closed_( false )
636 DISPATCHIMPL( Path2D );
638 Lang::Path2D::~Path2D( )
641 void
642 Lang::Path2D::close( )
644 closed_ = true;
646 bool
647 Lang::Path2D::isClosed( ) const
649 return closed_;
652 RefCountPtr< const Lang::Geometric2D >
653 Lang::Path2D::transformed( const Lang::Transform2D & tf, const RefCountPtr< const Lang::Geometric2D > & self ) const
655 typedef const Lang::Path2D ArgType;
656 RefCountPtr< ArgType > selfTyped = self.down_cast< ArgType >( );
657 if( selfTyped == NullPtr< ArgType >( ) )
659 throw Exceptions::InternalError( strrefdup( "Path2D::to3D: self was of unexpected type." ) );
662 return selfTyped->typed_transformed( tf );
665 RefCountPtr< const Lang::Geometric3D >
666 Lang::Path2D::to3D( const RefCountPtr< const Lang::Geometric2D > & self ) const
668 typedef const Lang::Path2D ArgType;
669 RefCountPtr< ArgType > selfTyped = self.down_cast< ArgType >( );
670 if( selfTyped == NullPtr< ArgType >( ) )
672 throw Exceptions::InternalError( strrefdup( "Path2D::to3D: self was of unexpected type." ) );
675 return selfTyped->typed_to3D( selfTyped );
678 RefCountPtr< const Lang::Class > Lang::Path2D::TypeID( new Lang::SystemFinalClass( strrefdup( "Path" ) ) );
679 TYPEINFOIMPL( Path2D );
682 Lang::CompositePath2D::CompositePath2D( )
683 : elementaryPath_( NullPtr< const ElementaryPath2D >( ) )
686 DISPATCHIMPL( CompositePath2D );
688 Lang::CompositePath2D::~CompositePath2D( )
691 Kernel::VariableHandle
692 Lang::CompositePath2D::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
694 computeElementaryPath( );
695 return elementaryPath_->getField( fieldID, elementaryPath_ );
698 RefCountPtr< const Lang::Path2D >
699 Lang::CompositePath2D::typed_transformed( const Lang::Transform2D & tf ) const
701 computeElementaryPath( );
702 return elementaryPath_->typed_transformed( tf );
705 RefCountPtr< const Lang::Path3D >
706 Lang::CompositePath2D::typed_to3D( const RefCountPtr< const Lang::Path2D > & self ) const
708 computeElementaryPath( );
709 return RefCountPtr< const Lang::Path3D >( new Lang::Path2Din3D( elementaryPath_ ) );
712 void
713 Lang::CompositePath2D::writePath( ostream & os ) const
715 computeElementaryPath( );
716 elementaryPath_->writePath( os );
719 RefCountPtr< const Lang::ElementaryPath2D >
720 Lang::CompositePath2D::getElementaryPath( ) const
722 computeElementaryPath( );
723 return elementaryPath_;
726 void
727 Lang::CompositePath2D::show( std::ostream & os ) const
729 os << "Composite subpath" ;
733 Lang::ClosedPath2D::ClosedPath2D( RefCountPtr< const Lang::Path2D > openPath )
734 : openPath_( openPath )
736 close( );
739 Lang::ClosedPath2D::~ClosedPath2D( )
742 DISPATCHIMPL( ClosedPath2D );
744 void
745 Lang::ClosedPath2D::elementaryJob( std::stack< const Lang::Value * > * nodeStack, Lang::ElementaryPath2D * pth, Concrete::Coords2D * basePoint ) const
747 openPath_->elementaryJob( nodeStack, pth, basePoint );
749 * Although this seems incorrect, as the fact that this path is closed will not be respected,
750 * this should not be a problem since it is not allowed to connect closed paths with anything.
754 void
755 Lang::ClosedPath2D::gcMark( Kernel::GCMarkedSet & marked )
757 const_cast< Lang::Path2D * >( openPath_.getPtr( ) )->gcMark( marked );
761 Lang::Connection2D::Connection2D( Kernel::ValueRef rear, Kernel::ValueRef front )
762 : rear_( rear ), front_( front )
765 DISPATCHIMPL( Connection2D );
767 Lang::Connection2D::~Connection2D( )
770 void
771 Lang::Connection2D::elementaryJob( std::stack< const Lang::Value * > * nodeStack, Lang::ElementaryPath2D * pth, Concrete::Coords2D * basePoint ) const
773 nodeStack->push( front_.getPtr( ) );
774 nodeStack->push( rear_.getPtr( ) );
777 void
778 Lang::Connection2D::gcMark( Kernel::GCMarkedSet & marked )
780 const_cast< Lang::Value * >( rear_.getPtr( ) )->gcMark( marked );
781 const_cast< Lang::Value * >( front_.getPtr( ) )->gcMark( marked );
785 Lang::SinglePointPath2D::SinglePointPath2D( Kernel::ValueRef thePoint )
786 : thePoint_( thePoint )
789 DISPATCHIMPL( SinglePointPath2D );
791 Lang::SinglePointPath2D::~SinglePointPath2D( )
794 void
795 Lang::SinglePointPath2D::elementaryJob( std::stack< const Lang::Value * > * nodeStack, Lang::ElementaryPath2D * pth, Concrete::Coords2D * basePoint ) const
797 nodeStack->push( thePoint_.getPtr( ) );
800 void
801 Lang::SinglePointPath2D::gcMark( Kernel::GCMarkedSet & marked )
803 const_cast< Lang::Value * >( thePoint_.getPtr( ) )->gcMark( marked );
807 Lang::HeadedPath2D::HeadedPath2D( Kernel::ValueRef rear, const RefCountPtr< const Lang::ElementaryPath2D > & bodyPath, Kernel::ValueRef front )
808 : bodyPath_( new Lang::HeadedPath2D_helper( bodyPath ) ), rearPathPoint_( NullPtr< const Lang::Value >( ) ), frontPathPoint_( NullPtr< const Lang::Value >( ) )
810 if( bodyPath->isClosed( ) )
812 throw Exceptions::InternalError( strrefdup( "Attempt to create closed but headed path." ) );
814 if( bodyPath->empty( ) )
816 throw Exceptions::InternalError( strrefdup( "Attempt to create empty but headed path." ) );
819 if( bodyPath->size( ) == 1 )
821 Lang::ElementaryPath2D::const_iterator i = bodyPath->begin( );
822 Lang::PathPoint2D * newPoint = new Lang::PathPoint2D( RefCountPtr< const Lang::Coords2D >( new Lang::Coords2D( *( (*i)->mid_ ) ) ) );
823 newPoint->rear_ = rear;
824 newPoint->front_ = front;
825 rearPathPoint_ = Kernel::ValueRef( newPoint );
827 return;
830 // We reach here if there's more than 1 point in bodyPath
833 Lang::ElementaryPath2D::const_reverse_iterator i = bodyPath->rbegin( );
834 Lang::PathPoint2D * newPoint = new Lang::PathPoint2D( RefCountPtr< const Lang::Coords2D >( new Lang::Coords2D( *( (*i)->mid_ ) ) ) );
835 if( (*i)->rear_ != 0 )
837 newPoint->rear_ = RefCountPtr< const Lang::Coords2D >( new Lang::Coords2D( *( (*i)->rear_ ) ) );
839 newPoint->front_ = front;
840 frontPathPoint_ = Kernel::ValueRef( newPoint );
843 Lang::ElementaryPath2D::const_iterator i = bodyPath->begin( );
844 Lang::PathPoint2D * newPoint = new Lang::PathPoint2D( RefCountPtr< const Lang::Coords2D >( new Lang::Coords2D( *( (*i)->mid_ ) ) ) );
845 if( (*i)->front_ != 0 )
847 newPoint->front_ = RefCountPtr< const Lang::Coords2D >( new Lang::Coords2D( *( (*i)->front_ ) ) );
849 newPoint->rear_ = rear;
850 rearPathPoint_ = Kernel::ValueRef( newPoint );
854 DISPATCHIMPL( HeadedPath2D );
856 Lang::HeadedPath2D::~HeadedPath2D( )
859 void
860 Lang::HeadedPath2D::elementaryJob( std::stack< const Lang::Value * > * nodeStack, Lang::ElementaryPath2D * pth, Concrete::Coords2D * basePoint ) const
862 if( frontPathPoint_ == NullPtr< const Lang::Value >( ) )
864 // This means that there was just a single point in bodyPath
866 nodeStack->push( rearPathPoint_.getPtr( ) );
867 return;
869 else
871 nodeStack->push( frontPathPoint_.getPtr( ) );
872 nodeStack->push( bodyPath_.getPtr( ) );
873 nodeStack->push( rearPathPoint_.getPtr( ) );
877 void
878 Lang::HeadedPath2D::gcMark( Kernel::GCMarkedSet & marked )
880 const_cast< Lang::HeadedPath2D_helper * >( bodyPath_.getPtr( ) )->gcMark( marked );
881 const_cast< Lang::Value * >( rearPathPoint_.getPtr( ) )->gcMark( marked );
882 const_cast< Lang::Value * >( frontPathPoint_.getPtr( ) )->gcMark( marked );
886 Lang::HeadedPath2D_helper::HeadedPath2D_helper( const RefCountPtr< const Lang::ElementaryPath2D > & bodyPath )
887 : bodyPath_( bodyPath )
890 Lang::HeadedPath2D_helper::~HeadedPath2D_helper( )
893 void
894 Lang::HeadedPath2D_helper::elementaryJob( std::stack< const Lang::Value * > * nodeStack, Lang::ElementaryPath2D * pth, Concrete::Coords2D * basePoint ) const
896 if( bodyPath_->size( ) <= 1 )
898 throw Exceptions::InternalError( strrefdup( "HeadedPath2D_helper::elementaryJob was unexpectedly called with a short path." ) );
901 Lang::ElementaryPath2D::const_iterator i = bodyPath_->begin( );
902 ++i;
903 Lang::ElementaryPath2D::const_iterator end = bodyPath_->end( );
904 --end;
905 for( ; i != end; ++i )
907 pth->push_back( new Concrete::PathPoint2D( **i ) );
910 --i; /* Go back to the last point added to pth. */
911 *basePoint = *((*i)->mid_);
914 void
915 Lang::HeadedPath2D_helper::gcMark( Kernel::GCMarkedSet & marked )
917 const_cast< Lang::ElementaryPath2D * >( bodyPath_.getPtr( ) )->gcMark( marked );
922 Lang::MultiPath2D::MultiPath2D( )
925 DISPATCHIMPL( MultiPath2D );
927 Lang::MultiPath2D::~MultiPath2D( )
930 Lang::MultiPath2D *
931 Lang::MultiPath2D::clone( ) const
933 Lang::MultiPath2D * res = new Lang::MultiPath2D( );
934 for( const_iterator i = begin( ); i != end( ); ++i )
936 res->push_back( *i );
938 return res;
941 RefCountPtr< const Lang::Class > Lang::MultiPath2D::TypeID( new Lang::SystemFinalClass( strrefdup( "MultiPath" ) ) );
942 TYPEINFOIMPL( MultiPath2D );
944 void
945 Lang::MultiPath2D::show( std::ostream & os ) const
947 os << "Path with " << size( ) << " subpaths" ;
950 Kernel::VariableHandle
951 Lang::MultiPath2D::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
953 if( strcmp( fieldID, "list" ) == 0 )
955 RefCountPtr< const Lang::SingleList > res = Lang::THE_CONS_NULL;
956 for( const_reverse_iterator i = rbegin( ); i != rend( ); ++i )
958 res = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( *i ) ),
959 res ) );
961 return Kernel::VariableHandle( new Kernel::Variable( res ) );
963 throw Exceptions::NonExistentMember( getTypeName( ), fieldID );
966 RefCountPtr< const Lang::Geometric2D >
967 Lang::MultiPath2D::transformed( const Lang::Transform2D & tf, const RefCountPtr< const Lang::Geometric2D > & self ) const
969 Lang::MultiPath2D * res = new Lang::MultiPath2D( );
970 for( const_iterator i = begin( ); i != end( ); ++i )
972 res->push_back( (*i)->typed_transformed( tf ) );
974 return RefCountPtr< Lang::Geometric2D >( res );
977 RefCountPtr< const Lang::Geometric3D >
978 Lang::MultiPath2D::to3D( const RefCountPtr< const Lang::Geometric2D > & self ) const
980 Lang::MultiPath3D * res = new Lang::MultiPath3D( );
981 for( const_iterator i = begin( ); i != end( ); ++i )
983 res->push_back( (*i)->typed_to3D( *i ) );
985 return RefCountPtr< const Lang::Geometric3D >( res );
988 void
989 Lang::MultiPath2D::writePath( ostream & os ) const
991 for( const_iterator i = begin( ); i != end( ); ++i )
993 (*i)->writePath( os );
997 void
998 Lang::MultiPath2D::gcMark( Kernel::GCMarkedSet & marked )
1000 for( const_iterator i = begin( ); i != end( ); ++i )
1002 const_cast< Path2D * >( i->getPtr( ) )->gcMark( marked );
1007 Lang::MultiPath3D::MultiPath3D( )
1010 DISPATCHIMPL( MultiPath3D );
1012 Lang::MultiPath3D::~MultiPath3D( )
1015 Lang::MultiPath3D *
1016 Lang::MultiPath3D::clone( ) const
1018 Lang::MultiPath3D * res = new Lang::MultiPath3D( );
1019 for( const_iterator i = begin( ); i != end( ); ++i )
1021 res->push_back( *i );
1023 return res;
1026 RefCountPtr< const Lang::Class > Lang::MultiPath3D::TypeID( new Lang::SystemFinalClass( strrefdup( "MultiPath3D" ) ) );
1027 TYPEINFOIMPL( MultiPath3D );
1029 void
1030 Lang::MultiPath3D::show( std::ostream & os ) const
1032 os << "3D path with " << size( ) << " subpaths" ;
1035 Kernel::VariableHandle
1036 Lang::MultiPath3D::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
1038 if( strcmp( fieldID, "list" ) == 0 )
1040 RefCountPtr< const Lang::SingleList > res = Lang::THE_CONS_NULL;
1041 for( const_reverse_iterator i = rbegin( ); i != rend( ); ++i )
1043 res = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( *i ) ),
1044 res ) );
1046 return Kernel::VariableHandle( new Kernel::Variable( res ) );
1048 throw Exceptions::NonExistentMember( getTypeName( ), fieldID );
1051 RefCountPtr< const Lang::Geometric3D >
1052 Lang::MultiPath3D::transformed( const Lang::Transform3D & tf, const RefCountPtr< const Lang::Geometric3D > & self ) const
1054 Lang::MultiPath3D * res = new Lang::MultiPath3D( );
1055 for( const_iterator i = begin( ); i != end( ); ++i )
1057 res->push_back( (*i)->typed_transformed( tf ) );
1059 return RefCountPtr< Lang::Geometric3D >( res );
1062 RefCountPtr< const Lang::Geometric2D >
1063 Lang::MultiPath3D::to2D( const Kernel::PassedDyn & dyn, const RefCountPtr< const Lang::Geometric3D > & self ) const
1065 Concrete::Length eyez = dyn->getEyeZ( );
1066 Lang::MultiPath2D * res = new Lang::MultiPath2D( );
1067 for( const_iterator i = begin( ); i != end( ); ++i )
1069 res->push_back( (*i)->make2D( eyez ) );
1071 return RefCountPtr< const Lang::Geometric2D >( res );
1074 void
1075 Lang::MultiPath3D::gcMark( Kernel::GCMarkedSet & marked )
1077 for( const_iterator i = begin( ); i != end( ); ++i )
1079 const_cast< Path3D * >( i->getPtr( ) )->gcMark( marked );
1084 Lang::Path3D::Path3D( )
1085 : closed_( false )
1088 DISPATCHIMPL( Path3D );
1090 Lang::Path3D::~Path3D( )
1093 void
1094 Lang::Path3D::close( )
1096 closed_ = true;
1098 bool
1099 Lang::Path3D::isClosed( ) const
1101 return closed_;
1104 RefCountPtr< const Lang::Geometric3D >
1105 Lang::Path3D::transformed( const Lang::Transform3D & tf, const RefCountPtr< const Lang::Geometric3D > & self ) const
1107 typedef const Lang::Path3D ArgType;
1108 RefCountPtr< ArgType > selfTyped = self.down_cast< ArgType >( );
1109 if( selfTyped == NullPtr< ArgType >( ) )
1111 throw Exceptions::InternalError( strrefdup( "Path3D::to3D: self was of unexpected type." ) );
1114 return selfTyped->typed_transformed( tf );
1117 RefCountPtr< const Lang::Geometric2D >
1118 Lang::Path3D::to2D( const Kernel::PassedDyn & dyn, const RefCountPtr< const Lang::Geometric3D > & self ) const
1120 Concrete::Length eyez = dyn->getEyeZ( );
1121 return this->make2D( eyez );
1124 RefCountPtr< const Lang::Class > Lang::Path3D::TypeID( new Lang::SystemFinalClass( strrefdup( "Path3D" ) ) );
1125 TYPEINFOIMPL( Path3D );
1128 Lang::Path2Din3D::Path2Din3D( const RefCountPtr< const Lang::ElementaryPath2D > & elementaryPath2D )
1129 : elementaryPath2D_( elementaryPath2D )
1131 if( elementaryPath2D_->isClosed( ) )
1133 close( );
1137 Lang::Path2Din3D::~Path2Din3D( )
1140 RefCountPtr< const Lang::ElementaryPath2D >
1141 Lang::Path2Din3D::make2D( Concrete::Length eyez ) const
1143 // Since this path has not been transformed, it's "already" in 2D.
1145 return elementaryPath2D_;
1148 RefCountPtr< const Lang::Path3D >
1149 Lang::Path2Din3D::typed_transformed( const Lang::Transform3D & tf ) const
1151 return elementaryPath2D_->elementaryTransformed( tf );
1154 void
1155 Lang::Path2Din3D::elementaryJob( std::stack< const Lang::Path3D * > * nodeStack, Lang::ElementaryPath3D * pth, Concrete::Coords3D * basePoint ) const
1157 for( Lang::ElementaryPath2D::const_iterator i = elementaryPath2D_->begin( ); i != elementaryPath2D_->end( ); ++i )
1159 pth->push_back( (*i)->typed_to3D( ) );
1161 *basePoint = *(elementaryPath2D_->back( )->mid_);
1164 void
1165 Lang::Path2Din3D::gcMark( Kernel::GCMarkedSet & marked )
1167 const_cast< Lang::ElementaryPath2D * >( elementaryPath2D_.getPtr( ) )->gcMark( marked );
1172 Lang::ClosedPath3D::ClosedPath3D( RefCountPtr< const Lang::Path3D > openPath )
1173 : openPath_( openPath )
1175 close( );
1178 Lang::ClosedPath3D::~ClosedPath3D( )
1181 DISPATCHIMPL( ClosedPath3D );
1183 void
1184 Lang::ClosedPath3D::elementaryJob( std::stack< const Lang::Path3D * > * nodeStack, Lang::ElementaryPath3D * pth, Concrete::Coords3D * basePoint ) const
1186 openPath_->elementaryJob( nodeStack, pth, basePoint );
1188 * Although this seems incorrect, as the fact that this path is closed will not be respected,
1189 * this should not be a problem since it is not allowed to connect closed paths with anything.
1193 void
1194 Lang::ClosedPath3D::gcMark( Kernel::GCMarkedSet & marked )
1196 const_cast< Lang::Path3D * >( openPath_.getPtr( ) )->gcMark( marked );
1200 Lang::Connection3D::Connection3D( const RefCountPtr< const Lang::Path3D > & rear, const RefCountPtr< const Lang::Path3D > & front )
1201 : rear_( rear ), front_( front )
1204 Lang::Connection3D::~Connection3D( )
1207 void
1208 Lang::Connection3D::elementaryJob( std::stack< const Lang::Path3D * > * nodeStack, Lang::ElementaryPath3D * pth, Concrete::Coords3D * basePoint ) const
1210 nodeStack->push( front_.getPtr( ) );
1211 nodeStack->push( rear_.getPtr( ) );
1214 void
1215 Lang::Connection3D::gcMark( Kernel::GCMarkedSet & marked )
1217 const_cast< Lang::Path3D * >( rear_.getPtr( ) )->gcMark( marked );
1218 const_cast< Lang::Path3D * >( front_.getPtr( ) )->gcMark( marked );
1221 DISPATCHIMPL( Connection3D );
1224 Lang::SinglePointPath3D::SinglePointPath3D( const RefCountPtr< const Lang::PathPoint3D > & thePoint )
1225 : thePoint_( thePoint )
1228 Lang::SinglePointPath3D::SinglePointPath3D( const RefCountPtr< const Lang::Coords3D > & mid )
1229 : thePoint_( new Lang::PathPoint3D( mid ) )
1232 DISPATCHIMPL( SinglePointPath3D );
1234 Lang::SinglePointPath3D::~SinglePointPath3D( )
1237 void
1238 Lang::SinglePointPath3D::elementaryJob( std::stack< const Lang::Path3D * > * nodeStack, Lang::ElementaryPath3D * pth, Concrete::Coords3D * basePoint ) const
1240 thePoint_->elementaryJob( pth, basePoint );
1243 void
1244 Lang::SinglePointPath3D::gcMark( Kernel::GCMarkedSet & marked )
1246 const_cast< Lang::PathPoint3D * >( thePoint_.getPtr( ) )->gcMark( marked );
1250 Lang::CompositePath3D::CompositePath3D( )
1251 : elementaryPath_( NullPtr< const ElementaryPath3D >( ) )
1254 DISPATCHIMPL( CompositePath3D );
1256 Lang::CompositePath3D::~CompositePath3D( )
1259 Kernel::VariableHandle
1260 Lang::CompositePath3D::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
1262 computeElementaryPath( );
1263 return elementaryPath_->getField( fieldID, elementaryPath_ );
1266 RefCountPtr< const Lang::Path3D >
1267 Lang::CompositePath3D::typed_transformed( const Lang::Transform3D & tf ) const
1269 computeElementaryPath( );
1270 return elementaryPath_->typed_transformed( tf );
1273 RefCountPtr< const Lang::ElementaryPath2D >
1274 Lang::CompositePath3D::make2D( Concrete::Length eyez ) const
1276 computeElementaryPath( );
1277 return elementaryPath_->make2D( eyez );
1280 RefCountPtr< const Lang::ElementaryPath3D >
1281 Lang::CompositePath3D::getElementaryPath( ) const
1283 computeElementaryPath( );
1285 return elementaryPath_;
1288 void
1289 Lang::CompositePath3D::show( std::ostream & os ) const
1291 os << "Composite subpath in 3D" ;
1294 void
1295 Lang::CompositePath3D::computeElementaryPath( ) const
1297 if( elementaryPath_ != NullPtr< const Lang::ElementaryPath3D >( ) )
1299 return;
1301 Lang::ElementaryPath3D * pth = new Lang::ElementaryPath3D;
1303 Concrete::Coords3D basePoint( 0, 0, 0 );
1305 std::stack< const Lang::Path3D * > nodeStack;
1306 nodeStack.push( this );
1307 while( ! nodeStack.empty( ) )
1309 const Lang::Path3D * node = nodeStack.top( );
1310 nodeStack.pop( );
1311 node->elementaryJob( & nodeStack, pth, & basePoint );
1314 if( closed_ )
1316 pth->close( );
1319 elementaryPath_ = RefCountPtr< const Lang::ElementaryPath3D >( pth );
1323 Lang::HeadedPath3D::HeadedPath3D( Kernel::ValueRef rear, const RefCountPtr< const Lang::ElementaryPath3D > & bodyPath, Kernel::ValueRef front )
1324 : bodyPath_( new Lang::HeadedPath3D_helper( bodyPath ) ),
1325 rearPathPoint_( NullPtr< const Lang::SinglePointPath3D >( ) ),
1326 frontPathPoint_( NullPtr< const Lang::SinglePointPath3D >( ) )
1328 if( bodyPath->isClosed( ) )
1330 throw Exceptions::InternalError( strrefdup( "Attempt to create closed but headed path." ) );
1332 if( bodyPath->empty( ) )
1334 throw Exceptions::InternalError( strrefdup( "Attempt to create empty but headed path." ) );
1336 if( bodyPath->size( ) == 1 )
1338 Lang::ElementaryPath3D::const_iterator i = bodyPath->begin( );
1339 Lang::PathPoint3D * newPoint = new Lang::PathPoint3D( RefCountPtr< const Lang::Coords3D >( new Lang::Coords3D( *( (*i)->mid_ ) ) ) );
1340 newPoint->rear_ = rear;
1341 newPoint->front_ = front;
1342 rearPathPoint_ = RefCountPtr< const Lang::SinglePointPath3D >( new Lang::SinglePointPath3D( RefCountPtr< const Lang::PathPoint3D >( newPoint ) ) );
1344 return;
1347 // We reach here if there's more than one point in the body.
1350 Lang::ElementaryPath3D::const_reverse_iterator i = bodyPath->rbegin( );
1351 Lang::PathPoint3D * newPoint = new Lang::PathPoint3D( RefCountPtr< const Lang::Coords3D >( new Lang::Coords3D( *( (*i)->mid_ ) ) ) );
1352 if( (*i)->rear_ != 0 )
1354 newPoint->rear_ = RefCountPtr< const Lang::Coords3D >( new Lang::Coords3D( *( (*i)->rear_ ) ) );
1356 newPoint->front_ = front;
1357 frontPathPoint_ = RefCountPtr< const Lang::SinglePointPath3D >( new Lang::SinglePointPath3D( RefCountPtr< const Lang::PathPoint3D >( newPoint ) ) );
1360 Lang::ElementaryPath3D::const_iterator i = bodyPath->begin( );
1361 Lang::PathPoint3D * newPoint = new Lang::PathPoint3D( RefCountPtr< const Lang::Coords3D >( new Lang::Coords3D( *( (*i)->mid_ ) ) ) );
1362 if( (*i)->front_ != 0 )
1364 newPoint->front_ = RefCountPtr< const Lang::Coords3D >( new Lang::Coords3D( *( (*i)->front_ ) ) );
1366 newPoint->rear_ = rear;
1367 rearPathPoint_ = RefCountPtr< const Lang::SinglePointPath3D >( new Lang::SinglePointPath3D( RefCountPtr< const Lang::PathPoint3D >( newPoint ) ) );
1372 DISPATCHIMPL( HeadedPath3D );
1374 Lang::HeadedPath3D::~HeadedPath3D( )
1377 void
1378 Lang::HeadedPath3D::elementaryJob( std::stack< const Lang::Path3D * > * nodeStack, Lang::ElementaryPath3D * pth, Concrete::Coords3D * basePoint ) const
1380 if( frontPathPoint_ == NullPtr< const Lang::SinglePointPath3D >( ) )
1382 // This means that there was just a single point in bodyPath
1384 nodeStack->push( rearPathPoint_.getPtr( ) );
1385 return;
1387 else
1389 nodeStack->push( frontPathPoint_.getPtr( ) );
1390 nodeStack->push( bodyPath_.getPtr( ) );
1391 nodeStack->push( rearPathPoint_.getPtr( ) );
1395 void
1396 Lang::HeadedPath3D::gcMark( Kernel::GCMarkedSet & marked )
1398 const_cast< Lang::HeadedPath3D_helper * >( bodyPath_.getPtr( ) )->gcMark( marked );
1399 const_cast< Lang::SinglePointPath3D * >( rearPathPoint_.getPtr( ) )->gcMark( marked );
1400 const_cast< Lang::SinglePointPath3D * >( frontPathPoint_.getPtr( ) )->gcMark( marked );
1404 Lang::HeadedPath3D_helper::HeadedPath3D_helper( const RefCountPtr< const Lang::ElementaryPath3D > & bodyPath )
1405 : bodyPath_( bodyPath )
1408 Lang::HeadedPath3D_helper::~HeadedPath3D_helper( )
1411 void
1412 Lang::HeadedPath3D_helper::elementaryJob( std::stack< const Lang::Path3D * > * nodeStack, Lang::ElementaryPath3D * pth, Concrete::Coords3D * basePoint ) const
1414 if( bodyPath_->size( ) <= 1 )
1416 throw Exceptions::InternalError( strrefdup( "HeadedPath3D_helper::elementaryJob was unexpectedly called with a short path." ) );
1419 Lang::ElementaryPath3D::const_iterator i = bodyPath_->begin( );
1420 ++i;
1421 Lang::ElementaryPath3D::const_iterator end = bodyPath_->end( );
1422 --end;
1423 for( ; i != end; ++i )
1425 pth->push_back( new Concrete::PathPoint3D( **i ) );
1428 --i; /* Go back to the last point added to pth. */
1429 *basePoint = *((*i)->mid_);
1432 void
1433 Lang::HeadedPath3D_helper::gcMark( Kernel::GCMarkedSet & marked )
1435 const_cast< Lang::ElementaryPath3D * >( bodyPath_.getPtr( ) )->gcMark( marked );