"Correcting" the name of some path types in Shapes.
[shapes.git] / source / pathtypes.cc
blob7b4d1563c18c8cd2ec923cf45d9be42a07a03a4b
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 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 " << Interaction::DYNAMIC_VARIABLE_PREFIX << Lang::DYNAMIC_VARIABLE_ID_DEFAULT_UNIT << "." ;
86 throw Exceptions::MiscellaneousRequirement( strrefdup( msg ) );
89 void
90 Kernel::PolarHandleEmptyPromise::gcMark( Kernel::GCMarkedSet & marked ) const
95 void
96 Kernel::PolarHandleEmptyPromise::show( std::ostream & os ) const
98 os << "< undefined >" ;
102 Kernel::PolarHandleTruePromise::PolarHandleTruePromise( Kernel::Thunk * thunk )
103 : thunk_( thunk )
106 Kernel::PolarHandleTruePromise::~PolarHandleTruePromise( )
108 delete thunk_;
112 double
113 Kernel::PolarHandleTruePromise::force( const Concrete::PathPoint2D * specialUnitP0, const Concrete::PathPoint2D * specialUnitP1, bool reverse ) const
115 Kernel::ValueRef valUntyped = NullPtr< const Lang::Value >( );
117 /* Note that the use of a StoreValueContinuation relies on valUntyped being alive at the time the continuation is invoked.
119 bool done = false;
120 Kernel::EvalState evalState( 0,
122 NullPtr< Kernel::DynamicEnvironment >( ),
123 Kernel::ContRef( new Kernel::StoreValueContinuation( & valUntyped,
124 Kernel::ContRef( new Kernel::ExitContinuation( & done, thunk_->getExpr( )->loc( ) ) ),
125 thunk_->getExpr( )->loc( ) ) ) );
127 thunk_->force( & evalState, false ); /* note that the dynamic environment is set below, before evaluation begins. "false" means that the thunk may be forced repeatedly */
129 Kernel::SpecialUnitVariables * dynVars = new Kernel::SpecialUnitVariables;
130 dynVars->reverseDirection_ = reverse;
131 dynVars->p0_ = specialUnitP0;
132 dynVars->p1_ = specialUnitP1;
133 evalState.dyn_ = Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState.dyn_, dynVars ) );
135 while( ! done )
137 evalState.expr_->eval( & evalState );
140 typedef const Lang::Length ArgType;
141 ArgType * valPtr = dynamic_cast< ArgType * >( valUntyped.getPtr( ) );
142 if( valPtr == 0 )
144 throw Exceptions::TypeMismatch( thunk_->getExpr( )->loc( ), valUntyped->getTypeName( ), ArgType::staticTypeName( ) );
147 return valPtr->getScalar( );
150 void
151 Kernel::PolarHandleTruePromise::gcMark( Kernel::GCMarkedSet & marked ) const
153 if( thunk_ != 0 )
155 thunk_->gcMark( marked );
159 void
160 Kernel::PolarHandleTruePromise::show( std::ostream & os ) const
162 os << "Dynamic expression at " << thunk_->getExpr( )->loc( ) ;
166 Lang::PolarHandleBase::PolarHandleBase( )
169 DISPATCHIMPL( PolarHandleBase );
171 Lang::PolarHandleBase::~PolarHandleBase( )
174 RefCountPtr< const Lang::Class > Lang::PolarHandleBase::TypeID( new Lang::SystemFinalClass( strrefdup( "PolarHandle" ) ) );
175 TYPEINFOIMPL( PolarHandleBase );
178 Lang::PolarHandle2D::PolarHandle2D( const RefCountPtr< const Kernel::PolarHandlePromise > & rPromise, double a )
179 : rPromise_( rPromise ), a_( a )
182 DISPATCHIMPL( PolarHandle2D );
184 Lang::PolarHandle2D::~PolarHandle2D( )
187 void
188 Lang::PolarHandle2D::show( std::ostream & os ) const
190 os << "Completely specified" ;
193 void
194 Lang::PolarHandle2D::gcMark( Kernel::GCMarkedSet & marked )
196 rPromise_->gcMark( marked );
200 Lang::PolarHandle2DFree_a::PolarHandle2DFree_a( const RefCountPtr< const Kernel::PolarHandlePromise > & rPromise )
201 : rPromise_( rPromise )
204 DISPATCHIMPL( PolarHandle2DFree_a );
206 Lang::PolarHandle2DFree_a::~PolarHandle2DFree_a( )
209 void
210 Lang::PolarHandle2DFree_a::show( std::ostream & os ) const
212 os << "Free angle, promise pointer: " << rPromise_.getPtr( ) ;
215 void
216 Lang::PolarHandle2DFree_a::gcMark( Kernel::GCMarkedSet & marked )
218 rPromise_->gcMark( marked );
222 Lang::PolarHandle2DFree_r::PolarHandle2DFree_r( const RefCountPtr< const Kernel::PolarHandlePromise > & defaultModulus, double a )
223 : defaultModulus_( defaultModulus ), a_( a )
226 DISPATCHIMPL( PolarHandle2DFree_r );
228 Lang::PolarHandle2DFree_r::~PolarHandle2DFree_r( )
231 void
232 Lang::PolarHandle2DFree_r::show( std::ostream & os ) const
234 os << "Free modulus, angle = " << a_ ;
237 void
238 Lang::PolarHandle2DFree_r::gcMark( Kernel::GCMarkedSet & marked )
240 defaultModulus_->gcMark( marked );
244 Lang::PolarHandle2DFree_ra::PolarHandle2DFree_ra( const RefCountPtr< const Kernel::PolarHandlePromise > & defaultModulus )
245 : defaultModulus_( defaultModulus )
248 DISPATCHIMPL( PolarHandle2DFree_ra );
250 Lang::PolarHandle2DFree_ra::~PolarHandle2DFree_ra( )
253 void
254 Lang::PolarHandle2DFree_ra::show( std::ostream & os ) const
256 os << "Completely free" ;
259 void
260 Lang::PolarHandle2DFree_ra::gcMark( Kernel::GCMarkedSet & marked )
262 defaultModulus_->gcMark( marked );
266 Concrete::PathPoint2D::PathPoint2D( const Concrete::PathPoint2D & orig )
267 : rearState_( orig.rearState_ ), rearAngle_( orig.rearAngle_ ), rearModulus_( orig.rearModulus_ ),
268 rearModulusPromise_( NullPtr< Kernel::PolarHandlePromise >( ) ),
269 frontState_( orig.frontState_ ), frontAngle_( orig.frontAngle_ ), frontModulus_( orig.frontModulus_ ),
270 frontModulusPromise_( NullPtr< Kernel::PolarHandlePromise >( ) ),
271 defaultAngle_( orig.defaultAngle_ )
273 mid_ = new Concrete::Coords2D( *orig.mid_ );
275 if( orig.rear_ != orig.mid_ )
277 rear_ = new Concrete::Coords2D( *orig.rear_ );
279 else
281 rear_ = mid_;
283 if( orig.front_ != orig.mid_ )
285 front_ = new Concrete::Coords2D( *orig.front_ );
287 else
289 front_ = mid_;
293 /* The initial state is set to COMPLETE, even though theoretically, the angle towards the neighboring pathpoints should be computed.
294 * However, by setting the default rearAngle_ and frontAngle_ to NaN, we can replace an atan2 computation by an IS_NAN test.
296 Concrete::PathPoint2D::PathPoint2D( Concrete::Coords2D * mid )
297 : rearState_( COMPLETE ), rearAngle_( std::numeric_limits< double >::signaling_NaN( ) ), rearModulusPromise_( NullPtr< Kernel::PolarHandlePromise >( ) ),
298 frontState_( COMPLETE ), frontAngle_( std::numeric_limits< double >::signaling_NaN( ) ), frontModulusPromise_( NullPtr< Kernel::PolarHandlePromise >( ) ),
299 defaultAngle_( 0 ),
300 rear_( mid ), mid_( mid ), front_( mid )
303 Concrete::PathPoint2D::PathPoint2D( Concrete::Length midx, Concrete::Length midy )
304 : rearState_( COMPLETE ), rearAngle_( std::numeric_limits< double >::signaling_NaN( ) ), rearModulusPromise_( NullPtr< Kernel::PolarHandlePromise >( ) ),
305 frontState_( COMPLETE ), frontAngle_( std::numeric_limits< double >::signaling_NaN( ) ), frontModulusPromise_( NullPtr< Kernel::PolarHandlePromise >( ) ),
306 defaultAngle_( 0 ),
307 rear_( new Concrete::Coords2D( midx, midy ) ), mid_( rear_ ), front_( rear_ )
310 Concrete::PathPoint2D::~PathPoint2D( )
312 if( rear_ != 0 && rear_ != mid_ )
314 delete rear_;
316 if( mid_ != 0 )
318 delete mid_;
320 if( front_ != 0 && front_ != mid_ )
322 delete front_;
326 Concrete::PathPoint2D *
327 Concrete::PathPoint2D::transformed( const Lang::Transform2D & tf ) const
329 Concrete::PathPoint2D * res = new Concrete::PathPoint2D( mid_->transformedPtr( tf ) );
330 if( rear_ != mid_ )
332 res->rear_ = rear_->transformedPtr( tf );
334 if( front_ != mid_ )
336 res->front_ = front_->transformedPtr( tf );
338 return res;
341 Concrete::PathPoint3D *
342 Concrete::PathPoint2D::transformed( const Lang::Transform3D & tf ) const
344 Concrete::PathPoint3D * res = new Concrete::PathPoint3D( mid_->transformedPtr( tf ) );
345 if( rear_ != mid_ )
347 res->rear_ = rear_->transformedPtr( tf );
349 if( front_ != mid_ )
351 res->front_ = front_->transformedPtr( tf );
353 return res;
356 Concrete::PathPoint3D *
357 Concrete::PathPoint2D::typed_to3D( ) const
359 Concrete::PathPoint3D * res = new Concrete::PathPoint3D( *mid_ );
360 if( rear_ != mid_ )
362 res->rear_ = new Concrete::Coords3D( *rear_ );
364 if( front_ != mid_ )
366 res->front_ = new Concrete::Coords3D( *front_ );
368 return res;
372 Concrete::PathPoint3D::PathPoint3D( const Concrete::PathPoint3D & orig )
373 : mid_( new Concrete::Coords3D( *orig.mid_ ) )
375 if( orig.rear_ != orig.mid_ )
377 rear_ = new Concrete::Coords3D( *orig.rear_ );
379 else
381 rear_ = mid_;
384 if( orig.front_ != orig.mid_ )
386 front_ = new Concrete::Coords3D( *orig.front_ );
388 else
390 front_ = mid_;
394 Concrete::PathPoint3D::PathPoint3D( Concrete::Coords3D * mid )
395 : rear_( mid ), mid_( mid ), front_( mid )
398 Concrete::PathPoint3D::PathPoint3D( const Concrete::Coords2D & mid )
399 : rear_( new Concrete::Coords3D( mid ) ), mid_( rear_ ), front_( rear_ )
402 Concrete::PathPoint3D::PathPoint3D( Concrete::Length midx, Concrete::Length midy, Concrete::Length midz )
403 : rear_( new Concrete::Coords3D( midx, midy, midz ) ), mid_( rear_ ), front_( rear_ )
406 Concrete::PathPoint3D::~PathPoint3D( )
408 if( rear_ != 0 && rear_ != mid_ )
410 delete rear_;
412 if( mid_ != 0 )
414 delete mid_;
416 if( front_ != 0 && front_ != mid_ )
418 delete front_;
422 Concrete::PathPoint3D *
423 Concrete::PathPoint3D::transformed( const Lang::Transform3D & tf ) const
425 Concrete::PathPoint3D * res = new Concrete::PathPoint3D( mid_->transformedPtr( tf ) );
426 if( rear_ != mid_ )
428 res->rear_ = rear_->transformedPtr( tf );
430 if( front_ != mid_ )
432 res->front_ = front_->transformedPtr( tf );
434 return res;
437 Concrete::PathPoint2D *
438 Concrete::PathPoint3D::make2D( Concrete::Length eyez ) const
440 Concrete::PathPoint2D * res = new Concrete::PathPoint2D( mid_->make2D( eyez ) );
441 if( rear_ != mid_ )
443 res->rear_ = rear_->make2D( eyez );
445 if( front_ != mid_ )
447 res->front_ = front_->make2D( eyez );
449 return res;
452 Lang::PathPoint2D::PathPoint2D( const Lang::PathPoint2D & orig )
453 : rear_( orig.rear_ ), mid_( orig.mid_ ), front_( orig.front_ )
456 DISPATCHIMPL( PathPoint2D );
458 Lang::PathPoint2D::PathPoint2D( RefCountPtr< const Lang::Coords2D > mid )
459 : rear_( NullPtr< Lang::Value >( ) ), mid_( mid ), front_( NullPtr< Lang::Value >( ) )
462 Kernel::VariableHandle
463 Lang::PathPoint2D::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
465 if( strcmp( fieldID, "mid" ) == 0 )
467 return Kernel::VariableHandle( new Kernel::Variable( mid_ ) );
469 if( strcmp( fieldID, "rear" ) == 0 )
471 return Kernel::VariableHandle( new Kernel::Variable( rear_ ) );
473 if( strcmp( fieldID, "front" ) == 0 )
475 return Kernel::VariableHandle( new Kernel::Variable( front_ ) );
477 throw Exceptions::NonExistentMember( getTypeName( ), fieldID );
480 RefCountPtr< const Lang::Geometric2D >
481 Lang::PathPoint2D::transformed( const Lang::Transform2D & tf, const RefCountPtr< const Lang::Geometric2D > & self ) const
483 throw Exceptions::MiscellaneousRequirement( strrefdup( "A pathpoint by itself cannot be transformed." ) );
486 RefCountPtr< const Lang::Geometric3D >
487 Lang::PathPoint2D::to3D( const RefCountPtr< const Lang::Geometric2D > & self ) const
489 throw Exceptions::MiscellaneousRequirement( strrefdup( "A 2D pathpoint by itself cannot go 3D." ) );
492 void
493 Lang::PathPoint2D::gcMark( Kernel::GCMarkedSet & marked )
496 Lang::Value * tmp = const_cast< Lang::Value * >( rear_.getPtr( ) );
497 if( tmp != 0 )
499 tmp->gcMark( marked );
503 const_cast< Lang::Coords2D * >( mid_.getPtr( ) )->gcMark( marked );
506 Lang::Value * tmp = const_cast< Lang::Value * >( front_.getPtr( ) );
507 if( tmp != 0 )
509 tmp->gcMark( marked );
515 RefCountPtr< const Lang::Class > Lang::PathPoint2D::TypeID( new Lang::SystemFinalClass( strrefdup( "PathPoint" ) ) );
516 TYPEINFOIMPL( PathPoint2D );
519 Lang::PathPoint3D::PathPoint3D( const Lang::PathPoint3D & orig )
520 : rear_( orig.rear_ ), mid_( orig.mid_ ), front_( orig.front_ )
523 DISPATCHIMPL( PathPoint3D );
525 Lang::PathPoint3D::PathPoint3D( const RefCountPtr< const Lang::Coords3D > & mid )
526 : rear_( NullPtr< Lang::Coords3D >( ) ), mid_( mid ), front_( NullPtr< Lang::Coords3D >( ) )
529 Kernel::VariableHandle
530 Lang::PathPoint3D::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
532 if( strcmp( fieldID, "mid" ) == 0 )
534 return Kernel::VariableHandle( new Kernel::Variable( mid_ ) );
536 if( strcmp( fieldID, "rear" ) == 0 )
538 return Kernel::VariableHandle( new Kernel::Variable( rear_ ) );
540 if( strcmp( fieldID, "front" ) == 0 )
542 return Kernel::VariableHandle( new Kernel::Variable( front_ ) );
544 throw Exceptions::NonExistentMember( getTypeName( ), fieldID );
547 void
548 Lang::PathPoint3D::elementaryJob( Lang::ElementaryPath3D * pth, Concrete::Coords3D * basePoint ) const
550 Concrete::Coords3D * newMid = new Concrete::Coords3D( *basePoint, *mid_ );
551 *basePoint = *newMid;
552 Concrete::PathPoint3D * newPoint = new Concrete::PathPoint3D( newMid );
554 if( rear_ != NullPtr< const Lang::Coords3D >( ) )
556 newPoint->rear_ = new Concrete::Coords3D( *basePoint, *rear_ );
559 if( front_ != NullPtr< const Lang::Coords3D >( ) )
561 newPoint->front_ = new Concrete::Coords3D( *basePoint, *front_ );
564 pth->push_back( newPoint );
567 RefCountPtr< const Lang::Geometric3D >
568 Lang::PathPoint3D::transformed( const Lang::Transform3D & tf, const RefCountPtr< const Lang::Geometric3D > & self ) const
570 PathPoint3D * res = new Lang::PathPoint3D( RefCountPtr< const Lang::Coords3D >( mid_->transformedPtr( tf ) ) );
572 if( rear_ != NullPtr< const Lang::Coords3D >( ) )
574 res->rear_ = RefCountPtr< const Lang::Coords3D >( rear_->transformedPtr( tf ) );
577 if( front_ != NullPtr< const Lang::Coords3D >( ) )
579 res->front_ = RefCountPtr< const Lang::Coords3D >( front_->transformedPtr( tf ) );
582 return RefCountPtr< const Lang::Geometric3D >( res );
585 RefCountPtr< const Lang::Geometric2D >
586 Lang::PathPoint3D::to2D( const Kernel::PassedDyn & dyn, const RefCountPtr< const Lang::Geometric3D > & self ) const
588 Concrete::Length eyez = dyn->getEyeZ( );
589 PathPoint2D * res = new Lang::PathPoint2D( mid_->make2D( eyez ) );
591 if( rear_ != NullPtr< const Lang::Coords3D >( ) )
593 res->rear_ = rear_->make2D( eyez );
596 if( front_ != NullPtr< const Lang::Coords3D >( ) )
598 res->front_ = front_->make2D( eyez );
601 return RefCountPtr< const Lang::Geometric2D >( res );
604 void
605 Lang::PathPoint3D::gcMark( Kernel::GCMarkedSet & marked )
608 Lang::Coords3D * tmp = const_cast< Lang::Coords3D * >( rear_.getPtr( ) );
609 if( tmp != 0 )
611 tmp->gcMark( marked );
615 const_cast< Lang::Coords3D * >( mid_.getPtr( ) )->gcMark( marked );
618 Lang::Coords3D * tmp = const_cast< Lang::Coords3D * >( front_.getPtr( ) );
619 if( tmp != 0 )
621 tmp->gcMark( marked );
626 RefCountPtr< const Lang::Class > Lang::PathPoint3D::TypeID( new Lang::SystemFinalClass( strrefdup( "PathPoint" ) ) );
627 TYPEINFOIMPL( PathPoint3D );
630 Lang::Path2D::Path2D( )
631 : closed_( false )
634 DISPATCHIMPL( Path2D );
636 Lang::Path2D::~Path2D( )
639 void
640 Lang::Path2D::close( )
642 closed_ = true;
644 bool
645 Lang::Path2D::isClosed( ) const
647 return closed_;
650 RefCountPtr< const Lang::Geometric2D >
651 Lang::Path2D::transformed( const Lang::Transform2D & tf, const RefCountPtr< const Lang::Geometric2D > & self ) const
653 typedef const Lang::Path2D ArgType;
654 RefCountPtr< ArgType > selfTyped = self.down_cast< ArgType >( );
655 if( selfTyped == NullPtr< ArgType >( ) )
657 throw Exceptions::InternalError( strrefdup( "Path2D::to3D: self was of unexpected type." ) );
660 return selfTyped->typed_transformed( tf );
663 RefCountPtr< const Lang::Geometric3D >
664 Lang::Path2D::to3D( const RefCountPtr< const Lang::Geometric2D > & self ) const
666 typedef const Lang::Path2D ArgType;
667 RefCountPtr< ArgType > selfTyped = self.down_cast< ArgType >( );
668 if( selfTyped == NullPtr< ArgType >( ) )
670 throw Exceptions::InternalError( strrefdup( "Path2D::to3D: self was of unexpected type." ) );
673 return selfTyped->typed_to3D( selfTyped );
676 RefCountPtr< const Lang::Class > Lang::Path2D::TypeID( new Lang::SystemFinalClass( strrefdup( "Path" ) ) );
677 TYPEINFOIMPL( Path2D );
680 Lang::CompositePath2D::CompositePath2D( )
681 : elementaryPath_( NullPtr< const ElementaryPath2D >( ) )
684 DISPATCHIMPL( CompositePath2D );
686 Lang::CompositePath2D::~CompositePath2D( )
689 Kernel::VariableHandle
690 Lang::CompositePath2D::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
692 computeElementaryPath( );
693 return elementaryPath_->getField( fieldID, elementaryPath_ );
696 RefCountPtr< const Lang::Path2D >
697 Lang::CompositePath2D::typed_transformed( const Lang::Transform2D & tf ) const
699 computeElementaryPath( );
700 return elementaryPath_->typed_transformed( tf );
703 RefCountPtr< const Lang::Path3D >
704 Lang::CompositePath2D::typed_to3D( const RefCountPtr< const Lang::Path2D > & self ) const
706 computeElementaryPath( );
707 return RefCountPtr< const Lang::Path3D >( new Lang::Path2Din3D( elementaryPath_ ) );
710 void
711 Lang::CompositePath2D::writePath( ostream & os ) const
713 computeElementaryPath( );
714 elementaryPath_->writePath( os );
717 RefCountPtr< const Lang::ElementaryPath2D >
718 Lang::CompositePath2D::getElementaryPath( ) const
720 computeElementaryPath( );
721 return elementaryPath_;
724 void
725 Lang::CompositePath2D::show( std::ostream & os ) const
727 os << "Composite subpath" ;
731 Lang::ClosedPath2D::ClosedPath2D( RefCountPtr< const Lang::Path2D > openPath )
732 : openPath_( openPath )
734 close( );
737 Lang::ClosedPath2D::~ClosedPath2D( )
740 DISPATCHIMPL( ClosedPath2D );
742 void
743 Lang::ClosedPath2D::elementaryJob( std::stack< const Lang::Value * > * nodeStack, Lang::ElementaryPath2D * pth, Concrete::Coords2D * basePoint ) const
745 openPath_->elementaryJob( nodeStack, pth, basePoint );
747 * Although this seems incorrect, as the fact that this path is closed will not be respected,
748 * this should not be a problem since it is not allowed to connect closed paths with anything.
752 void
753 Lang::ClosedPath2D::gcMark( Kernel::GCMarkedSet & marked )
755 const_cast< Lang::Path2D * >( openPath_.getPtr( ) )->gcMark( marked );
759 Lang::Connection2D::Connection2D( Kernel::ValueRef rear, Kernel::ValueRef front )
760 : rear_( rear ), front_( front )
763 DISPATCHIMPL( Connection2D );
765 Lang::Connection2D::~Connection2D( )
768 void
769 Lang::Connection2D::elementaryJob( std::stack< const Lang::Value * > * nodeStack, Lang::ElementaryPath2D * pth, Concrete::Coords2D * basePoint ) const
771 nodeStack->push( front_.getPtr( ) );
772 nodeStack->push( rear_.getPtr( ) );
775 void
776 Lang::Connection2D::gcMark( Kernel::GCMarkedSet & marked )
778 const_cast< Lang::Value * >( rear_.getPtr( ) )->gcMark( marked );
779 const_cast< Lang::Value * >( front_.getPtr( ) )->gcMark( marked );
783 Lang::SinglePointPath2D::SinglePointPath2D( Kernel::ValueRef thePoint )
784 : thePoint_( thePoint )
787 DISPATCHIMPL( SinglePointPath2D );
789 Lang::SinglePointPath2D::~SinglePointPath2D( )
792 void
793 Lang::SinglePointPath2D::elementaryJob( std::stack< const Lang::Value * > * nodeStack, Lang::ElementaryPath2D * pth, Concrete::Coords2D * basePoint ) const
795 nodeStack->push( thePoint_.getPtr( ) );
798 void
799 Lang::SinglePointPath2D::gcMark( Kernel::GCMarkedSet & marked )
801 const_cast< Lang::Value * >( thePoint_.getPtr( ) )->gcMark( marked );
805 Lang::HeadedPath2D::HeadedPath2D( Kernel::ValueRef rear, const RefCountPtr< const Lang::ElementaryPath2D > & bodyPath, Kernel::ValueRef front )
806 : bodyPath_( new Lang::HeadedPath2D_helper( bodyPath ) ), rearPathPoint_( NullPtr< const Lang::Value >( ) ), frontPathPoint_( NullPtr< const Lang::Value >( ) )
808 if( bodyPath->isClosed( ) )
810 throw Exceptions::InternalError( strrefdup( "Attempt to create closed but headed path." ) );
812 if( bodyPath->empty( ) )
814 throw Exceptions::InternalError( strrefdup( "Attempt to create empty but headed path." ) );
817 if( bodyPath->size( ) == 1 )
819 Lang::ElementaryPath2D::const_iterator i = bodyPath->begin( );
820 Lang::PathPoint2D * newPoint = new Lang::PathPoint2D( RefCountPtr< const Lang::Coords2D >( new Lang::Coords2D( *( (*i)->mid_ ) ) ) );
821 newPoint->rear_ = rear;
822 newPoint->front_ = front;
823 rearPathPoint_ = Kernel::ValueRef( newPoint );
825 return;
828 // We reach here if there's more than 1 point in bodyPath
831 Lang::ElementaryPath2D::const_reverse_iterator i = bodyPath->rbegin( );
832 Lang::PathPoint2D * newPoint = new Lang::PathPoint2D( RefCountPtr< const Lang::Coords2D >( new Lang::Coords2D( *( (*i)->mid_ ) ) ) );
833 if( (*i)->rear_ != 0 )
835 newPoint->rear_ = RefCountPtr< const Lang::Coords2D >( new Lang::Coords2D( *( (*i)->rear_ ) ) );
837 newPoint->front_ = front;
838 frontPathPoint_ = Kernel::ValueRef( newPoint );
841 Lang::ElementaryPath2D::const_iterator i = bodyPath->begin( );
842 Lang::PathPoint2D * newPoint = new Lang::PathPoint2D( RefCountPtr< const Lang::Coords2D >( new Lang::Coords2D( *( (*i)->mid_ ) ) ) );
843 if( (*i)->front_ != 0 )
845 newPoint->front_ = RefCountPtr< const Lang::Coords2D >( new Lang::Coords2D( *( (*i)->front_ ) ) );
847 newPoint->rear_ = rear;
848 rearPathPoint_ = Kernel::ValueRef( newPoint );
852 DISPATCHIMPL( HeadedPath2D );
854 Lang::HeadedPath2D::~HeadedPath2D( )
857 void
858 Lang::HeadedPath2D::elementaryJob( std::stack< const Lang::Value * > * nodeStack, Lang::ElementaryPath2D * pth, Concrete::Coords2D * basePoint ) const
860 if( frontPathPoint_ == NullPtr< const Lang::Value >( ) )
862 // This means that there was just a single point in bodyPath
864 nodeStack->push( rearPathPoint_.getPtr( ) );
865 return;
867 else
869 nodeStack->push( frontPathPoint_.getPtr( ) );
870 nodeStack->push( bodyPath_.getPtr( ) );
871 nodeStack->push( rearPathPoint_.getPtr( ) );
875 void
876 Lang::HeadedPath2D::gcMark( Kernel::GCMarkedSet & marked )
878 const_cast< Lang::HeadedPath2D_helper * >( bodyPath_.getPtr( ) )->gcMark( marked );
879 const_cast< Lang::Value * >( rearPathPoint_.getPtr( ) )->gcMark( marked );
880 const_cast< Lang::Value * >( frontPathPoint_.getPtr( ) )->gcMark( marked );
884 Lang::HeadedPath2D_helper::HeadedPath2D_helper( const RefCountPtr< const Lang::ElementaryPath2D > & bodyPath )
885 : bodyPath_( bodyPath )
888 Lang::HeadedPath2D_helper::~HeadedPath2D_helper( )
891 void
892 Lang::HeadedPath2D_helper::elementaryJob( std::stack< const Lang::Value * > * nodeStack, Lang::ElementaryPath2D * pth, Concrete::Coords2D * basePoint ) const
894 if( bodyPath_->size( ) <= 1 )
896 throw Exceptions::InternalError( strrefdup( "HeadedPath2D_helper::elementaryJob was unexpectedly called with a short path." ) );
899 Lang::ElementaryPath2D::const_iterator i = bodyPath_->begin( );
900 ++i;
901 Lang::ElementaryPath2D::const_iterator end = bodyPath_->end( );
902 --end;
903 for( ; i != end; ++i )
905 pth->push_back( new Concrete::PathPoint2D( **i ) );
908 --i; /* Go back to the last point added to pth. */
909 *basePoint = *((*i)->mid_);
912 void
913 Lang::HeadedPath2D_helper::gcMark( Kernel::GCMarkedSet & marked )
915 const_cast< Lang::ElementaryPath2D * >( bodyPath_.getPtr( ) )->gcMark( marked );
920 Lang::MultiPath2D::MultiPath2D( )
923 DISPATCHIMPL( MultiPath2D );
925 Lang::MultiPath2D::~MultiPath2D( )
928 Lang::MultiPath2D *
929 Lang::MultiPath2D::clone( ) const
931 Lang::MultiPath2D * res = new Lang::MultiPath2D( );
932 for( const_iterator i = begin( ); i != end( ); ++i )
934 res->push_back( *i );
936 return res;
939 RefCountPtr< const Lang::Class > Lang::MultiPath2D::TypeID( new Lang::SystemFinalClass( strrefdup( "MultiPath" ) ) );
940 TYPEINFOIMPL( MultiPath2D );
942 void
943 Lang::MultiPath2D::show( std::ostream & os ) const
945 os << "Path with " << size( ) << " subpaths" ;
948 RefCountPtr< const Lang::Geometric2D >
949 Lang::MultiPath2D::transformed( const Lang::Transform2D & tf, const RefCountPtr< const Lang::Geometric2D > & self ) const
951 Lang::MultiPath2D * res = new Lang::MultiPath2D( );
952 for( const_iterator i = begin( ); i != end( ); ++i )
954 res->push_back( (*i)->typed_transformed( tf ) );
956 return RefCountPtr< Lang::Geometric2D >( res );
959 RefCountPtr< const Lang::Geometric3D >
960 Lang::MultiPath2D::to3D( const RefCountPtr< const Lang::Geometric2D > & self ) const
962 Lang::MultiPath3D * res = new Lang::MultiPath3D( );
963 for( const_iterator i = begin( ); i != end( ); ++i )
965 res->push_back( (*i)->typed_to3D( *i ) );
967 return RefCountPtr< const Lang::Geometric3D >( res );
970 void
971 Lang::MultiPath2D::writePath( ostream & os ) const
973 for( const_iterator i = begin( ); i != end( ); ++i )
975 (*i)->writePath( os );
979 void
980 Lang::MultiPath2D::gcMark( Kernel::GCMarkedSet & marked )
982 for( const_iterator i = begin( ); i != end( ); ++i )
984 const_cast< Path2D * >( i->getPtr( ) )->gcMark( marked );
989 Lang::MultiPath3D::MultiPath3D( )
992 DISPATCHIMPL( MultiPath3D );
994 Lang::MultiPath3D::~MultiPath3D( )
997 Lang::MultiPath3D *
998 Lang::MultiPath3D::clone( ) const
1000 Lang::MultiPath3D * res = new Lang::MultiPath3D( );
1001 for( const_iterator i = begin( ); i != end( ); ++i )
1003 res->push_back( *i );
1005 return res;
1008 RefCountPtr< const Lang::Class > Lang::MultiPath3D::TypeID( new Lang::SystemFinalClass( strrefdup( "MultiPath3D" ) ) );
1009 TYPEINFOIMPL( MultiPath3D );
1011 void
1012 Lang::MultiPath3D::show( std::ostream & os ) const
1014 os << "3D path with " << size( ) << " subpaths" ;
1017 RefCountPtr< const Lang::Geometric3D >
1018 Lang::MultiPath3D::transformed( const Lang::Transform3D & tf, const RefCountPtr< const Lang::Geometric3D > & self ) const
1020 Lang::MultiPath3D * res = new Lang::MultiPath3D( );
1021 for( const_iterator i = begin( ); i != end( ); ++i )
1023 res->push_back( (*i)->typed_transformed( tf ) );
1025 return RefCountPtr< Lang::Geometric3D >( res );
1028 RefCountPtr< const Lang::Geometric2D >
1029 Lang::MultiPath3D::to2D( const Kernel::PassedDyn & dyn, const RefCountPtr< const Lang::Geometric3D > & self ) const
1031 Concrete::Length eyez = dyn->getEyeZ( );
1032 Lang::MultiPath2D * res = new Lang::MultiPath2D( );
1033 for( const_iterator i = begin( ); i != end( ); ++i )
1035 res->push_back( (*i)->make2D( eyez ) );
1037 return RefCountPtr< const Lang::Geometric2D >( res );
1040 void
1041 Lang::MultiPath3D::gcMark( Kernel::GCMarkedSet & marked )
1043 for( const_iterator i = begin( ); i != end( ); ++i )
1045 const_cast< Path3D * >( i->getPtr( ) )->gcMark( marked );
1050 Lang::Path3D::Path3D( )
1051 : closed_( false )
1054 DISPATCHIMPL( Path3D );
1056 Lang::Path3D::~Path3D( )
1059 void
1060 Lang::Path3D::close( )
1062 closed_ = true;
1064 bool
1065 Lang::Path3D::isClosed( ) const
1067 return closed_;
1070 RefCountPtr< const Lang::Geometric3D >
1071 Lang::Path3D::transformed( const Lang::Transform3D & tf, const RefCountPtr< const Lang::Geometric3D > & self ) const
1073 typedef const Lang::Path3D ArgType;
1074 RefCountPtr< ArgType > selfTyped = self.down_cast< ArgType >( );
1075 if( selfTyped == NullPtr< ArgType >( ) )
1077 throw Exceptions::InternalError( strrefdup( "Path3D::to3D: self was of unexpected type." ) );
1080 return selfTyped->typed_transformed( tf );
1083 RefCountPtr< const Lang::Geometric2D >
1084 Lang::Path3D::to2D( const Kernel::PassedDyn & dyn, const RefCountPtr< const Lang::Geometric3D > & self ) const
1086 Concrete::Length eyez = dyn->getEyeZ( );
1087 return this->make2D( eyez );
1090 RefCountPtr< const Lang::Class > Lang::Path3D::TypeID( new Lang::SystemFinalClass( strrefdup( "Path3D" ) ) );
1091 TYPEINFOIMPL( Path3D );
1094 Lang::Path2Din3D::Path2Din3D( const RefCountPtr< const Lang::ElementaryPath2D > & elementaryPath2D )
1095 : elementaryPath2D_( elementaryPath2D )
1097 if( elementaryPath2D_->isClosed( ) )
1099 close( );
1103 Lang::Path2Din3D::~Path2Din3D( )
1106 RefCountPtr< const Lang::ElementaryPath2D >
1107 Lang::Path2Din3D::make2D( Concrete::Length eyez ) const
1109 // Since this path has not been transformed, it's "already" in 2D.
1111 return elementaryPath2D_;
1114 RefCountPtr< const Lang::Path3D >
1115 Lang::Path2Din3D::typed_transformed( const Lang::Transform3D & tf ) const
1117 return elementaryPath2D_->elementaryTransformed( tf );
1120 void
1121 Lang::Path2Din3D::elementaryJob( std::stack< const Lang::Path3D * > * nodeStack, Lang::ElementaryPath3D * pth, Concrete::Coords3D * basePoint ) const
1123 for( Lang::ElementaryPath2D::const_iterator i = elementaryPath2D_->begin( ); i != elementaryPath2D_->end( ); ++i )
1125 pth->push_back( (*i)->typed_to3D( ) );
1127 *basePoint = *(elementaryPath2D_->back( )->mid_);
1130 void
1131 Lang::Path2Din3D::gcMark( Kernel::GCMarkedSet & marked )
1133 const_cast< Lang::ElementaryPath2D * >( elementaryPath2D_.getPtr( ) )->gcMark( marked );
1138 Lang::ClosedPath3D::ClosedPath3D( RefCountPtr< const Lang::Path3D > openPath )
1139 : openPath_( openPath )
1141 close( );
1144 Lang::ClosedPath3D::~ClosedPath3D( )
1147 DISPATCHIMPL( ClosedPath3D );
1149 void
1150 Lang::ClosedPath3D::elementaryJob( std::stack< const Lang::Path3D * > * nodeStack, Lang::ElementaryPath3D * pth, Concrete::Coords3D * basePoint ) const
1152 openPath_->elementaryJob( nodeStack, pth, basePoint );
1154 * Although this seems incorrect, as the fact that this path is closed will not be respected,
1155 * this should not be a problem since it is not allowed to connect closed paths with anything.
1159 void
1160 Lang::ClosedPath3D::gcMark( Kernel::GCMarkedSet & marked )
1162 const_cast< Lang::Path3D * >( openPath_.getPtr( ) )->gcMark( marked );
1166 Lang::Connection3D::Connection3D( const RefCountPtr< const Lang::Path3D > & rear, const RefCountPtr< const Lang::Path3D > & front )
1167 : rear_( rear ), front_( front )
1170 Lang::Connection3D::~Connection3D( )
1173 void
1174 Lang::Connection3D::elementaryJob( std::stack< const Lang::Path3D * > * nodeStack, Lang::ElementaryPath3D * pth, Concrete::Coords3D * basePoint ) const
1176 nodeStack->push( front_.getPtr( ) );
1177 nodeStack->push( rear_.getPtr( ) );
1180 void
1181 Lang::Connection3D::gcMark( Kernel::GCMarkedSet & marked )
1183 const_cast< Lang::Path3D * >( rear_.getPtr( ) )->gcMark( marked );
1184 const_cast< Lang::Path3D * >( front_.getPtr( ) )->gcMark( marked );
1187 DISPATCHIMPL( Connection3D );
1190 Lang::SinglePointPath3D::SinglePointPath3D( const RefCountPtr< const Lang::PathPoint3D > & thePoint )
1191 : thePoint_( thePoint )
1194 Lang::SinglePointPath3D::SinglePointPath3D( const RefCountPtr< const Lang::Coords3D > & mid )
1195 : thePoint_( new Lang::PathPoint3D( mid ) )
1198 DISPATCHIMPL( SinglePointPath3D );
1200 Lang::SinglePointPath3D::~SinglePointPath3D( )
1203 void
1204 Lang::SinglePointPath3D::elementaryJob( std::stack< const Lang::Path3D * > * nodeStack, Lang::ElementaryPath3D * pth, Concrete::Coords3D * basePoint ) const
1206 thePoint_->elementaryJob( pth, basePoint );
1209 void
1210 Lang::SinglePointPath3D::gcMark( Kernel::GCMarkedSet & marked )
1212 const_cast< Lang::PathPoint3D * >( thePoint_.getPtr( ) )->gcMark( marked );
1216 Lang::CompositePath3D::CompositePath3D( )
1217 : elementaryPath_( NullPtr< const ElementaryPath3D >( ) )
1220 DISPATCHIMPL( CompositePath3D );
1222 Lang::CompositePath3D::~CompositePath3D( )
1225 Kernel::VariableHandle
1226 Lang::CompositePath3D::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
1228 computeElementaryPath( );
1229 return elementaryPath_->getField( fieldID, elementaryPath_ );
1232 RefCountPtr< const Lang::Path3D >
1233 Lang::CompositePath3D::typed_transformed( const Lang::Transform3D & tf ) const
1235 computeElementaryPath( );
1236 return elementaryPath_->typed_transformed( tf );
1239 RefCountPtr< const Lang::ElementaryPath2D >
1240 Lang::CompositePath3D::make2D( Concrete::Length eyez ) const
1242 computeElementaryPath( );
1243 return elementaryPath_->make2D( eyez );
1246 RefCountPtr< const Lang::ElementaryPath3D >
1247 Lang::CompositePath3D::getElementaryPath( ) const
1249 computeElementaryPath( );
1251 return elementaryPath_;
1254 void
1255 Lang::CompositePath3D::show( std::ostream & os ) const
1257 os << "Composite subpath in 3D" ;
1260 void
1261 Lang::CompositePath3D::computeElementaryPath( ) const
1263 if( elementaryPath_ != NullPtr< const Lang::ElementaryPath3D >( ) )
1265 return;
1267 Lang::ElementaryPath3D * pth = new Lang::ElementaryPath3D;
1269 Concrete::Coords3D basePoint( 0, 0, 0 );
1271 std::stack< const Lang::Path3D * > nodeStack;
1272 nodeStack.push( this );
1273 while( ! nodeStack.empty( ) )
1275 const Lang::Path3D * node = nodeStack.top( );
1276 nodeStack.pop( );
1277 node->elementaryJob( & nodeStack, pth, & basePoint );
1280 if( closed_ )
1282 pth->close( );
1285 elementaryPath_ = RefCountPtr< const Lang::ElementaryPath3D >( pth );
1289 Lang::HeadedPath3D::HeadedPath3D( Kernel::ValueRef rear, const RefCountPtr< const Lang::ElementaryPath3D > & bodyPath, Kernel::ValueRef front )
1290 : bodyPath_( new Lang::HeadedPath3D_helper( bodyPath ) ),
1291 rearPathPoint_( NullPtr< const Lang::SinglePointPath3D >( ) ),
1292 frontPathPoint_( NullPtr< const Lang::SinglePointPath3D >( ) )
1294 if( bodyPath->isClosed( ) )
1296 throw Exceptions::InternalError( strrefdup( "Attempt to create closed but headed path." ) );
1298 if( bodyPath->empty( ) )
1300 throw Exceptions::InternalError( strrefdup( "Attempt to create empty but headed path." ) );
1302 if( bodyPath->size( ) == 1 )
1304 Lang::ElementaryPath3D::const_iterator i = bodyPath->begin( );
1305 Lang::PathPoint3D * newPoint = new Lang::PathPoint3D( RefCountPtr< const Lang::Coords3D >( new Lang::Coords3D( *( (*i)->mid_ ) ) ) );
1306 newPoint->rear_ = rear;
1307 newPoint->front_ = front;
1308 rearPathPoint_ = RefCountPtr< const Lang::SinglePointPath3D >( new Lang::SinglePointPath3D( RefCountPtr< const Lang::PathPoint3D >( newPoint ) ) );
1310 return;
1313 // We reach here if there's more than one point in the body.
1316 Lang::ElementaryPath3D::const_reverse_iterator i = bodyPath->rbegin( );
1317 Lang::PathPoint3D * newPoint = new Lang::PathPoint3D( RefCountPtr< const Lang::Coords3D >( new Lang::Coords3D( *( (*i)->mid_ ) ) ) );
1318 if( (*i)->rear_ != 0 )
1320 newPoint->rear_ = RefCountPtr< const Lang::Coords3D >( new Lang::Coords3D( *( (*i)->rear_ ) ) );
1322 newPoint->front_ = front;
1323 frontPathPoint_ = RefCountPtr< const Lang::SinglePointPath3D >( new Lang::SinglePointPath3D( RefCountPtr< const Lang::PathPoint3D >( newPoint ) ) );
1326 Lang::ElementaryPath3D::const_iterator i = bodyPath->begin( );
1327 Lang::PathPoint3D * newPoint = new Lang::PathPoint3D( RefCountPtr< const Lang::Coords3D >( new Lang::Coords3D( *( (*i)->mid_ ) ) ) );
1328 if( (*i)->front_ != 0 )
1330 newPoint->front_ = RefCountPtr< const Lang::Coords3D >( new Lang::Coords3D( *( (*i)->front_ ) ) );
1332 newPoint->rear_ = rear;
1333 rearPathPoint_ = RefCountPtr< const Lang::SinglePointPath3D >( new Lang::SinglePointPath3D( RefCountPtr< const Lang::PathPoint3D >( newPoint ) ) );
1338 DISPATCHIMPL( HeadedPath3D );
1340 Lang::HeadedPath3D::~HeadedPath3D( )
1343 void
1344 Lang::HeadedPath3D::elementaryJob( std::stack< const Lang::Path3D * > * nodeStack, Lang::ElementaryPath3D * pth, Concrete::Coords3D * basePoint ) const
1346 if( frontPathPoint_ == NullPtr< const Lang::SinglePointPath3D >( ) )
1348 // This means that there was just a single point in bodyPath
1350 nodeStack->push( rearPathPoint_.getPtr( ) );
1351 return;
1353 else
1355 nodeStack->push( frontPathPoint_.getPtr( ) );
1356 nodeStack->push( bodyPath_.getPtr( ) );
1357 nodeStack->push( rearPathPoint_.getPtr( ) );
1361 void
1362 Lang::HeadedPath3D::gcMark( Kernel::GCMarkedSet & marked )
1364 const_cast< Lang::HeadedPath3D_helper * >( bodyPath_.getPtr( ) )->gcMark( marked );
1365 const_cast< Lang::SinglePointPath3D * >( rearPathPoint_.getPtr( ) )->gcMark( marked );
1366 const_cast< Lang::SinglePointPath3D * >( frontPathPoint_.getPtr( ) )->gcMark( marked );
1370 Lang::HeadedPath3D_helper::HeadedPath3D_helper( const RefCountPtr< const Lang::ElementaryPath3D > & bodyPath )
1371 : bodyPath_( bodyPath )
1374 Lang::HeadedPath3D_helper::~HeadedPath3D_helper( )
1377 void
1378 Lang::HeadedPath3D_helper::elementaryJob( std::stack< const Lang::Path3D * > * nodeStack, Lang::ElementaryPath3D * pth, Concrete::Coords3D * basePoint ) const
1380 if( bodyPath_->size( ) <= 1 )
1382 throw Exceptions::InternalError( strrefdup( "HeadedPath3D_helper::elementaryJob was unexpectedly called with a short path." ) );
1385 Lang::ElementaryPath3D::const_iterator i = bodyPath_->begin( );
1386 ++i;
1387 Lang::ElementaryPath3D::const_iterator end = bodyPath_->end( );
1388 --end;
1389 for( ; i != end; ++i )
1391 pth->push_back( new Concrete::PathPoint3D( **i ) );
1394 --i; /* Go back to the last point added to pth. */
1395 *basePoint = *((*i)->mid_);
1398 void
1399 Lang::HeadedPath3D_helper::gcMark( Kernel::GCMarkedSet & marked )
1401 const_cast< Lang::ElementaryPath3D * >( bodyPath_.getPtr( ) )->gcMark( marked );