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
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 Henrik Tidefelt
21 #include "Shapes_Helpers_decls.h"
23 #include "shapescore.h"
26 #include "shapesexceptions.h"
28 #include "simplepdfi.h"
29 #include "upsamplers.h"
37 using namespace Shapes
;
44 class Core_bbox
: public Lang::CoreFunction
47 Core_bbox( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
48 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
50 formals_
->appendEvaluatedCoreFormal( "obj", Kernel::THE_SLOT_VARIABLE
);
51 formals_
->appendEvaluatedCoreFormal( "type", Helpers::newValHandle( new Lang::Symbol( "bounding" ) ) );
54 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
56 args
.applyDefaults( callLoc
);
59 typedef const Lang::Drawable2D ArgType
;
60 RefCountPtr
< ArgType
> arg
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, argsi
, callLoc
);
63 typedef const Lang::Symbol TypeType
;
64 RefCountPtr
< TypeType
> type
= Helpers::down_cast_CoreArgument
< TypeType
>( id_
, args
, argsi
, callLoc
);
65 static Lang::Symbol
BOUNDING( "bounding" );
66 static Lang::Symbol
BLEED( "bleed" );
67 Kernel::ContRef cont
= evalState
->cont_
;
68 if( *type
== BOUNDING
)
70 cont
->takeValue( arg
->bbox( Lang::Drawable2D::BOUNDING
),
73 else if( *type
== BLEED
)
75 cont
->takeValue( arg
->bbox( Lang::Drawable2D::BLEED
),
80 std::ostringstream msg
;
81 msg
<< "The only allowed symbols are { " ;
86 throw Exceptions::CoreOutOfRange( id_
, args
, argsi
, strrefdup( msg
) );
91 class Core_controlling
: public Lang::CoreFunction
94 Core_controlling( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
96 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
98 const size_t ARITY
= 1;
99 CHECK_ARITY( args
, ARITY
, id_
);
102 typedef const Lang::ElementaryPath2D ArgType
;
103 RefCountPtr
< ArgType
> path
= NullPtr
< ArgType
>( );
106 path
= Helpers::elementaryPathTry2D( args
.getValue( 0 ) );
108 catch( const NonLocalExit::NotThisType
& ball
)
112 Lang::MultiPath2D
* res
= new Lang::MultiPath2D( );
114 typedef typeof *path ListType
;
115 typedef ListType::const_iterator I
;
116 for( I i
= path
->begin( ); i
!= path
->end( ); ++i
)
118 const Concrete::Coords2D
* h
= (*i
)->rear_
;
121 Lang::ElementaryPath2D
* handlePath
= new Lang::ElementaryPath2D
;
122 handlePath
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( *( (*i
)->mid_
) ) ) );
123 handlePath
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( *h
) ) );
124 res
->push_back( RefCountPtr
< const Lang::ElementaryPath2D
>( handlePath
) );
129 Lang::ElementaryPath2D
* handlePath
= new Lang::ElementaryPath2D
;
130 handlePath
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( *( (*i
)->mid_
) ) ) );
131 handlePath
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( *h
) ) );
132 res
->push_back( RefCountPtr
< const Lang::ElementaryPath2D
>( handlePath
) );
136 Kernel::ContRef cont
= evalState
->cont_
;
137 cont
->takeValue( Kernel::ValueRef( res
),
144 typedef const Lang::ElementaryPath3D ArgType
;
145 RefCountPtr
< ArgType
> path
= NullPtr
< ArgType
>( );
148 path
= Helpers::elementaryPathTry3D( args
.getValue( 0 ) );
150 catch( const NonLocalExit::NotThisType
& ball
)
154 Lang::MultiPath3D
* res
= new Lang::MultiPath3D( );
156 typedef typeof *path ListType
;
157 typedef ListType::const_iterator I
;
158 for( I i
= path
->begin( ); i
!= path
->end( ); ++i
)
160 const Concrete::Coords3D
* h
= (*i
)->rear_
;
163 Lang::ElementaryPath3D
* handlePath
= new Lang::ElementaryPath3D
;
164 handlePath
->push_back( new Concrete::PathPoint3D( new Concrete::Coords3D( *( (*i
)->mid_
) ) ) );
165 handlePath
->push_back( new Concrete::PathPoint3D( new Concrete::Coords3D( *h
) ) );
166 res
->push_back( RefCountPtr
< const Lang::ElementaryPath3D
>( handlePath
) );
171 Lang::ElementaryPath3D
* handlePath
= new Lang::ElementaryPath3D
;
172 handlePath
->push_back( new Concrete::PathPoint3D( new Concrete::Coords3D( *( (*i
)->mid_
) ) ) );
173 handlePath
->push_back( new Concrete::PathPoint3D( new Concrete::Coords3D( *h
) ) );
174 res
->push_back( RefCountPtr
< const Lang::ElementaryPath3D
>( handlePath
) );
178 Kernel::ContRef cont
= evalState
->cont_
;
179 cont
->takeValue( Kernel::ValueRef( res
),
185 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, 0, Helpers::typeSetString( Lang::ElementaryPath2D::staticTypeName( ), Lang::ElementaryPath3D::staticTypeName( ) ) );
189 class Core_controlling_hull
: public Lang::CoreFunction
192 Core_controlling_hull( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
194 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
196 const size_t ARITY
= 1;
197 CHECK_ARITY( args
, ARITY
, id_
);
199 typedef const Lang::ElementaryPath2D ArgType
;
200 RefCountPtr
< ArgType
> path
= Helpers::elementaryPathCast2D( id_
, args
, 0, callLoc
);
202 Kernel::ContRef cont
= evalState
->cont_
;
203 cont
->takeValue( path
->controlling_hull( ),
208 class Core_subpath
: public Lang::CoreFunction
211 Core_subpath( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
213 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
215 const size_t ARITY
= 3;
216 CHECK_ARITY( args
, ARITY
, id_
);
219 typedef const Lang::ElementaryPath2D ArgType
;
220 RefCountPtr
< ArgType
> path
= NullPtr
< ArgType
>( );
224 path
= Helpers::elementaryPathTry2D( args
.getValue( argsi
) );
226 catch( const NonLocalExit::NotThisType
& ball
)
231 Concrete::SplineTime t1
= Helpers::pathTimeCast( id_
, path
, args
, argsi
, callLoc
);
233 Concrete::SplineTime t2
= Helpers::pathTimeCast( id_
, path
, args
, argsi
, callLoc
);
235 Kernel::ContRef cont
= evalState
->cont_
;
236 cont
->takeValue( path
->subpath( t1
, t2
),
243 typedef const Lang::ElementaryPath3D ArgType
;
244 RefCountPtr
< ArgType
> path
= NullPtr
< ArgType
>( );
248 path
= Helpers::elementaryPathTry3D( args
.getValue( argsi
) );
250 catch( const NonLocalExit::NotThisType
& ball
)
255 Concrete::SplineTime t1
= Helpers::pathTimeCast( id_
, path
, args
, argsi
, callLoc
);
257 Concrete::SplineTime t2
= Helpers::pathTimeCast( id_
, path
, args
, argsi
, callLoc
);
259 Kernel::ContRef cont
= evalState
->cont_
;
260 cont
->takeValue( path
->subpath( t1
, t2
),
266 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, 0, Helpers::typeSetString( Lang::ElementaryPath2D::staticTypeName( ), Lang::ElementaryPath3D::staticTypeName( ) ) );
270 class Core_reverse
: public Lang::CoreFunction
273 Core_reverse( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
275 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
277 const size_t ARITY
= 1;
278 CHECK_ARITY( args
, ARITY
, id_
);
284 typedef const Lang::ElementaryPath2D ArgType
;
285 RefCountPtr
< ArgType
> arg
= Helpers::elementaryPathTry2D( args
.getValue( argsi
) );
286 Kernel::ContRef cont
= evalState
->cont_
;
287 cont
->takeValue( arg
->reverse( ),
291 catch( const NonLocalExit::NotThisType
& ball
)
293 /* Wrong type; never mind!.. but see below!
299 typedef const Lang::ElementaryPath3D ArgType
;
300 RefCountPtr
< ArgType
> arg
= Helpers::elementaryPathTry3D( args
.getValue( argsi
) );
301 Kernel::ContRef cont
= evalState
->cont_
;
302 cont
->takeValue( arg
->reverse( ),
306 catch( const NonLocalExit::NotThisType
& ball
)
308 /* Wrong type; never mind!.. but see below!
312 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, argsi
, Helpers::typeSetString( Lang::ElementaryPath2D::staticTypeName( ), Lang::ElementaryPath3D::staticTypeName( ) ) );
316 class Core_meetpaths
: public Lang::CoreFunction
319 Core_meetpaths( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
321 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
323 const size_t ARITY
= 2;
324 CHECK_ARITY( args
, ARITY
, id_
);
327 typedef const Lang::ElementaryPath2D ArgType
;
328 RefCountPtr
< ArgType
> path1
= NullPtr
< ArgType
>( );
332 path1
= Helpers::elementaryPathTry2D( args
.getValue( argsi
) );
334 catch( const NonLocalExit::NotThisType
& ball
)
339 RefCountPtr
< ArgType
> path2
= Helpers::elementaryPathCast2D( id_
, args
, argsi
, callLoc
);
341 Lang::ElementaryPath2D
* res
= new Lang::ElementaryPath2D( );
343 Concrete::PathPoint2D
* meetPoint
;
346 Lang::ElementaryPath2D::const_iterator i
= path1
->begin( );
347 Lang::ElementaryPath2D::const_iterator end
= path1
->end( );
349 for( ; i
!= end
; ++i
)
351 Concrete::PathPoint2D
* newPoint
= new Concrete::PathPoint2D( new Concrete::Coords2D( *( (*i
)->mid_
) ) );
352 res
->push_back( newPoint
);
353 const Concrete::Coords2D
* h
= (*i
)->rear_
;
356 newPoint
->rear_
= new Concrete::Coords2D( *( (*i
)->rear_
) );
361 newPoint
->front_
= new Concrete::Coords2D( *( (*i
)->front_
) );
364 meetPoint
= new Concrete::PathPoint2D( new Concrete::Coords2D( *( (*i
)->mid_
) ) );
365 if( (*i
)->rear_
!= 0 )
367 meetPoint
->rear_
= new Concrete::Coords2D( *( (*i
)->rear_
) );
371 res
->push_back( meetPoint
);
374 Lang::ElementaryPath2D::const_iterator i
= path2
->begin( );
376 *(meetPoint
->mid_
) = 0.5 * ( *( (*i
)->mid_
) + *(meetPoint
->mid_
) );
378 if( (*i
)->front_
!= 0 )
380 meetPoint
->front_
= new Concrete::Coords2D( *( (*i
)->front_
) );
384 Lang::ElementaryPath2D::const_iterator end
= path2
->end( );
385 for( ; i
!= end
; ++i
)
387 Concrete::PathPoint2D
* newPoint
= new Concrete::PathPoint2D( new Concrete::Coords2D( *( (*i
)->mid_
) ) );
388 res
->push_back( newPoint
);
389 const Concrete::Coords2D
* h
= (*i
)->rear_
;
392 newPoint
->rear_
= new Concrete::Coords2D( *( (*i
)->rear_
) );
397 newPoint
->front_
= new Concrete::Coords2D( *( (*i
)->front_
) );
402 Kernel::ContRef cont
= evalState
->cont_
;
403 cont
->takeValue( Kernel::ValueRef( res
),
410 typedef const Lang::ElementaryPath3D ArgType
;
411 RefCountPtr
< ArgType
> path1
= NullPtr
< ArgType
>( );
415 path1
= Helpers::elementaryPathTry3D( args
.getValue( argsi
) );
417 catch( const NonLocalExit::NotThisType
& ball
)
422 RefCountPtr
< ArgType
> path2
= Helpers::elementaryPathCast3D( id_
, args
, argsi
, callLoc
);
424 Lang::ElementaryPath3D
* res
= new Lang::ElementaryPath3D( );
426 Concrete::PathPoint3D
* meetPoint
;
429 Lang::ElementaryPath3D::const_iterator i
= path1
->begin( );
430 Lang::ElementaryPath3D::const_iterator end
= path1
->end( );
432 for( ; i
!= end
; ++i
)
434 Concrete::PathPoint3D
* newPoint
= new Concrete::PathPoint3D( new Concrete::Coords3D( *( (*i
)->mid_
) ) );
435 res
->push_back( newPoint
);
436 const Concrete::Coords3D
* h
= (*i
)->rear_
;
439 newPoint
->rear_
= new Concrete::Coords3D( *( (*i
)->rear_
) );
444 newPoint
->front_
= new Concrete::Coords3D( *( (*i
)->front_
) );
447 meetPoint
= new Concrete::PathPoint3D( new Concrete::Coords3D( *( (*i
)->mid_
) ) );
448 if( (*i
)->rear_
!= 0 )
450 meetPoint
->rear_
= new Concrete::Coords3D( *( (*i
)->rear_
) );
454 res
->push_back( meetPoint
);
457 Lang::ElementaryPath3D::const_iterator i
= path2
->begin( );
459 *(meetPoint
->mid_
) = 0.5 * ( *( (*i
)->mid_
) + *(meetPoint
->mid_
) );
461 if( (*i
)->front_
!= 0 )
463 meetPoint
->front_
= new Concrete::Coords3D( *( (*i
)->front_
) );
467 Lang::ElementaryPath3D::const_iterator end
= path2
->end( );
468 for( ; i
!= end
; ++i
)
470 Concrete::PathPoint3D
* newPoint
= new Concrete::PathPoint3D( new Concrete::Coords3D( *( (*i
)->mid_
) ) );
471 res
->push_back( newPoint
);
472 const Concrete::Coords3D
* h
= (*i
)->rear_
;
475 newPoint
->rear_
= new Concrete::Coords3D( *( (*i
)->rear_
) );
480 newPoint
->front_
= new Concrete::Coords3D( *( (*i
)->front_
) );
485 Kernel::ContRef cont
= evalState
->cont_
;
486 cont
->takeValue( Kernel::ValueRef( res
),
492 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, 0, Helpers::typeSetString( Lang::ElementaryPath2D::staticTypeName( ), Lang::ElementaryPath3D::staticTypeName( ) ) );
496 class Core_upsampleinflections
: public Lang::CoreFunction
499 Core_upsampleinflections( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
501 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
503 const size_t ARITY
= 1;
504 CHECK_ARITY( args
, ARITY
, id_
);
508 typedef const Lang::ElementaryPath2D ArgType
;
509 RefCountPtr
< ArgType
> arg
= Helpers::elementaryPathCast2D( id_
, args
, argsi
, callLoc
);
510 Kernel::ContRef cont
= evalState
->cont_
;
511 cont
->takeValue( arg
->upsample( Computation::UpsampleInflections( ) ),
516 class Core_upsampledifferentiably
: public Lang::CoreFunction
519 Core_upsampledifferentiably( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
521 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
523 const size_t ARITY
= 1;
524 CHECK_ARITY( args
, ARITY
, id_
);
530 typedef const Lang::ElementaryPath2D ArgType
;
531 RefCountPtr
< ArgType
> arg
= Helpers::elementaryPathTry2D( args
.getValue( argsi
) );
532 Kernel::ContRef cont
= evalState
->cont_
;
533 cont
->takeValue( arg
->upsample( Computation::UpsampleDifferentiably2D( ) ),
537 catch( const NonLocalExit::NotThisType
& ball
)
539 /* Wrong type; never mind!.. but see below!
545 typedef const Lang::ElementaryPath3D ArgType
;
546 RefCountPtr
< ArgType
> arg
= Helpers::elementaryPathTry3D( args
.getValue( argsi
) );
547 Kernel::ContRef cont
= evalState
->cont_
;
548 cont
->takeValue( arg
->upsample( Computation::UpsampleDifferentiably3D( ) ),
552 catch( const NonLocalExit::NotThisType
& ball
)
554 /* Wrong type; never mind!.. but see below!
558 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, argsi
, Helpers::typeSetString( Lang::ElementaryPath2D::staticTypeName( ), Lang::ElementaryPath3D::staticTypeName( ) ) );
562 class Core_upsampleevery
: public Lang::CoreFunction
565 Core_upsampleevery( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
566 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
568 formals_
->appendEvaluatedCoreFormal( "period", Kernel::THE_SLOT_VARIABLE
);
569 formals_
->appendEvaluatedCoreFormal( "path", Kernel::THE_SLOT_VARIABLE
);
572 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
574 args
.applyDefaults( callLoc
);
578 typedef const Lang::Length PeriodType
;
579 Concrete::Length period
= Helpers::down_cast_CoreArgument
< PeriodType
>( id_
, args
, argsi
, callLoc
)->get( );
580 if( period
<= Concrete::ZERO_LENGTH
)
582 throw Exceptions::CoreOutOfRange( id_
, args
, argsi
, "The sample period must be positive." );
589 typedef const Lang::ElementaryPath2D ArgType
;
590 RefCountPtr
< ArgType
> arg
= Helpers::elementaryPathTry2D( args
.getValue( argsi
) );
591 Kernel::ContRef cont
= evalState
->cont_
;
592 cont
->takeValue( arg
->upsample( Computation::UpsampleEvery2D( period
) ),
596 catch( const NonLocalExit::NotThisType
& ball
)
598 /* Wrong type; never mind!.. but see below!
604 typedef const Lang::ElementaryPath3D ArgType
;
605 RefCountPtr
< ArgType
> arg
= Helpers::elementaryPathTry3D( args
.getValue( argsi
) );
606 Kernel::ContRef cont
= evalState
->cont_
;
607 cont
->takeValue( arg
->upsample( Computation::UpsampleEvery3D( period
) ),
611 catch( const NonLocalExit::NotThisType
& ball
)
613 /* Wrong type; never mind!.. but see below!
617 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, argsi
, Helpers::typeSetString( Lang::ElementaryPath2D::staticTypeName( ), Lang::ElementaryPath3D::staticTypeName( ) ) );
621 class Core_upsamplebends
: public Lang::CoreFunction
624 Core_upsamplebends( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
625 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
627 formals_
->appendEvaluatedCoreFormal( "angle", Kernel::THE_SLOT_VARIABLE
);
628 formals_
->appendEvaluatedCoreFormal( "path", Kernel::THE_SLOT_VARIABLE
);
631 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
633 args
.applyDefaults( callLoc
);
637 typedef const Lang::Float AngleType
;
638 double maxAngle
= Helpers::down_cast_CoreArgument
< AngleType
>( id_
, args
, argsi
, callLoc
)->val_
;
641 throw Exceptions::CoreOutOfRange( id_
, args
, argsi
, "The angle bound must be positive." );
645 typedef const Lang::ElementaryPath2D PathType
;
646 RefCountPtr
< PathType
> path
= Helpers::elementaryPathCast2D( id_
, args
, argsi
, callLoc
);
648 Kernel::ContRef cont
= evalState
->cont_
;
649 cont
->takeValue( path
->upsample( Computation::UpsampleBends( maxAngle
) ),
654 class Core_winding
: public Lang::CoreFunction
657 Core_winding( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
658 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
660 formals_
->appendEvaluatedCoreFormal( "path", Kernel::THE_SLOT_VARIABLE
);
661 formals_
->appendEvaluatedCoreFormal( "origin", Kernel::THE_SLOT_VARIABLE
);
664 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
666 args
.applyDefaults( callLoc
);
669 typedef const Lang::Coords2D OriginType
;
670 RefCountPtr
< OriginType
> origin
= Helpers::down_cast_CoreArgument
< OriginType
>( id_
, args
, 1, callLoc
);
675 typedef const Lang::ElementaryPath2D PathType
;
676 RefCountPtr
< PathType
> path
= Helpers::elementaryPathTry2D( args
.getValue( argsi
) );
677 if( ! path
->isClosed( ) )
679 throw Exceptions::CoreOutOfRange( id_
, args
, argsi
, "The path must be closed." );
681 Kernel::ContRef cont
= evalState
->cont_
;
682 cont
->takeValue( Kernel::ValueRef( new Lang::Integer( path
->windingNumber( *origin
) ) ),
686 catch( const NonLocalExit::NotThisType
& ball
)
688 /* Wrong type; never mind!.. but see below!
692 typedef const Lang::MultiPath2D PathType
;
693 RefCountPtr
< PathType
> path
= Helpers::down_cast_CoreArgument
< PathType
>( id_
, args
, argsi
, callLoc
);
695 for( PathType::const_iterator i
= path
->begin( ); i
!= path
->end( ); ++i
)
699 typedef const Lang::ElementaryPath2D SimplePathType
;
700 RefCountPtr
< SimplePathType
> simplePath
= Helpers::elementaryPathTry2D( *i
);
701 if( ! simplePath
->isClosed( ) )
703 throw Exceptions::CoreOutOfRange( id_
, args
, argsi
, "All simple paths in the multi-path must be closed." );
705 res
+= simplePath
->windingNumber( *origin
);
707 catch( const NonLocalExit::NotThisType
& ball
)
709 throw Exceptions::InternalError( "Element in MultiPath2D failed to be cast as ElementaryPath2D." );
713 Kernel::ContRef cont
= evalState
->cont_
;
714 cont
->takeValue( Kernel::ValueRef( new Lang::Integer( res
) ),
725 Kernel::registerCore_path( Kernel::Environment
* env
)
727 env
->initDefineCoreFunction( new Lang::Core_bbox( Lang::THE_NAMESPACE_Shapes_Layout
, "bbox" ) );
728 env
->initDefineCoreFunction( new Lang::Core_controlling( Lang::THE_NAMESPACE_Shapes_Geometry
, "controlling" ) );
729 env
->initDefineCoreFunction( new Lang::Core_controlling_hull( Lang::THE_NAMESPACE_Shapes_Geometry
, "controlling_hull" ) );
731 env
->initDefineCoreFunction( new Lang::Core_reverse( Lang::THE_NAMESPACE_Shapes_Geometry
, "reverse" ) );
732 env
->initDefineCoreFunction( new Lang::Core_meetpaths( Lang::THE_NAMESPACE_Shapes_Geometry
, "meetpaths" ) );
734 env
->initDefineCoreFunction( new Lang::Core_upsampleinflections( Lang::THE_NAMESPACE_Shapes_Geometry
, "upsample_inflections" ) );
735 env
->initDefineCoreFunction( new Lang::Core_upsampledifferentiably( Lang::THE_NAMESPACE_Shapes_Geometry
, "upsample_balance" ) );
736 env
->initDefineCoreFunction( new Lang::Core_upsampleevery( Lang::THE_NAMESPACE_Shapes_Geometry
, "upsample_every" ) );
737 env
->initDefineCoreFunction( new Lang::Core_upsamplebends( Lang::THE_NAMESPACE_Shapes_Geometry
, "upsample_bends" ) );
739 env
->initDefineCoreFunction( new Lang::Core_winding( Lang::THE_NAMESPACE_Shapes_Geometry
, "winding" ) );
741 /* subpath functions yet to be implemented */
742 // env->initDefineCoreFunction( new Lang::Core_directiontime( "directiontime" ) );
743 // env->initDefineCoreFunction( new Lang::Core_nearesttimes( "nearesttimes" ) ); /* generalizes distance between subpaths */
744 // env->initDefineCoreFunction( new Lang::Core_slidetimes( "slidetimes" ) ); /* "directional distance" between subpaths */
745 // env->initDefineCoreFunction( new Lang::Core_sidepath( "sidepath" ) );
747 // env->initDefineCoreFunction( new Lang::Core_convhull( "convhull" ) ); /* convex hull of a (full) path */
748 // env->initDefineCoreFunction( new Lang::Core_convhull( "contex?" ) ); /* test if closed subpath is (strictly) convex */
749 // env->initDefineCoreFunction( new Lang::Core_convhull( "rounded?" ) ); /* test if path has continuous tangent */
750 // env->initDefineCoreFunction( new Lang::Core_convhull( "differentiable?" ) ); /* test if path has continuous velocity */