Update suitable examples and tests to use blank mode
[shapes.git] / source / corepath.cc
blobf8aa3f9848c0a70409e8744ad61174d31ca460c0
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 Henrik Tidefelt
19 #include <cmath>
21 #include "Shapes_Helpers_decls.h"
23 #include "shapescore.h"
24 #include "ast.h"
25 #include "globals.h"
26 #include "shapesexceptions.h"
27 #include "consts.h"
28 #include "simplepdfi.h"
29 #include "upsamplers.h"
31 #include <iostream>
32 #include <sstream>
33 #include <fstream>
34 #include <vector>
35 #include <stdio.h>
37 using namespace Shapes;
40 namespace Shapes
42 namespace Lang
44 class Core_bbox : public Lang::CoreFunction
46 public:
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" ) ) );
53 virtual void
54 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
56 args.applyDefaults( callLoc );
58 size_t argsi = 0;
59 typedef const Lang::Drawable2D ArgType;
60 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, argsi, callLoc );
62 ++argsi;
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 ),
71 evalState );
73 else if( *type == BLEED )
75 cont->takeValue( arg->bbox( Lang::Drawable2D::BLEED ),
76 evalState );
78 else
80 std::ostringstream msg;
81 msg << "The only allowed symbols are { " ;
82 BOUNDING.show( msg );
83 msg << " , " ;
84 BLEED.show( msg );
85 msg << " }." ;
86 throw Exceptions::CoreOutOfRange( id_, args, argsi, strrefdup( msg ) );
91 class Core_controlling : public Lang::CoreFunction
93 public:
94 Core_controlling( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
95 virtual void
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 )
110 goto nextType1;
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_;
119 if( h != 0 )
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 ) );
126 h = (*i)->front_;
127 if( h != 0 )
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 ),
138 evalState );
139 return;
142 nextType1:
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 )
152 goto nextType2;
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_;
161 if( h != 0 )
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 ) );
168 h = (*i)->front_;
169 if( h != 0 )
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 ),
180 evalState );
181 return;
184 nextType2:
185 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 0, Helpers::typeSetString( Lang::ElementaryPath2D::staticTypeName( ), Lang::ElementaryPath3D::staticTypeName( ) ) );
189 class Core_controlling_hull : public Lang::CoreFunction
191 public:
192 Core_controlling_hull( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
193 virtual void
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( ),
204 evalState );
208 class Core_subpath : public Lang::CoreFunction
210 public:
211 Core_subpath( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
212 virtual void
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 >( );
221 size_t argsi = 0;
224 path = Helpers::elementaryPathTry2D( args.getValue( argsi ) );
226 catch( const NonLocalExit::NotThisType & ball )
228 goto nextType1;
230 ++argsi;
231 Concrete::SplineTime t1 = Helpers::pathTimeCast( id_, path, args, argsi, callLoc );
232 ++argsi;
233 Concrete::SplineTime t2 = Helpers::pathTimeCast( id_, path, args, argsi, callLoc );
235 Kernel::ContRef cont = evalState->cont_;
236 cont->takeValue( path->subpath( t1, t2 ),
237 evalState );
238 return;
241 nextType1:
243 typedef const Lang::ElementaryPath3D ArgType;
244 RefCountPtr< ArgType > path = NullPtr< ArgType >( );
245 size_t argsi = 0;
248 path = Helpers::elementaryPathTry3D( args.getValue( argsi ) );
250 catch( const NonLocalExit::NotThisType & ball )
252 goto nextType2;
254 ++argsi;
255 Concrete::SplineTime t1 = Helpers::pathTimeCast( id_, path, args, argsi, callLoc );
256 ++argsi;
257 Concrete::SplineTime t2 = Helpers::pathTimeCast( id_, path, args, argsi, callLoc );
259 Kernel::ContRef cont = evalState->cont_;
260 cont->takeValue( path->subpath( t1, t2 ),
261 evalState );
262 return;
265 nextType2:
266 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 0, Helpers::typeSetString( Lang::ElementaryPath2D::staticTypeName( ), Lang::ElementaryPath3D::staticTypeName( ) ) );
270 class Core_reverse : public Lang::CoreFunction
272 public:
273 Core_reverse( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
274 virtual void
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_ );
280 size_t argsi = 0;
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( ),
288 evalState );
289 return;
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( ),
303 evalState );
304 return;
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
318 public:
319 Core_meetpaths( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
320 virtual void
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 >( );
329 size_t argsi = 0;
332 path1 = Helpers::elementaryPathTry2D( args.getValue( argsi ) );
334 catch( const NonLocalExit::NotThisType & ball )
336 goto nextType1;
338 ++argsi;
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( );
348 --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_;
354 if( h != 0 )
356 newPoint->rear_ = new Concrete::Coords2D( *( (*i)->rear_ ) );
358 h = (*i)->front_;
359 if( h != 0 )
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_ ) );
383 ++i;
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_;
390 if( h != 0 )
392 newPoint->rear_ = new Concrete::Coords2D( *( (*i)->rear_ ) );
394 h = (*i)->front_;
395 if( h != 0 )
397 newPoint->front_ = new Concrete::Coords2D( *( (*i)->front_ ) );
402 Kernel::ContRef cont = evalState->cont_;
403 cont->takeValue( Kernel::ValueRef( res ),
404 evalState );
405 return;
408 nextType1:
410 typedef const Lang::ElementaryPath3D ArgType;
411 RefCountPtr< ArgType > path1 = NullPtr< ArgType >( );
412 size_t argsi = 0;
415 path1 = Helpers::elementaryPathTry3D( args.getValue( argsi ) );
417 catch( const NonLocalExit::NotThisType & ball )
419 goto nextType2;
421 ++argsi;
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( );
431 --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_;
437 if( h != 0 )
439 newPoint->rear_ = new Concrete::Coords3D( *( (*i)->rear_ ) );
441 h = (*i)->front_;
442 if( h != 0 )
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_ ) );
466 ++i;
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_;
473 if( h != 0 )
475 newPoint->rear_ = new Concrete::Coords3D( *( (*i)->rear_ ) );
477 h = (*i)->front_;
478 if( h != 0 )
480 newPoint->front_ = new Concrete::Coords3D( *( (*i)->front_ ) );
485 Kernel::ContRef cont = evalState->cont_;
486 cont->takeValue( Kernel::ValueRef( res ),
487 evalState );
488 return;
491 nextType2:
492 throw Exceptions::CoreTypeMismatch( callLoc, id_, args, 0, Helpers::typeSetString( Lang::ElementaryPath2D::staticTypeName( ), Lang::ElementaryPath3D::staticTypeName( ) ) );
496 class Core_upsampleinflections : public Lang::CoreFunction
498 public:
499 Core_upsampleinflections( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
500 virtual void
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_ );
506 size_t argsi = 0;
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( ) ),
512 evalState );
516 class Core_upsampledifferentiably : public Lang::CoreFunction
518 public:
519 Core_upsampledifferentiably( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
520 virtual void
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_ );
526 size_t argsi = 0;
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( ) ),
534 evalState );
535 return;
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( ) ),
549 evalState );
550 return;
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
564 public:
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 );
571 virtual void
572 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
574 args.applyDefaults( callLoc );
576 size_t argsi = 0;
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." );
585 ++argsi;
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 ) ),
593 evalState );
594 return;
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 ) ),
608 evalState );
609 return;
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
623 public:
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 );
630 virtual void
631 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
633 args.applyDefaults( callLoc );
635 size_t argsi = 0;
637 typedef const Lang::Float AngleType;
638 double maxAngle = Helpers::down_cast_CoreArgument< AngleType >( id_, args, argsi, callLoc )->val_;
639 if( maxAngle <= 0 )
641 throw Exceptions::CoreOutOfRange( id_, args, argsi, "The angle bound must be positive." );
644 ++argsi;
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 ) ),
650 evalState );
654 class Core_winding : public Lang::CoreFunction
656 public:
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 );
663 virtual void
664 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
666 args.applyDefaults( callLoc );
668 size_t argsi = 1;
669 typedef const Lang::Coords2D OriginType;
670 RefCountPtr< OriginType > origin = Helpers::down_cast_CoreArgument< OriginType >( id_, args, 1, callLoc );
672 argsi = 0;
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 ) ) ),
683 evalState );
684 return;
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 );
694 int res = 0;
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 ) ),
715 evalState );
724 void
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 */