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 "shapestypes.h"
22 #include "shapesexceptions.h"
24 #include "angleselect.h"
28 using namespace Shapes
;
33 Lang::CompositePath2D::computeElementaryPath( ) const
35 if( elementaryPath_
!= NullPtr
< const Lang::ElementaryPath2D
>( ) )
39 Lang::ElementaryPath2D
* pth
= new Lang::ElementaryPath2D
;
41 const double GAMMA_ANGLE
= 0.5;
43 Concrete::Coords2D
basePoint( 0, 0 );
45 std::stack
< const Lang::Value
* > nodeStack
;
46 nodeStack
.push( this );
47 while( ! nodeStack
.empty( ) )
49 const Lang::Value
* node
= nodeStack
.top( );
51 switch( node
->getTypeID( ) )
53 SINGLELOOP1( CLASSTREE1_Coords2D
, QUICKTYPECASE
)
55 const Lang::Coords2D
* coords
= dynamic_cast< const Lang::Coords2D
* >( node
);
56 /* We don't care if the point has an angle since there are no handles.
57 * Perhaps it should be an error.
60 const Lang::CornerCoords2D * tmp = dynamic_cast< const Lang::CornerCoords2D * >( coords );
63 newPoint->defaultAngle = tmp->a_;
66 Concrete::Coords2D
* newMid
= new Concrete::Coords2D( basePoint
, *coords
);
68 pth
->push_back( new Concrete::PathPoint2D( newMid
) );
71 SINGLELOOP1( CLASSTREE1_PathPoint2D
, QUICKTYPECASE
)
73 const Lang::PathPoint2D
* pathPoint
= reinterpret_cast< const Lang::PathPoint2D
* >( node
);
74 Concrete::Coords2D
* newMid
= new Concrete::Coords2D( basePoint
, *(pathPoint
->mid_
) );
76 Concrete::PathPoint2D
* newPoint
= new Concrete::PathPoint2D( newMid
);
79 const Lang::CornerCoords2D
* tmp
= dynamic_cast< const Lang::CornerCoords2D
* >( pathPoint
->mid_
.getPtr( ) );
82 newPoint
->defaultAngle_
= tmp
->a_
;
86 if( pathPoint
->rear_
!= NullPtr
< const Lang::Value
>( ) )
88 newPoint
->rear_
= new Concrete::Coords2D( 0, 0 );
90 typedef const Lang::Coords2D
* VariableHandle
;
91 VariableHandle typedHandle
= dynamic_cast< VariableHandle
>( pathPoint
->rear_
.getPtr( ) );
92 if( typedHandle
!= 0 )
94 *(newPoint
->rear_
) = Concrete::Coords2D( basePoint
, *typedHandle
);
95 Concrete::Length dx
= newPoint
->rear_
->x_
- newPoint
->mid_
->x_
;
96 Concrete::Length dy
= newPoint
->rear_
->y_
- newPoint
->mid_
->y_
;
97 newPoint
->rearAngle_
= atan2( dy
.offtype
< 1, 0 >( ), dx
.offtype
< 1, 0 >( ) );
98 newPoint
->rearModulus_
= hypotPhysical( dx
, dy
);
99 newPoint
->rearState_
= Concrete::PathPoint2D::COMPLETE
;
103 newPoint
->rearState_
= Concrete::PathPoint2D::UNFORCED_M
; // This is the normal case, the only exception being rectangular handles
104 pth
->allComplete_
= false;
106 typedef const Lang::PolarHandle2D
* VariableHandle
;
107 VariableHandle typedHandle
= dynamic_cast< VariableHandle
>( pathPoint
->rear_
.getPtr( ) );
108 if( typedHandle
!= 0 )
110 newPoint
->rearModulusPromise_
= typedHandle
->rPromise_
;
111 newPoint
->rearAngle_
= typedHandle
->a_
;
112 newPoint
->rearState_
|= Concrete::PathPoint2D::COMPLETE
; // This is just a no-op way of saying "keep it UNFORCED_M"
117 typedef const Lang::PolarHandle2DFree_a
* VariableHandle
;
118 VariableHandle typedHandle
= dynamic_cast< VariableHandle
>( pathPoint
->rear_
.getPtr( ) );
119 if( typedHandle
!= 0 )
121 newPoint
->rearModulusPromise_
= typedHandle
->rPromise_
;
122 newPoint
->rearState_
|= Concrete::PathPoint2D::FREE_ANGLE
;
127 typedef const Lang::PolarHandle2DFree_r
* VariableHandle
;
128 VariableHandle typedHandle
= dynamic_cast< VariableHandle
>( pathPoint
->rear_
.getPtr( ) );
129 if( typedHandle
!= 0 )
131 newPoint
->rearModulusPromise_
= typedHandle
->defaultModulus_
;
132 newPoint
->rearAngle_
= typedHandle
->a_
;
133 newPoint
->rearState_
|= Concrete::PathPoint2D::FREE_MODULUS
;
138 typedef const Lang::PolarHandle2DFree_ra
* VariableHandle
;
139 VariableHandle typedHandle
= dynamic_cast< VariableHandle
>( pathPoint
->rear_
.getPtr( ) );
140 if( typedHandle
!= 0 )
142 newPoint
->rearModulusPromise_
= typedHandle
->defaultModulus_
;
143 newPoint
->rearState_
|= Concrete::PathPoint2D::FREE
;
148 std::ostringstream msg
;
149 msg
<< "Unexpected type found in handle point: " << pathPoint
->rear_
->getTypeName( ) ;
150 throw Exceptions::InternalError( msg
);
155 if( pathPoint
->front_
!= NullPtr
< const Lang::Value
>( ) )
157 newPoint
->front_
= new Concrete::Coords2D( 0, 0 );
159 typedef const Lang::Coords2D
* VariableHandle
;
160 VariableHandle typedHandle
= dynamic_cast< VariableHandle
>( pathPoint
->front_
.getPtr( ) );
161 if( typedHandle
!= 0 )
163 *(newPoint
->front_
) = Concrete::Coords2D( basePoint
, *typedHandle
);
164 Concrete::Length dx
= newPoint
->front_
->x_
- newPoint
->mid_
->x_
;
165 Concrete::Length dy
= newPoint
->front_
->y_
- newPoint
->mid_
->y_
;
166 newPoint
->frontAngle_
= atan2( dy
.offtype
< 1, 0 >( ), dx
.offtype
< 1, 0 >( ) );
167 newPoint
->frontModulus_
= hypotPhysical( dx
, dy
);
168 newPoint
->frontState_
= Concrete::PathPoint2D::COMPLETE
;
172 newPoint
->frontState_
= Concrete::PathPoint2D::UNFORCED_M
;
173 pth
->allComplete_
= false;
175 typedef const Lang::PolarHandle2D
* VariableHandle
;
176 VariableHandle typedHandle
= dynamic_cast< VariableHandle
>( pathPoint
->front_
.getPtr( ) );
177 if( typedHandle
!= 0 )
179 newPoint
->frontModulusPromise_
= typedHandle
->rPromise_
;
180 newPoint
->frontAngle_
= typedHandle
->a_
;
181 newPoint
->frontState_
|= Concrete::PathPoint2D::COMPLETE
; // This is just a no-op way of saying "keep it UNFORCED_M"
186 typedef const Lang::PolarHandle2DFree_a
* VariableHandle
;
187 VariableHandle typedHandle
= dynamic_cast< VariableHandle
>( pathPoint
->front_
.getPtr( ) );
188 if( typedHandle
!= 0 )
190 newPoint
->frontModulusPromise_
= typedHandle
->rPromise_
;
191 newPoint
->frontState_
|= Concrete::PathPoint2D::FREE_ANGLE
;
196 typedef const Lang::PolarHandle2DFree_r
* VariableHandle
;
197 VariableHandle typedHandle
= dynamic_cast< VariableHandle
>( pathPoint
->front_
.getPtr( ) );
198 if( typedHandle
!= 0 )
200 newPoint
->frontModulusPromise_
= typedHandle
->defaultModulus_
;
201 newPoint
->frontAngle_
= typedHandle
->a_
;
202 newPoint
->frontState_
|= Concrete::PathPoint2D::FREE_MODULUS
;
207 typedef const Lang::PolarHandle2DFree_ra
* VariableHandle
;
208 VariableHandle typedHandle
= dynamic_cast< VariableHandle
>( pathPoint
->front_
.getPtr( ) );
209 if( typedHandle
!= 0 )
211 newPoint
->frontModulusPromise_
= typedHandle
->defaultModulus_
;
212 newPoint
->frontState_
|= Concrete::PathPoint2D::FREE
;
217 std::ostringstream msg
;
218 msg
<< "Unexpected type found in handle point: " << pathPoint
->front_
->getTypeName( ) ;
219 throw Exceptions::InternalError( msg
);
224 pth
->push_back( newPoint
);
227 SINGLELOOP1( CLASSTREE1_Path2D
, QUICKTYPECASE
)
229 const Lang::Path2D
* subPath
= reinterpret_cast< const Lang::Path2D
* >( node
);
230 subPath
->elementaryJob( & nodeStack
, pth
, & basePoint
);
235 std::ostringstream msg
;
236 msg
<< "Unexpected type found in subpath: " << node
->getTypeName( ) ;
237 throw Exceptions::InternalError( msg
);
242 if( pth
->allComplete_
)
248 /* Now, fill in all the missing angles.
252 Lang::ElementaryPath2D::iterator the_rend
= pth
->begin( );
254 Lang::ElementaryPath2D::iterator the_rbegin
= pth
->end( );
258 pth
->allComplete_
= true;
259 for( Lang::ElementaryPath2D::iterator i
= pth
->begin( );
263 if( ( (*i
)->rear_
== (*i
)->mid_
&&
264 (*i
)->front_
== (*i
)->mid_
) ||
265 isnan( (*i
)->defaultAngle_
) )
267 /* There are no handles at this point.
268 * Set angles in direction to neighboring coordinates
270 if( (*i
)->rearState_
& Concrete::PathPoint2D::FREE_ANGLE
)
272 Lang::ElementaryPath2D::iterator prev
= i
;
274 if( prev
== the_rend
)
278 Concrete::Length dxRear
= (*prev
)->mid_
->x_
- (*i
)->mid_
->x_
;
279 Concrete::Length dyRear
= (*prev
)->mid_
->y_
- (*i
)->mid_
->y_
;
280 (*i
)->rearAngle_
= atan2( dyRear
.offtype
< 1, 0 >( ), dxRear
.offtype
< 1, 0 >( ) );
281 (*i
)->rearState_
&= ~Concrete::PathPoint2D::FREE_ANGLE
;
283 if( (*i
)->frontState_
& Concrete::PathPoint2D::FREE_ANGLE
)
285 Lang::ElementaryPath2D::iterator next
= i
;
287 if( next
== pth
->end( ) )
289 next
= pth
->begin( );
291 Concrete::Length dxFront
= (*next
)->mid_
->x_
- (*i
)->mid_
->x_
;
292 Concrete::Length dyFront
= (*next
)->mid_
->y_
- (*i
)->mid_
->y_
;
293 (*i
)->frontAngle_
= atan2( dyFront
.offtype
< 1, 0 >( ), dxFront
.offtype
< 1, 0 >( ) );
294 (*i
)->frontState_
&= ~Concrete::PathPoint2D::FREE_ANGLE
;
299 if( (*i
)->front_
== (*i
)->mid_
)
301 /* There is only a rear handle at this point */
302 if( (*i
)->rearState_
& Concrete::PathPoint2D::UNFORCED_A
)
304 /* Put code for forcing the angle here
309 if( (*i
)->rearState_
& ( Concrete::PathPoint2D::FREE_MODULUS
| Concrete::PathPoint2D::UNFORCED_M
) )
311 pth
->allComplete_
= false;
314 if( ! ( (*i
)->rearState_
& Concrete::PathPoint2D::FREE_ANGLE
) )
318 (*i
)->rearState_
&= ~Concrete::PathPoint2D::FREE_ANGLE
;
320 Lang::ElementaryPath2D::iterator next
= i
;
322 if( next
== pth
->end( ) )
326 next
= pth
->begin( );
330 /* In this case we do something completely different.
332 Lang::ElementaryPath2D::iterator prev
= i
;
334 if( prev
== the_rend
)
336 throw Exceptions::MiscellaneousRequirement( "The angles of a singleton pathpoint cannot be determined." );
338 Concrete::Length dxRear
= (*prev
)->mid_
->x_
- (*i
)->mid_
->x_
;
339 Concrete::Length dyRear
= (*prev
)->mid_
->y_
- (*i
)->mid_
->y_
;
340 (*i
)->rearAngle_
= atan2( dyRear
.offtype
< 1, 0 >( ), dxRear
.offtype
< 1, 0 >( ) );
341 (*i
)->frontAngle_
= (*i
)->rearAngle_
+ M_PI
+ (*i
)->defaultAngle_
; /* Both angles must always be set, even where there is no handle. */
342 if( ! ( (*i
)->rearState_
& ( Concrete::PathPoint2D::FREE_MODULUS
| Concrete::PathPoint2D::UNFORCED_M
) ) )
344 (*i
)->rear_
->x_
= (*i
)->mid_
->x_
+ (*i
)->rearModulus_
* cos( (*i
)->rearAngle_
);
345 (*i
)->rear_
->y_
= (*i
)->mid_
->y_
+ (*i
)->rearModulus_
* sin( (*i
)->rearAngle_
);
346 (*i
)->rearState_
= Concrete::PathPoint2D::COMPLETE
;
351 Concrete::Length dxFront
= (*next
)->mid_
->x_
- (*i
)->mid_
->x_
;
352 Concrete::Length dyFront
= (*next
)->mid_
->y_
- (*i
)->mid_
->y_
;
353 (*i
)->frontAngle_
= atan2( dyFront
.offtype
< 1, 0 >( ), dxFront
.offtype
< 1, 0 >( ) ); /* Both angles must always be set, even where there is no handle. */
354 (*i
)->rearAngle_
= (*i
)->frontAngle_
+ M_PI
- (*i
)->defaultAngle_
;
355 if( ! ( (*i
)->rearState_
& ( Concrete::PathPoint2D::FREE_MODULUS
| Concrete::PathPoint2D::UNFORCED_M
) ) )
357 (*i
)->rear_
->x_
= (*i
)->mid_
->x_
+ (*i
)->rearModulus_
* cos( (*i
)->rearAngle_
);
358 (*i
)->rear_
->y_
= (*i
)->mid_
->y_
+ (*i
)->rearModulus_
* sin( (*i
)->rearAngle_
);
359 (*i
)->rearState_
= Concrete::PathPoint2D::COMPLETE
;
363 if( (*i
)->rear_
== (*i
)->mid_
)
365 /* There is only a front handle at this point */
367 if( (*i
)->frontState_
& Concrete::PathPoint2D::UNFORCED_A
)
369 /* Put code for forcing the angle here
374 if( (*i
)->frontState_
& ( Concrete::PathPoint2D::FREE_MODULUS
| Concrete::PathPoint2D::UNFORCED_M
) )
376 pth
->allComplete_
= false;
379 if( ! ( (*i
)->frontState_
& Concrete::PathPoint2D::FREE_ANGLE
) )
383 (*i
)->frontState_
&= ~Concrete::PathPoint2D::FREE_ANGLE
;
385 Lang::ElementaryPath2D::iterator prev
= i
;
387 if( prev
== the_rend
)
395 /* In this case we do something completely different.
397 Lang::ElementaryPath2D::iterator next
= i
;
399 if( next
== pth
->end( ) )
401 throw Exceptions::MiscellaneousRequirement( "The angles of a singleton pathpoint cannot be determined." );
403 Concrete::Length dxFront
= (*next
)->mid_
->x_
- (*i
)->mid_
->x_
;
404 Concrete::Length dyFront
= (*next
)->mid_
->y_
- (*i
)->mid_
->y_
;
405 (*i
)->frontAngle_
= atan2( dyFront
.offtype
< 1, 0 >( ), dxFront
.offtype
< 1, 0 >( ) );
406 (*i
)->rearAngle_
= (*i
)->frontAngle_
+ M_PI
- (*i
)->defaultAngle_
; /* Both angles must always be set, even where there is no handle. */
407 if( ! ( (*i
)->frontState_
& ( Concrete::PathPoint2D::FREE_MODULUS
| Concrete::PathPoint2D::UNFORCED_M
) ) )
409 (*i
)->front_
->x_
= (*i
)->mid_
->x_
+ (*i
)->frontModulus_
* cos( (*i
)->frontAngle_
);
410 (*i
)->front_
->y_
= (*i
)->mid_
->y_
+ (*i
)->frontModulus_
* sin( (*i
)->frontAngle_
);
411 (*i
)->frontState_
= Concrete::PathPoint2D::COMPLETE
;
416 Concrete::Length dxRear
= (*prev
)->mid_
->x_
- (*i
)->mid_
->x_
;
417 Concrete::Length dyRear
= (*prev
)->mid_
->y_
- (*i
)->mid_
->y_
;
418 (*i
)->rearAngle_
= atan2( dyRear
.offtype
< 1, 0 >( ), dxRear
.offtype
< 1, 0 >( ) ); /* Both angles must always be set, even where there is no handle. */
419 (*i
)->frontAngle_
= (*i
)->rearAngle_
+ M_PI
+ (*i
)->defaultAngle_
;
420 if( ! ( (*i
)->frontState_
& ( Concrete::PathPoint2D::FREE_MODULUS
| Concrete::PathPoint2D::UNFORCED_M
) ) )
422 (*i
)->front_
->x_
= (*i
)->mid_
->x_
+ (*i
)->frontModulus_
* cos( (*i
)->frontAngle_
);
423 (*i
)->front_
->y_
= (*i
)->mid_
->y_
+ (*i
)->frontModulus_
* sin( (*i
)->frontAngle_
);
424 (*i
)->frontState_
= Concrete::PathPoint2D::COMPLETE
;
430 /* We reach here if there are two handles at the point */
432 if( (*i
)->rearState_
& Concrete::PathPoint2D::UNFORCED_A
)
434 /* Put code for forcing the angle here
439 if( (*i
)->frontState_
& Concrete::PathPoint2D::UNFORCED_A
)
441 /* Put code for forcing the angle here
446 if( ( (*i
)->rearState_
| (*i
)->frontState_
) & ( Concrete::PathPoint2D::FREE_MODULUS
| Concrete::PathPoint2D::UNFORCED_M
) )
448 pth
->allComplete_
= false;
451 if( ! ( (*i
)->rearState_
& Concrete::PathPoint2D::FREE_ANGLE
) &&
452 ! ( (*i
)->frontState_
& Concrete::PathPoint2D::FREE_ANGLE
) )
454 /* Both handles have specified angles */
457 if( ! ( (*i
)->rearState_
& Concrete::PathPoint2D::FREE_ANGLE
) )
459 /* The rear handle has a specified angle, that may propagate to the front handle */
460 if( (*i
)->frontState_
& Concrete::PathPoint2D::FREE_ANGLE
)
462 (*i
)->frontAngle_
= (*i
)->rearAngle_
+ M_PI
+ (*i
)->defaultAngle_
;
463 (*i
)->frontState_
&= ~Concrete::PathPoint2D::FREE_ANGLE
;
467 if( ! ( (*i
)->frontState_
& Concrete::PathPoint2D::FREE_ANGLE
) )
469 /* Analogous to above */
470 if( (*i
)->rearState_
& Concrete::PathPoint2D::FREE_ANGLE
)
472 (*i
)->rearAngle_
= (*i
)->frontAngle_
+ M_PI
- (*i
)->defaultAngle_
;
473 (*i
)->rearState_
&= ~Concrete::PathPoint2D::FREE_ANGLE
;
478 /* None of the handles have specified angles */
480 Lang::ElementaryPath2D::iterator prev
= i
;
482 if( prev
== the_rend
)
486 Lang::ElementaryPath2D::iterator next
= i
;
488 if( next
== pth
->end( ) )
490 next
= pth
->begin( );
493 Concrete::Length dxRear
= (*prev
)->mid_
->x_
- (*i
)->mid_
->x_
;
494 Concrete::Length dyRear
= (*prev
)->mid_
->y_
- (*i
)->mid_
->y_
;
495 Concrete::Length dxFront
= (*next
)->mid_
->x_
- (*i
)->mid_
->x_
;
496 Concrete::Length dyFront
= (*next
)->mid_
->y_
- (*i
)->mid_
->y_
;
497 double angleRear
= atan2( dyRear
.offtype
< 1, 0 >( ), dxRear
.offtype
< 1, 0 >( ) );
498 double angleFront
= atan2( dyFront
.offtype
< 1, 0 >( ), dxFront
.offtype
< 1, 0 >( ) );
499 double weightRear
= pow( hypot( dxFront
.offtype
< 1, 0 >( ), dyFront
.offtype
< 1, 0 >( ) ), GAMMA_ANGLE
);
500 double weightFront
= pow( hypot( dxRear
.offtype
< 1, 0 >( ), dyRear
.offtype
< 1, 0 >( ) ), GAMMA_ANGLE
);
501 double a
= angleSelectNorm2( angleRear
, angleFront
- ( M_PI
+ (*i
)->defaultAngle_
), weightRear
, weightFront
);
502 (*i
)->rearAngle_
= a
;
503 (*i
)->frontAngle_
= a
+ M_PI
+ (*i
)->defaultAngle_
;
505 (*i
)->frontState_
&= ~Concrete::PathPoint2D::FREE_ANGLE
;
506 (*i
)->rearState_
&= ~Concrete::PathPoint2D::FREE_ANGLE
;
510 } // Done filling in angles.
513 /* Now, complete the path by filling in all the handle radii.
517 Lang::ElementaryPath2D::iterator the_rend
= pth
->begin( );
519 Lang::ElementaryPath2D::iterator the_rbegin
= pth
->end( );
522 pth
->allComplete_
= true;
523 for( Lang::ElementaryPath2D::iterator i
= pth
->begin( );
527 if( (*i
)->rear_
== (*i
)->mid_
&&
528 (*i
)->front_
== (*i
)->mid_
)
530 /* There are no handles at this point */
535 Lang::ElementaryPath2D::iterator prev
= i
;
537 if( prev
== the_rend
)
541 Lang::ElementaryPath2D::iterator next
= i
;
543 if( next
== pth
->end( ) )
545 next
= pth
->begin( );
548 if( (*i
)->front_
== (*i
)->mid_
)
550 /* There is only a rear handle at this point */
551 if( (*i
)->rearState_
== Concrete::PathPoint2D::COMPLETE
)
555 if( ( (*i
)->rearState_
& Concrete::PathPoint2D::UNFORCED_M
) != 0)
557 (*i
)->rearModulus_
= (*i
)->rearModulusPromise_
->force( *prev
, *i
, true );
559 (*i
)->rear_
->x_
= (*i
)->mid_
->x_
+ (*i
)->rearModulus_
* cos( (*i
)->rearAngle_
);
560 (*i
)->rear_
->y_
= (*i
)->mid_
->y_
+ (*i
)->rearModulus_
* sin( (*i
)->rearAngle_
);
563 if( (*i
)->rear_
== (*i
)->mid_
)
565 /* There is only a front handle at this point */
566 if( (*i
)->frontState_
== Concrete::PathPoint2D::COMPLETE
)
570 if( ( (*i
)->frontState_
& Concrete::PathPoint2D::UNFORCED_M
) != 0 )
572 (*i
)->frontModulus_
= (*i
)->frontModulusPromise_
->force( *i
, *next
, false );
574 (*i
)->front_
->x_
= (*i
)->mid_
->x_
+ (*i
)->frontModulus_
* cos( (*i
)->frontAngle_
);
575 (*i
)->front_
->y_
= (*i
)->mid_
->y_
+ (*i
)->frontModulus_
* sin( (*i
)->frontAngle_
);
579 /* We reach here if there are two handles at the point */
581 if( (*i
)->rearState_
!= Concrete::PathPoint2D::COMPLETE
)
583 if( ! ( (*i
)->rearState_
& Concrete::PathPoint2D::FREE_MODULUS
) )
585 if( ( (*i
)->rearState_
& Concrete::PathPoint2D::UNFORCED_M
) != 0 )
587 (*i
)->rearModulus_
= (*i
)->rearModulusPromise_
->force( *prev
, *i
, true );
589 (*i
)->rear_
->x_
= (*i
)->mid_
->x_
+ (*i
)->rearModulus_
* cos( (*i
)->rearAngle_
);
590 (*i
)->rear_
->y_
= (*i
)->mid_
->y_
+ (*i
)->rearModulus_
* sin( (*i
)->rearAngle_
);
591 (*i
)->rearState_
= Concrete::PathPoint2D::COMPLETE
;
595 if( (*i
)->frontState_
!= Concrete::PathPoint2D::COMPLETE
)
597 if( ! ( (*i
)->frontState_
& Concrete::PathPoint2D::FREE_MODULUS
) )
599 if( ( (*i
)->frontState_
& Concrete::PathPoint2D::UNFORCED_M
) != 0)
601 (*i
)->frontModulus_
= (*i
)->frontModulusPromise_
->force( *i
, *next
, false );
603 (*i
)->front_
->x_
= (*i
)->mid_
->x_
+ (*i
)->frontModulus_
* cos( (*i
)->frontAngle_
);
604 (*i
)->front_
->y_
= (*i
)->mid_
->y_
+ (*i
)->frontModulus_
* sin( (*i
)->frontAngle_
);
605 (*i
)->frontState_
= Concrete::PathPoint2D::COMPLETE
;
609 if( (*i
)->rearState_
== Concrete::PathPoint2D::COMPLETE
&&
610 (*i
)->frontState_
== Concrete::PathPoint2D::COMPLETE
)
615 /* The only reason why a handle is not complete at this point is that it's modulus
616 * has not been determined.
618 if( (*i
)->rearState_
== Concrete::PathPoint2D::COMPLETE
)
620 /* The rear modulus is known, and may propagate to the other side. */
621 if( (*i
)->frontState_
& Concrete::PathPoint2D::FREE_MODULUS
)
623 (*i
)->frontModulus_
= (*i
)->rearModulus_
;
624 (*i
)->front_
->x_
= (*i
)->mid_
->x_
+ (*i
)->frontModulus_
* cos( (*i
)->frontAngle_
);
625 (*i
)->front_
->y_
= (*i
)->mid_
->y_
+ (*i
)->frontModulus_
* sin( (*i
)->frontAngle_
);
629 if( (*i
)->frontState_
== Concrete::PathPoint2D::COMPLETE
)
631 /* Analogous to the above */
632 if( (*i
)->rearState_
& Concrete::PathPoint2D::FREE_MODULUS
)
634 (*i
)->rearModulus_
= (*i
)->frontModulus_
;
635 (*i
)->rear_
->x_
= (*i
)->mid_
->x_
+ (*i
)->rearModulus_
* cos( (*i
)->rearAngle_
);
636 (*i
)->rear_
->y_
= (*i
)->mid_
->y_
+ (*i
)->rearModulus_
* sin( (*i
)->rearAngle_
);
641 /* We get here if both modulus are free.
642 * We first compute madulus for each individually, and then merge the two values somehow to make both equal in the end.
645 double rearModulus
= (*i
)->rearModulusPromise_
->force( *prev
, *i
, true );
646 double frontModulus
= (*i
)->frontModulusPromise_
->force( *i
, *next
, false );
647 double theModulus
= min( rearModulus
, frontModulus
);
648 (*i
)->rearModulus_
= theModulus
;
649 (*i
)->frontModulus_
= theModulus
;
650 (*i
)->front_
->x_
= (*i
)->mid_
->x_
+ (*i
)->frontModulus_
* cos( (*i
)->frontAngle_
);
651 (*i
)->front_
->y_
= (*i
)->mid_
->y_
+ (*i
)->frontModulus_
* sin( (*i
)->frontAngle_
);
652 (*i
)->rear_
->x_
= (*i
)->mid_
->x_
+ (*i
)->rearModulus_
* cos( (*i
)->rearAngle_
);
653 (*i
)->rear_
->y_
= (*i
)->mid_
->y_
+ (*i
)->rearModulus_
* sin( (*i
)->rearAngle_
);
657 } // Closing scope of the_rend and the_rbegin
667 elementaryPath_
= RefCountPtr
< const Lang::ElementaryPath2D
>( pth
);