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"
25 #include "angleselect.h"
28 #include "statetypes.h"
29 #include "lighttypes.h"
30 #include "shadingtypes.h"
32 #include "trianglefunctions.h"
33 #include "pagecontentstates.h"
34 #include "continuations.h"
40 using namespace Shapes
;
43 Lang::Drawable2D::Drawable2D( )
46 Lang::Drawable2D::~Drawable2D( )
49 RefCountPtr
< const Lang::Transformed2D
>
50 Lang::Drawable2D::typed_transformed( const Lang::Transform2D
& tf
, const RefCountPtr
< const Lang::Drawable2D
> & self
) const
52 return RefCountPtr
< const Lang::Transformed2D
>( new Lang::Transformed2D( self
, tf
) );
55 RefCountPtr
< const Lang::Geometric2D
>
56 Lang::Drawable2D::transformed( const Lang::Transform2D
& tf
, const RefCountPtr
< const Lang::Geometric2D
> & self
) const
58 return typed_transformed( tf
, self
.down_cast
< const Lang::Drawable2D
>( ) );
61 RefCountPtr
< const Lang::Geometric3D
>
62 Lang::Drawable2D::to3D( const RefCountPtr
< const Lang::Geometric2D
> & self
) const
64 typedef const Lang::Drawable2D SelfType
;
65 RefCountPtr
< SelfType
> typedSelf
= self
.down_cast
< SelfType
>( );
66 if( typedSelf
== NullPtr
< SelfType
>( ) )
68 throw Exceptions::InternalError( "The self-value passed to Drawable2D::to3D was of bad type." );
70 return RefCountPtr
< const Lang::Geometric3D
>( new Lang::Drawable2Din3D( typedSelf
) );
74 Lang::Drawable2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
76 // Not overloading this methods means that there are no tagged objects within this.
80 Lang::Drawable2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
82 // Not overloading this methods means that there are no tagged objects within this.
87 Lang::Drawable2D::gcMark( Kernel::GCMarkedSet
& marked
)
90 RefCountPtr
< const Lang::Class
> Lang::Drawable2D::TypeID
= NullPtr
< const Lang::Class
>( ); /* The value is set in main */
91 TYPEINFOIMPL( Drawable2D
);
92 DISPATCHIMPL( Drawable2D
);
95 Lang::Group2D::Group2D( )
98 Lang::Group2D::~Group2D( )
101 RefCountPtr
< const Lang::Class
> Lang::Group2D::TypeID( new Lang::SystemFinalClass( strrefdup( "Group2D" ) ) );
102 TYPEINFOIMPL( Group2D
);
105 RefCountPtr
< const Lang::Group2D
>
106 Helpers::newGroup2D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
, const RefCountPtr
< const Lang::Drawable2D
> & obj2
, const RefCountPtr
< const Lang::Drawable2D
> & obj1
)
108 RefCountPtr
< const Lang::Group2D
> res
= Lang::THE_NULL2D
;
109 res
= RefCountPtr
< const Lang::GroupPair2D
>( new Lang::GroupPair2D( obj1
,
112 res
= RefCountPtr
< const Lang::GroupPair2D
>( new Lang::GroupPair2D( obj2
,
118 RefCountPtr
< const Lang::Group2D
>
119 Helpers::newGroup2D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
, const RefCountPtr
< const Lang::Drawable2D
> & obj3
, const RefCountPtr
< const Lang::Drawable2D
> & obj2
, const RefCountPtr
< const Lang::Drawable2D
> & obj1
)
121 RefCountPtr
< const Lang::Group2D
> res
= Lang::THE_NULL2D
;
122 res
= RefCountPtr
< const Lang::GroupPair2D
>( new Lang::GroupPair2D( obj1
,
125 res
= RefCountPtr
< const Lang::GroupPair2D
>( new Lang::GroupPair2D( obj2
,
128 res
= RefCountPtr
< const Lang::GroupPair2D
>( new Lang::GroupPair2D( obj3
,
135 Lang::GroupPair2D::GroupPair2D( RefCountPtr
< const Lang::Drawable2D
> car
, RefCountPtr
< const Lang::Group2D
> cdr
, const RefCountPtr
< const Kernel::GraphicsState
> & metaState
)
136 : metaState_( metaState
), car_( car
), cdr_( cdr
)
139 Lang::GroupPair2D::~GroupPair2D( )
143 Lang::GroupPair2D::isNull( ) const
149 Lang::GroupPair2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
151 cdr_
->shipout( os
, pdfState
, tf
);
152 if( pdfState
->graphics_
.synchBlend( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) ) )
156 car_
->shipout( os
, pdfState
, tf
);
159 RefCountPtr
< const Lang::ElementaryPath2D
>
160 Lang::GroupPair2D::bbox( Lang::Drawable2D::BoxType boxType
) const
162 RefCountPtr
< const Lang::ElementaryPath2D
> carbbox
= car_
->bbox( boxType
);
163 RefCountPtr
< const Lang::ElementaryPath2D
> cdrbbox
= cdr_
->bbox( boxType
);
165 if( cdrbbox
->empty( ) )
170 Concrete::Length xmin
= Concrete::HUGE_LENGTH
;
171 Concrete::Length xmax
= -Concrete::HUGE_LENGTH
;
172 Concrete::Length ymin
= Concrete::HUGE_LENGTH
;
173 Concrete::Length ymax
= -Concrete::HUGE_LENGTH
;
175 typedef typeof *carbbox PathType
;
176 for( PathType::const_iterator i
= carbbox
->begin( ); i
!= carbbox
->end( ); ++i
)
178 Concrete::Length x
= (*i
)->mid_
->x_
;
179 xmin
= std::min( xmin
, x
);
180 xmax
= std::max( xmax
, x
);
182 Concrete::Length y
= (*i
)->mid_
->y_
;
183 ymin
= std::min( ymin
, y
);
184 ymax
= std::max( ymax
, y
);
187 for( PathType::const_iterator i
= cdrbbox
->begin( ); i
!= cdrbbox
->end( ); ++i
)
189 Concrete::Length x
= (*i
)->mid_
->x_
;
190 xmin
= std::min( xmin
, x
);
191 xmax
= std::max( xmax
, x
);
193 Concrete::Length y
= (*i
)->mid_
->y_
;
194 ymin
= std::min( ymin
, y
);
195 ymax
= std::max( ymax
, y
);
198 Lang::ElementaryPath2D
* res
= new Lang::ElementaryPath2D
;
200 if( xmin
< Concrete::HUGE_LENGTH
)
202 res
->push_back( new Concrete::PathPoint2D( xmin
, ymin
) );
203 res
->push_back( new Concrete::PathPoint2D( xmin
, ymax
) );
204 res
->push_back( new Concrete::PathPoint2D( xmax
, ymax
) );
205 res
->push_back( new Concrete::PathPoint2D( xmax
, ymin
) );
209 return RefCountPtr
< const Lang::ElementaryPath2D
>( res
);
214 Lang::GroupPair2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
216 /* Note the order! Objects are added on the car side of a group being built, so the car side is the "latter".
218 cdr_
->findTags( dst
, dyn
, key
, tf
);
219 car_
->findTags( dst
, dyn
, key
, tf
);
223 Lang::GroupPair2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
226 cdr_
->findOneTag( evalState
, key
, tf
) ||
227 car_
->findOneTag( evalState
, key
, tf
);
230 RefCountPtr
< const Lang::Group2D
>
231 Lang::GroupPair2D::removeShallow( Lang::Symbol::KeyType key
) const
234 typedef const Lang::Tagged2D TaggedType
;
235 TaggedType
* t
= dynamic_cast< TaggedType
* >( car_
.getPtr( ) );
236 if( t
!= 0 && t
->key( ) == key
)
238 return cdr_
->removeShallow( key
);
241 return RefCountPtr
< const Lang::Group2D
>( new Lang::GroupPair2D( car_
, cdr_
->removeShallow( key
), metaState_
) );
245 Lang::GroupPair2D::gcMark( Kernel::GCMarkedSet
& marked
)
247 const_cast< Lang::Drawable2D
* >( car_
.getPtr( ) )->gcMark( marked
);
248 const_cast< Lang::Group2D
* >( cdr_
.getPtr( ) )->gcMark( marked
);
252 Lang::GroupNull2D::GroupNull2D( )
255 Lang::GroupNull2D::~GroupNull2D( )
259 Lang::GroupNull2D::isNull( ) const
264 RefCountPtr
< const Lang::Group2D
>
265 Lang::GroupNull2D::removeShallow( Lang::Symbol::KeyType key
) const
267 return Lang::THE_NULL2D
;
271 Lang::GroupNull2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
274 RefCountPtr
< const Lang::ElementaryPath2D
>
275 Lang::GroupNull2D::bbox( Lang::Drawable2D::BoxType boxType
) const
277 return Lang::THE_EMPTYPATH2D
;
281 Lang::XObject::XObject( const RefCountPtr
< SimplePDF::PDF_Object
> & resource
, const RefCountPtr
< const Lang::ElementaryPath2D
> & boundingbox
)
282 : metaState_( Kernel::THE_NO_STATE
), resource_( resource
), boundingbox_( boundingbox
), bleedbox_( boundingbox
)
285 Lang::XObject::XObject( const RefCountPtr
< SimplePDF::PDF_Object
> & resource
, const RefCountPtr
< const Lang::ElementaryPath2D
> & boundingbox
, const RefCountPtr
< const Lang::ElementaryPath2D
> & bleedbox
, const RefCountPtr
< const Kernel::GraphicsState
> & metaState
)
286 : metaState_( metaState
), resource_( resource
), boundingbox_( boundingbox
), bleedbox_( bleedbox
)
289 Lang::XObject::~XObject( )
293 Lang::XObject::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
295 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
, false );
296 if( ! tf
.isIdentity( ) )
300 os
<< " cm" << std::endl
;
302 if( metaState_
!= Kernel::THE_NO_STATE
)
304 pdfState
->graphics_
.synchForNonStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
306 os
<< pdfState
->resources_
->nameofXObject( resource_
) << " Do" << std::endl
;
309 RefCountPtr
< SimplePDF::PDF_Object
>
310 Lang::XObject::getResource( ) const
315 RefCountPtr
< const Lang::ElementaryPath2D
>
316 Lang::XObject::bbox( Lang::Drawable2D::BoxType boxType
) const
320 case Lang::Drawable2D::BOUNDING
:
322 case Lang::Drawable2D::BLEED
:
325 throw Exceptions::InternalError( "Lang::XObject::bbox: boxType out of range." );
328 RefCountPtr
< const Lang::XObject
>
329 Lang::XObject::cloneWithState( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
, Concrete::Length bleedMargin
) const
331 Concrete::Coords2D
llcorner( 0, 0 );
332 Concrete::Coords2D
urcorner( 0, 0 );
333 boundingbox_
->boundingRectangle( & llcorner
, & urcorner
);
335 Lang::ElementaryPath2D
* bleedBox
= new Lang::ElementaryPath2D
;
337 bleedBox
->push_back( new Concrete::PathPoint2D( llcorner
.x_
- bleedMargin
, llcorner
.y_
- bleedMargin
) );
338 bleedBox
->push_back( new Concrete::PathPoint2D( urcorner
.x_
+ bleedMargin
, llcorner
.y_
- bleedMargin
) );
339 bleedBox
->push_back( new Concrete::PathPoint2D( urcorner
.x_
+ bleedMargin
, urcorner
.y_
+ bleedMargin
) );
340 bleedBox
->push_back( new Concrete::PathPoint2D( llcorner
.x_
- bleedMargin
, urcorner
.y_
+ bleedMargin
) );
343 return RefCountPtr
< const Lang::XObject
>( new Lang::XObject( resource_
, boundingbox_
, RefCountPtr
< const Lang::ElementaryPath2D
>( bleedBox
), metaState
) );
347 Lang::XObject::setDebugStr( const std::string
& debugStr
)
349 debugStr_
= debugStr
;
353 Lang::XObject::getDebugStr( ) const
359 Lang::XObject::show( std::ostream
& os
) const
361 os
<< "XObject (" << getDebugStr( ) << ")" ;
365 Lang::XObject::gcMark( Kernel::GCMarkedSet
& marked
)
367 // At the time of writing, there is nothing to propagate to.
371 Lang::TransparencyGroup::TransparencyGroup( const RefCountPtr
< SimplePDF::PDF_Indirect_out
> & indirection
, RefCountPtr
< const Lang::ElementaryPath2D
> mybbox
, const RefCountPtr
< const Lang::ColorSpace
> & colorSpace
)
372 : Lang::XObject( indirection
, mybbox
), colorSpace_( colorSpace
), indirection_( indirection
)
375 Lang::TransparencyGroup::~TransparencyGroup( )
378 RefCountPtr
< const Lang::ColorSpace
>
379 Lang::TransparencyGroup::colorSpace( ) const
384 RefCountPtr
< SimplePDF::PDF_Indirect_out
>
385 Lang::TransparencyGroup::getPDF_Object( ) const
387 return indirection_
.unconst_cast
< SimplePDF::PDF_Indirect_out
>( );
390 RefCountPtr
< const Lang::TransparencyGroup
>
391 Helpers::newTransparencyGroup( const RefCountPtr
< const Lang::Group2D
> & content
, bool isolated
, bool knockout
, const RefCountPtr
< const Lang::ColorSpace
> & blendSpace
)
393 RefCountPtr
< const Lang::ElementaryPath2D
> theBBox
= content
->bbox( Lang::Drawable2D::BOUNDING
);
394 Concrete::Coords2D
llcorner( 0, 0 );
395 Concrete::Coords2D
urcorner( 0, 0 );
396 if( ! theBBox
->boundingRectangle( & llcorner
, & urcorner
) )
398 throw Exceptions::InternalError( "newTransparencyGroup: The object has no bounding box!" );
401 using namespace Shapes
;
403 RefCountPtr
< SimplePDF::PDF_Stream_out
> form
;
405 (*form
)[ "Subtype" ] = SimplePDF::newName( "Form" );
406 (*form
)[ "FormType" ] = SimplePDF::newInt( 1 );
407 (*form
)[ "BBox" ] = RefCountPtr
< SimplePDF::PDF_Vector
>( new SimplePDF::PDF_Vector( llcorner
.x_
.offtype
< 1, 0 >( ), llcorner
.y_
.offtype
< 1, 0 >( ),
408 urcorner
.x_
.offtype
< 1, 0 >( ), urcorner
.y_
.offtype
< 1, 0 >( ) ) );
409 RefCountPtr
< SimplePDF::PDF_Resources
> resources
;
410 (*form
)[ "Resources" ] = SimplePDF::indirect( resources
, & Kernel::theIndirectObjectCount
);
412 if( ! Kernel::allowTransparency
)
416 else if( ! Kernel::the_PDF_version
.greaterOrEqual( SimplePDF::PDF_Version::PDF_1_4
) )
418 Kernel::the_PDF_version
.message( SimplePDF::PDF_Version::PDF_1_4
, "A transparency group was replaced by a plain XObject." );
422 RefCountPtr
< SimplePDF::PDF_Dictionary
> groupDic
;
423 (*form
)[ "Group" ] = groupDic
;
424 (*groupDic
)[ "S" ] = SimplePDF::newName( "Transparency" );
425 if( ! blendSpace
->isInherent( ) )
427 (*groupDic
)[ "CS" ] = blendSpace
->name( );
431 (*groupDic
)[ "I" ] = SimplePDF::newBoolean( true );
435 (*groupDic
)[ "K" ] = SimplePDF::newBoolean( true );
439 /* There's a possibility of adding a transformation matrix entry in the dictionary here, but it is not used, not even
440 * for transformed drawables.
442 // (*markForm)[ "Matrix" ] = RefCountPtr<PDF_Object>( new PDF_Vector( 1, 0, 0, 1, -30, -30 ) );
444 Kernel::PageContentStates
pdfState( resources
);
445 content
->shipout( form
->data
, & pdfState
, Lang::Transform2D( 1, 0, 0, 1, Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
) );
447 Lang::TransparencyGroup
* res
= new Lang::TransparencyGroup( SimplePDF::indirect( form
, & Kernel::theIndirectObjectCount
),
448 content
->bbox( Lang::Drawable2D::BOUNDING
),
450 res
->setDebugStr( "transparency group" );
451 return RefCountPtr
< const Lang::TransparencyGroup
>( res
);
457 Lang::PaintedPath2D::PaintedPath2D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
,
458 const char * paintCmd
)
459 : metaState_( metaState
), paintCmd_( paintCmd
)
462 Lang::PaintedPath2D::PaintedPath2D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
,
463 RefCountPtr
< const Lang::ElementaryPath2D
> path
,
464 const char * paintCmd
)
465 : metaState_( metaState
), paintCmd_( paintCmd
)
470 Lang::PaintedPath2D::PaintedPath2D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
,
471 RefCountPtr
< const Lang::MultiPath2D
> paths
,
472 const char * paintCmd
)
473 : metaState_( metaState
), paintCmd_( paintCmd
)
475 for( Lang::MultiPath2D::const_iterator i
= paths
->begin( ); i
!= paths
->end( ); ++i
)
478 typedef const Lang::ElementaryPath2D ArgType
;
479 RefCountPtr
< ArgType
> subpath
= (*i
).down_cast
< ArgType
>( );
480 if( subpath
!= NullPtr
< ArgType
>( ) )
482 addSubPath( subpath
);
488 typedef const Lang::CompositePath2D ArgType
;
489 ArgType
* subpath
= dynamic_cast< ArgType
* >( (*i
).getPtr( ) );
492 addSubPath( subpath
->getElementaryPath( ) );
496 throw Exceptions::InternalError( "Painting 2D path: Encountered a subpath of unexpected type" );
500 Lang::PaintedPath2D::~PaintedPath2D( )
503 RefCountPtr
< const Lang::Class
> Lang::PaintedPath2D::TypeID( new Lang::SystemFinalClass( strrefdup( "PaintedPath2D" ) ) );
504 TYPEINFOIMPL( PaintedPath2D
);
507 Lang::PaintedPath2D::addSubPath( RefCountPtr
< const Lang::ElementaryPath2D
> subpath
)
509 path_
.push_back( subpath
);
513 Lang::PaintedPath2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
515 /* Transforming the path by tf is not good enough, since that does not transform softmasks etc.
519 strcpy( pdfCmd
, paintCmd_
);
521 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
, false );
522 if( ! tf
.isIdentity( ) )
526 os
<< " cm" << std::endl
;
528 if( strcmp( paintCmd_
, "S" ) == 0 )
530 pdfState
->graphics_
.synchForStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
532 else if( strcmp( paintCmd_
, "f" ) == 0 ||
533 strcmp( paintCmd_
, "f*" ) == 0 )
535 pdfState
->graphics_
.synchForNonStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
537 else if( strcmp( paintCmd_
, "B" ) == 0 ||
538 strcmp( paintCmd_
, "B*" ) == 0 ||
539 strcmp( paintCmd_
, "b" ) == 0 ||
540 strcmp( paintCmd_
, "b*" ) == 0 )
542 pdfState
->graphics_
.synchForNonStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
543 pdfState
->graphics_
.synchForStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
545 else if( strcmp( paintCmd_
, "E" ) == 0 ||
546 strcmp( paintCmd_
, "E*" ) == 0 ||
547 strcmp( paintCmd_
, "e" ) == 0 ||
548 strcmp( paintCmd_
, "e*" ) == 0 )
550 pdfCmd
[0] += 'B' - 'E';
551 // Note that this is my own interpretation; usually, the stroke is made with the stroking color,
552 // but I use this to make filled regions just a little bit bigger, and then it is the nonstroking
553 // color that shall be applied to the stroke as well.
554 pdfState
->graphics_
.synchForNonStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
555 pdfState
->graphics_
.synchStrokingColorWithNonStrokingColor( os
, pdfState
->resources_
.getPtr( ), Concrete::ZERO_LENGTH
);
559 throw Exceptions::InternalError( "Unexpected paintCmd in PaintedPath2D::shipout" );
562 typedef typeof path_ ListType
;
563 for( ListType::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
565 (*i
)->writePath( os
);
567 os
<< " " << pdfCmd
<< std::endl
;
570 RefCountPtr
< const Lang::ElementaryPath2D
>
571 Lang::PaintedPath2D::bbox( Lang::Drawable2D::BoxType boxType
) const
575 return RefCountPtr
< const Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D
);
578 Concrete::Length xmin
= Concrete::HUGE_LENGTH
;
579 Concrete::Length xmax
= -Concrete::HUGE_LENGTH
;
580 Concrete::Length ymin
= Concrete::HUGE_LENGTH
;
581 Concrete::Length ymax
= -Concrete::HUGE_LENGTH
;
583 Concrete::Coords2D
llcorner( 0, 0 ); /* Temporary variables to be used in the loop below. */
584 Concrete::Coords2D
urcorner( 0, 0 );
586 typedef typeof path_ PathType
;
587 for( PathType::const_iterator j
= path_
.begin( ); j
!= path_
.end( ); ++j
)
589 if( (*j
)->boundingRectangle( & llcorner
, & urcorner
) )
592 xmin
= std::min( xmin
, llcorner
.x_
);
593 xmax
= std::max( xmax
, urcorner
.x_
);
594 ymin
= std::min( ymin
, llcorner
.y_
);
595 ymax
= std::max( ymax
, urcorner
.y_
);
599 Lang::ElementaryPath2D
* res
= new Lang::ElementaryPath2D
;
601 if( xmin
< Concrete::HUGE_LENGTH
)
603 if( toupper( *paintCmd_
) == 'S' ||
604 toupper( *paintCmd_
) == 'B' )
606 xmin
-= 0.5 * metaState_
->width_
;
607 ymin
-= 0.5 * metaState_
->width_
;
608 xmax
+= 0.5 * metaState_
->width_
;
609 ymax
+= 0.5 * metaState_
->width_
;
611 res
->push_back( new Concrete::PathPoint2D( xmin
, ymin
) );
612 res
->push_back( new Concrete::PathPoint2D( xmin
, ymax
) );
613 res
->push_back( new Concrete::PathPoint2D( xmax
, ymax
) );
614 res
->push_back( new Concrete::PathPoint2D( xmax
, ymin
) );
618 return RefCountPtr
< const Lang::ElementaryPath2D
>( res
);
622 Lang::PaintedPath2D::gcMark( Kernel::GCMarkedSet
& marked
)
626 Lang::Transformed2D::Transformed2D( RefCountPtr
< const Lang::Drawable2D
> element
, const Lang::Transform2D
& mytf
)
627 : mytf_( mytf
), element_( element
)
630 Lang::Transformed2D::~Transformed2D( )
634 Lang::Transformed2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
636 element_
->shipout( os
, pdfState
, Lang::Transform2D( tf
, mytf_
) );
639 RefCountPtr
< const Lang::ElementaryPath2D
>
640 Lang::Transformed2D::bbox( Lang::Drawable2D::BoxType boxType
) const
642 return element_
->bbox( boxType
)->elementaryTransformed( mytf_
);
646 Lang::Transformed2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
648 element_
->findTags( dst
, dyn
, key
, Lang::Transform2D( tf
, mytf_
) );
652 Lang::Transformed2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
655 element_
->findOneTag( evalState
, key
, Lang::Transform2D( tf
, mytf_
) );
659 Lang::Transformed2D::gcMark( Kernel::GCMarkedSet
& marked
)
661 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
665 Lang::BBoxed2D::BBoxed2D( RefCountPtr
< const Lang::Drawable2D
> element
, RefCountPtr
< const Lang::ElementaryPath2D
> mybbox
, BoxType boxType
)
666 : Lang::PaintedPolygon2D( Kernel::THE_NO_STATE
, mybbox
), mybbox_( mybbox
), element_( element
), boxType_( boxType
)
669 Lang::BBoxed2D::~BBoxed2D( )
673 Lang::BBoxed2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
675 /* At the moment, we don't clip according to the bbox, we only lie about our size.
677 element_
->shipout( os
, pdfState
, tf
);
680 RefCountPtr
< const Lang::ElementaryPath2D
>
681 Lang::BBoxed2D::bbox( Lang::Drawable2D::BoxType boxType
) const
684 || ( boxType
== Lang::Drawable2D::BOUNDING
&& boxType_
== BOUNDING
)
685 || ( boxType
== Lang::Drawable2D::BLEED
&& boxType_
== BLEED
) )
689 return element_
->bbox( boxType
);
693 Lang::BBoxed2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
695 element_
->findTags( dst
, dyn
, key
, tf
);
699 Lang::BBoxed2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
702 element_
->findOneTag( evalState
, key
, tf
);
706 Lang::BBoxed2D::gcMark( Kernel::GCMarkedSet
& marked
)
708 Lang::PaintedPolygon2D::gcMark( marked
);
709 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
713 Lang::Clipped2D::Clipped2D( const RefCountPtr
< const Lang::Drawable2D
> & element
, const char * clipCommand
)
714 : element_( element
), clipCommand_( clipCommand
)
717 Lang::Clipped2D::~Clipped2D( )
721 Lang::Clipped2D::addSubPath( const RefCountPtr
< const Lang::ElementaryPath2D
> & subpath
)
723 clipList_
.push_back( subpath
);
727 Lang::Clipped2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
729 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
);
730 if( ! tf
.isIdentity( ) )
733 os
<< " cm" << std::endl
;
735 typedef typeof clipList_ ListType
;
736 for( ListType::const_iterator i
= clipList_
.begin( ); i
!= clipList_
.end( ); ++i
)
738 (*i
)->writePath( os
);
740 os
<< " " << clipCommand_
<< " n" << std::endl
;
741 element_
->shipout( os
, pdfState
, THE_2D_IDENTITY
);
744 RefCountPtr
< const Lang::ElementaryPath2D
>
745 Lang::Clipped2D::bbox( Lang::Drawable2D::BoxType boxType
) const
747 RefCountPtr
< const Lang::ElementaryPath2D
> elem_bbox
= element_
->bbox( boxType
);
749 if( clipList_
.empty( ) )
751 return RefCountPtr
< const Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D
);
754 Concrete::Coords2D
llElemBbox( 0, 0 );
755 Concrete::Coords2D
urElemBbox( 0, 0 );
756 elem_bbox
->boundingRectangle( & llElemBbox
, & urElemBbox
);
758 Concrete::Length xmin
= Concrete::HUGE_LENGTH
;
759 Concrete::Length xmax
= -Concrete::HUGE_LENGTH
;
760 Concrete::Length ymin
= Concrete::HUGE_LENGTH
;
761 Concrete::Length ymax
= -Concrete::HUGE_LENGTH
;
763 Concrete::Coords2D
llcorner( 0, 0 ); /* Temporary variables to be used in the loop below. */
764 Concrete::Coords2D
urcorner( 0, 0 );
766 typedef typeof clipList_ PathType
;
767 for( PathType::const_iterator j
= clipList_
.begin( ); j
!= clipList_
.end( ); ++j
)
769 if( (*j
)->boundingRectangle( & llcorner
, & urcorner
) )
772 xmin
= std::min( xmin
, llcorner
.x_
);
773 xmax
= std::max( xmax
, urcorner
.x_
);
774 ymin
= std::min( ymin
, llcorner
.y_
);
775 ymax
= std::max( ymax
, urcorner
.y_
);
779 xmin
= std::max( xmin
, llElemBbox
.x_
);
780 ymin
= std::max( ymin
, llElemBbox
.y_
);
781 xmax
= std::min( xmax
, urElemBbox
.x_
);
782 ymax
= std::min( ymax
, urElemBbox
.y_
);
784 Lang::ElementaryPath2D
* res
= new Lang::ElementaryPath2D
;
786 if( xmin
< xmax
&& ymin
< ymax
)
788 res
->push_back( new Concrete::PathPoint2D( xmin
, ymin
) );
789 res
->push_back( new Concrete::PathPoint2D( xmin
, ymax
) );
790 res
->push_back( new Concrete::PathPoint2D( xmax
, ymax
) );
791 res
->push_back( new Concrete::PathPoint2D( xmax
, ymin
) );
795 return RefCountPtr
< const Lang::ElementaryPath2D
>( res
);
799 Lang::Clipped2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
801 element_
->findTags( dst
, dyn
, key
, tf
);
805 Lang::Clipped2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
808 element_
->findOneTag( evalState
, key
, tf
);
812 Lang::Clipped2D::gcMark( Kernel::GCMarkedSet
& marked
)
814 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
817 RefCountPtr
< const Lang::Drawable2D
>
818 Lang::Clipped2D::debugPolys( ) const
820 Kernel::GraphicsState
* frameStatePtr
= new Kernel::GraphicsState( true );
821 frameStatePtr
->width_
= Concrete::Length( 0.2 );
822 RefCountPtr
< const Kernel::GraphicsState
> frameState( frameStatePtr
);
824 Lang::PaintedPath2D
* res
= new Lang::PaintedPath2D( frameState
, "S" );
825 typedef typeof clipList_ ListType
;
826 for( ListType::const_iterator i
= clipList_
.begin( ); i
!= clipList_
.end( ); ++i
)
828 res
->addSubPath( *i
);
831 return RefCountPtr
< const Lang::Drawable2D
>( res
);
835 Lang::Clipped2D::isSingleConvexPoly( Concrete::Length tol
) const
837 if( clipList_
.size( ) != 1 )
841 return clipList_
.front( )->isConvexPoly( tol
);
845 Lang::Clipped2D::convexPolyContains( const Concrete::Coords2D
& p
, Concrete::Length tol
) const
847 return clipList_
.front( )->convexPolyContains( p
, tol
);
850 Lang::SoftMasked2D::SoftMasked2D( const RefCountPtr
< const Lang::Drawable2D
> & element
, const RefCountPtr
< const Lang::SoftMask
> & mask
)
851 : element_( element
), mask_( mask
)
854 Lang::SoftMasked2D::~SoftMasked2D( )
858 Lang::SoftMasked2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
860 const SimplePDF::PDF_Version::Version SOFTMASK_VERSION
= SimplePDF::PDF_Version::PDF_1_4
;
861 if( Kernel::the_PDF_version
.greaterOrEqual( SOFTMASK_VERSION
) )
863 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
);
864 if( ! tf
.isIdentity( ) )
867 os
<< " cm" << std::endl
;
869 os
<< pdfState
->resources_
->nameofGraphicsState( mask_
->graphicsStateResource_
) << " gs " << std::endl
;
870 element_
->shipout( os
, pdfState
, THE_2D_IDENTITY
);
874 Kernel::the_PDF_version
.message( SOFTMASK_VERSION
, "A soft mask was ignored." );
875 element_
->shipout( os
, pdfState
, tf
);
879 RefCountPtr
< const Lang::ElementaryPath2D
>
880 Lang::SoftMasked2D::bbox( Lang::Drawable2D::BoxType boxType
) const
882 return element_
->bbox( boxType
);
886 Lang::SoftMasked2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
888 element_
->findTags( dst
, dyn
, key
, tf
);
892 Lang::SoftMasked2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
895 element_
->findOneTag( evalState
, key
, tf
);
899 Lang::SoftMasked2D::gcMark( Kernel::GCMarkedSet
& marked
)
901 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
902 const_cast< Lang::SoftMask
* >( mask_
.getPtr( ) )->gcMark( marked
);
906 Lang::TextMasked2D::TextMasked2D( const RefCountPtr
< const Lang::Drawable2D
> & element
, const RefCountPtr
< const Lang::Text
> & mask
)
907 : element_( element
), mask_( mask
)
910 Lang::TextMasked2D::~TextMasked2D( )
914 Lang::TextMasked2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
916 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
);
917 if( ! tf
.isIdentity( ) )
920 os
<< " cm" << std::endl
;
922 mask_
->shipout_clip( os
, pdfState
, THE_2D_IDENTITY
);
923 element_
->shipout( os
, pdfState
, THE_2D_IDENTITY
);
926 RefCountPtr
< const Lang::ElementaryPath2D
>
927 Lang::TextMasked2D::bbox( Lang::Drawable2D::BoxType boxType
) const
929 return mask_
->bbox( boxType
);
933 Lang::TextMasked2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
935 element_
->findTags( dst
, dyn
, key
, tf
);
939 Lang::TextMasked2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
942 element_
->findOneTag( evalState
, key
, tf
);
946 Lang::TextMasked2D::gcMark( Kernel::GCMarkedSet
& marked
)
948 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
949 const_cast< Lang::Text
* >( mask_
.getPtr( ) )->gcMark( marked
);
953 Lang::Drawable3D::Drawable3D( )
956 Lang::Drawable3D::~Drawable3D( )
959 RefCountPtr
< const Lang::Transformed3D
>
960 Lang::Drawable3D::typed_transformed( const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
962 return RefCountPtr
< const Lang::Transformed3D
>( new Lang::Transformed3D( self
, tf
) );
965 RefCountPtr
< const Lang::Geometric3D
>
966 Lang::Drawable3D::transformed( const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Geometric3D
> & self
) const
968 return typed_transformed( tf
, self
.down_cast
< const Lang::Drawable3D
>( ) );
971 RefCountPtr
< const Lang::Geometric2D
>
972 Lang::Drawable3D::to2D( const Kernel::PassedDyn
& dyn
, const RefCountPtr
< const Lang::Geometric3D
> & self
) const
974 typedef const Lang::Drawable3D SelfType
;
975 RefCountPtr
< SelfType
> typedSelf
= self
.down_cast
< SelfType
>( );
976 if( typedSelf
== NullPtr
< SelfType
>( ) )
978 throw Exceptions::InternalError( "The self-value passed to Drawable3D::to2D was of bad type." );
980 return typed_to2D( dyn
, Lang::THE_3D_IDENTITY
, typedSelf
);
984 Lang::Drawable3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
986 // Not overloading this methods means that there are no tagged objects within this.
990 Lang::Drawable3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
992 // Not overloading this methods means that there are no tagged objects within this.
997 Lang::Drawable3D::gcMark( Kernel::GCMarkedSet
& marked
)
1000 RefCountPtr
< const Lang::Class
> Lang::Drawable3D::TypeID
= NullPtr
< const Lang::Class
>( ); /* The value is set in main */
1001 TYPEINFOIMPL( Drawable3D
);
1002 DISPATCHIMPL( Drawable3D
);
1005 Lang::Group3D::Group3D( )
1008 Lang::Group3D::~Group3D( )
1011 RefCountPtr
< const Lang::Drawable2D
>
1012 Lang::Group3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1014 return group_to2D( dyn
, tf
);
1018 RefCountPtr
< const Lang::Class
> Lang::Group3D::TypeID( new Lang::SystemFinalClass( strrefdup( "Group3D" ) ) );
1019 TYPEINFOIMPL( Group3D
);
1021 RefCountPtr
< const Lang::Group3D
>
1022 Helpers::newGroup3D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
, const RefCountPtr
< const Lang::Drawable3D
> & obj2
, const RefCountPtr
< const Lang::Drawable3D
> & obj1
)
1024 RefCountPtr
< const Lang::Group3D
> res
= Lang::THE_NULL3D
;
1025 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj1
,
1028 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj2
,
1034 RefCountPtr
< const Lang::Group3D
>
1035 Helpers::newGroup3D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
, const RefCountPtr
< const Lang::Drawable3D
> & obj3
, const RefCountPtr
< const Lang::Drawable3D
> & obj2
, const RefCountPtr
< const Lang::Drawable3D
> & obj1
)
1037 RefCountPtr
< const Lang::Group3D
> res
= Lang::THE_NULL3D
;
1038 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj1
,
1041 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj2
,
1044 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj3
,
1051 Lang::GroupPair3D::GroupPair3D( const RefCountPtr
< const Lang::Drawable3D
> & car
, const RefCountPtr
< const Lang::Group3D
> & cdr
, const RefCountPtr
< const Kernel::GraphicsState
> & metaState
)
1052 : metaState_( metaState
), car_( car
), cdr_( cdr
)
1055 Lang::GroupPair3D::~GroupPair3D( )
1059 Lang::GroupPair3D::isNull( ) const
1064 RefCountPtr
< const Lang::Group2D
>
1065 Lang::GroupPair3D::group_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
) const
1067 return RefCountPtr
< const Lang::Group2D
>( new Lang::GroupPair2D( car_
->typed_to2D( dyn
, tf
, car_
),
1068 cdr_
->group_to2D( dyn
, tf
),
1073 Lang::GroupPair3D::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1075 car_
->polygonize( zBufPile
, linePile
, dyn
, tf
, car_
);
1076 cdr_
->polygonize( zBufPile
, linePile
, dyn
, tf
, cdr_
);
1080 Lang::GroupPair3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1082 /* See note on order in GroupPair2D!
1084 cdr_
->findTags( dst
, dyn
, key
, tf
);
1085 car_
->findTags( dst
, dyn
, key
, tf
);
1089 Lang::GroupPair3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1092 cdr_
->findOneTag( evalState
, key
, tf
) ||
1093 car_
->findOneTag( evalState
, key
, tf
);
1096 RefCountPtr
< const Lang::Group3D
>
1097 Lang::GroupPair3D::removeShallow( Lang::Symbol::KeyType key
) const
1100 typedef const Lang::Tagged3D TaggedType
;
1101 TaggedType
* t
= dynamic_cast< TaggedType
* >( car_
.getPtr( ) );
1102 if( t
!= 0 && t
->key( ) == key
)
1104 return cdr_
->removeShallow( key
);
1107 return RefCountPtr
< const Lang::Group3D
>( new Lang::GroupPair3D( car_
, cdr_
->removeShallow( key
), metaState_
) );
1111 Lang::GroupPair3D::gcMark( Kernel::GCMarkedSet
& marked
)
1113 const_cast< Lang::Drawable3D
* >( car_
.getPtr( ) )->gcMark( marked
);
1114 const_cast< Lang::Group3D
* >( cdr_
.getPtr( ) )->gcMark( marked
);
1118 Lang::GroupNull3D::GroupNull3D( )
1121 Lang::GroupNull3D::~GroupNull3D( )
1125 Lang::GroupNull3D::isNull( ) const
1130 RefCountPtr
< const Lang::Group3D
>
1131 Lang::GroupNull3D::removeShallow( Lang::Symbol::KeyType key
) const
1133 return Lang::THE_NULL3D
;
1136 RefCountPtr
< const Lang::Group2D
>
1137 Lang::GroupNull3D::group_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
) const
1139 return Lang::THE_NULL2D
;
1143 Lang::GroupNull3D::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1147 Lang::Drawable2Din3D::Drawable2Din3D( RefCountPtr
< const Lang::Drawable2D
> element
)
1148 : element_( element
)
1151 Lang::Drawable2Din3D::~Drawable2Din3D( )
1154 RefCountPtr
< const Lang::Drawable2D
>
1155 Lang::Drawable2Din3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1157 Concrete::Length eyez
= dyn
->getEyeZ( );
1158 if( eyez
< Concrete::HUGE_LENGTH
)
1160 std::ostringstream msg
;
1161 msg
<< "An object of type " << element_
->getTypeName( ) << " in 3D cannot go back to 2D viewed from a finite distance. Consider using facing rather than immerse." ;
1162 throw Exceptions::MiscellaneousRequirement( strrefdup( msg
.str( ).c_str( ) ) );
1165 // The transform in 2D is obtained by setting z = 0 in the source 3D coordinates, and omitting the z-coordinate in the new coordinates
1167 return RefCountPtr
< const Lang::Drawable2D
>( new Lang::Transformed2D( element_
, Lang::Transform2D( tf
.xx_
, tf
.yx_
, tf
.xy_
, tf
.yy_
, tf
.xt_
, tf
.yt_
) ) );
1171 Lang::Drawable2Din3D::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1173 throw Exceptions::NotImplemented( "Triangularization of immersed objects." );
1177 Lang::Drawable2Din3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1179 Concrete::Length eyez
= dyn
->getEyeZ( );
1180 if( eyez
< Concrete::HUGE_LENGTH
)
1182 std::ostringstream msg
;
1183 msg
<< "Tags in an immersed object are not accessible from a finite viewing distance. Consider using facing rather than immerse." ;
1184 throw Exceptions::MiscellaneousRequirement( strrefdup( msg
.str( ).c_str( ) ) );
1187 // The transform in 2D is obtained by setting z = 0 in the source 3D coordinates, and omitting the z-coordinate in the new coordinates
1189 element_
->findTags( dst
, dyn
, key
, Lang::Transform2D( tf
.xx_
, tf
.yx_
, tf
.xy_
, tf
.yy_
, tf
.xt_
, tf
.yt_
) );
1193 Lang::Drawable2Din3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1195 Concrete::Length eyez
= evalState
->dyn_
->getEyeZ( );
1196 if( eyez
< Concrete::HUGE_LENGTH
)
1198 std::ostringstream msg
;
1199 msg
<< "Tags in an immersed object are not accessible from a finite viewing distance. Consider using facing rather than immerse." ;
1200 throw Exceptions::MiscellaneousRequirement( strrefdup( msg
.str( ).c_str( ) ) );
1203 // The transform in 2D is obtained by setting z = 0 in the source 3D coordinates, and omitting the z-coordinate in the new coordinates
1206 element_
->findOneTag( evalState
, key
, Lang::Transform2D( tf
.xx_
, tf
.yx_
, tf
.xy_
, tf
.yy_
, tf
.xt_
, tf
.yt_
) );
1210 Lang::Drawable2Din3D::gcMark( Kernel::GCMarkedSet
& marked
)
1212 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
1217 Lang::Facing2Din3D::Facing2Din3D( RefCountPtr
< const Lang::Drawable2D
> element
, bool scale
, bool distort
)
1218 : element_( element
), scale_( scale
), distort_( distort
)
1221 Lang::Facing2Din3D::~Facing2Din3D( )
1224 RefCountPtr
< const Lang::Drawable2D
>
1225 Lang::Facing2Din3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1227 Concrete::Length eyez
= dyn
->getEyeZ( );
1229 if( scale_
&& eyez
< Concrete::HUGE_LENGTH
)
1231 s
= eyez
/ ( eyez
- tf
.zt_
);
1236 if( eyez
< Concrete::HUGE_LENGTH
)
1238 x
= tf
.xt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1239 y
= tf
.yt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1249 return RefCountPtr
< const Lang::Drawable2D
>( new Lang::Transformed2D( element_
, Lang::Transform2D( s
* tf
.xx_
, s
* tf
.yx_
, s
* tf
.xy_
, s
* tf
.yy_
, x
, y
) ) );
1253 return RefCountPtr
< const Lang::Drawable2D
>( new Lang::Transformed2D( element_
, Lang::Transform2D( s
, 0, 0, s
, x
, y
) ) );
1258 Lang::Facing2Din3D::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1260 throw Exceptions::MiscellaneousRequirement( "Facing objects cannot be polygonized." );
1264 Lang::Facing2Din3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1266 Concrete::Length eyez
= dyn
->getEyeZ( );
1268 if( scale_
&& eyez
< Concrete::HUGE_LENGTH
)
1270 s
= eyez
/ ( eyez
- tf
.zt_
);
1275 if( eyez
< Concrete::HUGE_LENGTH
)
1277 x
= tf
.xt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1278 y
= tf
.yt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1288 element_
->findTags( dst
, dyn
, key
, Lang::Transform2D( s
* tf
.xx_
, s
* tf
.yx_
, s
* tf
.xy_
, s
* tf
.yy_
, x
, y
) );
1292 element_
->findTags( dst
, dyn
, key
, Lang::Transform2D( s
, 0, 0, s
, x
, y
) );
1297 Lang::Facing2Din3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1299 Concrete::Length eyez
= evalState
->dyn_
->getEyeZ( );
1301 if( scale_
&& eyez
< Concrete::HUGE_LENGTH
)
1303 s
= eyez
/ ( eyez
- tf
.zt_
);
1308 if( eyez
< Concrete::HUGE_LENGTH
)
1310 x
= tf
.xt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1311 y
= tf
.yt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1322 element_
->findOneTag( evalState
, key
, Lang::Transform2D( s
* tf
.xx_
, s
* tf
.yx_
, s
* tf
.xy_
, s
* tf
.yy_
, x
, y
) );
1327 element_
->findOneTag( evalState
, key
, Lang::Transform2D( s
, 0, 0, s
, x
, y
) );
1332 Lang::Facing2Din3D::gcMark( Kernel::GCMarkedSet
& marked
)
1334 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
1338 Lang::FacingFunction3D::FacingFunction3D( Kernel::PassedDyn dyn
, RefCountPtr
< const Lang::Function
> generator
)
1339 : dyn_( dyn
), generator_( generator
)
1342 Lang::FacingFunction3D::~FacingFunction3D( )
1345 RefCountPtr
< const Lang::Drawable2D
>
1346 Lang::FacingFunction3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1348 /* Too bad we can't call the function CPP here...
1350 Kernel::ValueRef valUntyped
= NullPtr
< const Lang::Value
>( );
1352 Ast::SourceLocation loc
= Ast::SourceLocation( Ast::FileID::build_internal( "<Facing a function in 3D>" ) );
1354 /* Note that the use of a StoreValueContinuation relies on valUntyped being alive at the time the continuation is invoked.
1357 Kernel::EvalState
evalState( 0,
1360 Kernel::ContRef( new Kernel::StoreValueContinuation( & valUntyped
,
1361 Kernel::ContRef( new Kernel::ExitContinuation( & done
, loc
) ),
1364 generator_
->call( & evalState
, RefCountPtr
< const Lang::Value
>( new Lang::Transform3D( tf
) ), loc
);
1368 evalState
.expr_
->eval( & evalState
);
1371 return Helpers::down_cast
< const Lang::Drawable2D
>( valUntyped
, loc
);
1375 Lang::FacingFunction3D::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1377 throw Exceptions::MiscellaneousRequirement( "Facing functions cannot be polygonized." );
1381 Lang::FacingFunction3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1384 * At the moment, we don't search facing functions for tags!
1389 Lang::FacingFunction3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1392 * At the moment, we don't search facing functions for tags!
1398 Lang::FacingFunction3D::gcMark( Kernel::GCMarkedSet
& marked
)
1400 const_cast< Lang::Function
* >( generator_
.getPtr( ) )->gcMark( marked
);
1404 Computation::PaintedPolygon3D::PaintedPolygon3D( bool singleSided
, const Concrete::UnitFloatTriple
& normal
, Concrete::Length m
, Concrete::Length tiebreaker
)
1405 : singleSided_( singleSided
), normal_( normal
), m_( m
), tiebreaker_( tiebreaker
)
1408 Computation::PaintedPolygon3D::~PaintedPolygon3D( )
1412 Computation::PaintedPolygon3D::pushPoint( const Concrete::Coords3D
& p
)
1414 Concrete::Length tmp
= Concrete::inner( normal_
, p
) - m_
;
1415 if( fabs( tmp
> Computation::theTrixelizeSplicingTol
) )
1417 std::cerr
<< "Greater than tol: " << tmp
.offtype
< 1, 0 >( ) << std::endl
;
1418 throw Exceptions::OutOfRange( "The 3D painted path was not flat enough to make a polygon." );
1420 points_
.push_back( p
);
1424 Computation::PaintedPolygon3D::push_zBufTriangles( const Lang::Transform3D
& tf
, const Concrete::Length eyez
, std::list
< Computation::ZBufTriangle
> * triangleQueue
, bool respectSingleSided
) const
1426 // This function shall not push tiny triangles!
1428 // Note that the ZBufTriangles pushed are not completely transformed, since *this is the painter, and not transformed by tf.
1429 // The ugly solution to this is that tf must also be specified when painting the area.
1431 if( points_
.size( ) < 3 )
1436 // At the moment, convexity is assumed!
1438 typedef Computation::ZBufTriangle::ZMap ZMapType
;
1439 if( tf
.isIdentity( ) )
1441 if( respectSingleSided
&& singleSided_
)
1443 const Concrete::Coords3D
& somePoint
= points_
.front( );
1444 if( normal_
.z_
* eyez
- Concrete::inner( normal_
, somePoint
) <= 0 )
1450 RefCountPtr
< const ZMapType
> zMap( new ZMapType( normal_
, m_
, tiebreaker_
, eyez
) );
1451 typedef typeof points_ ListType
;
1452 ListType::const_iterator i
= points_
.begin( );
1453 Concrete::Coords2D p0
= i
->make2DAutomatic( eyez
);
1455 Concrete::Coords2D p1
= i
->make2DAutomatic( eyez
);
1457 for( ; i
!= points_
.end( ); ++i
)
1459 Concrete::Coords2D p2
= i
->make2DAutomatic( eyez
);
1460 // This tolerance test assures that we don't produce tiny-tiny triangles. It is an inscribed circle test.
1461 if( Computation::triangleArea( p0
, p1
, p2
) > Computation::theTrixelizeOverlapTol
* Computation::triangleSemiPerimeter( p0
, p1
, p2
) )
1463 triangleQueue
->push_back( Computation::ZBufTriangle( this,
1472 RefCountPtr
< const ZMapType
> zMap
= RefCountPtr
< const ZMapType
>( NullPtr
< const ZMapType
>( ) );
1474 Concrete::UnitFloatTriple Tnormal
= tf
.transformPlaneUnitNormal( normal_
);
1475 if( respectSingleSided
&& singleSided_
)
1477 const Concrete::Coords3D
& somePoint
= points_
.front( );
1478 if( Tnormal
.z_
* eyez
- Concrete::inner( Tnormal
, somePoint
.transformed( tf
) ) <= 0 )
1484 double ax
= fabs( normal_
.x_
);
1485 double ay
= fabs( normal_
.y_
);
1486 double az
= fabs( normal_
.z_
);
1487 Concrete::Coords3D
x0( 0, 0, 0 );
1488 if( ax
>= ay
&& ax
>= az
)
1490 x0
= Concrete::Coords3D( m_
/ normal_
.x_
, 0, 0 );
1494 x0
= Concrete::Coords3D( 0, m_
/ normal_
.y_
, 0 );
1498 x0
= Concrete::Coords3D( 0, 0, m_
/ normal_
.z_
);
1500 Concrete::Length Tm
= Concrete::inner( Tnormal
, x0
.transformed( tf
) );
1502 zMap
= RefCountPtr
< const ZMapType
>( new ZMapType( Tnormal
, Tm
, tiebreaker_
, eyez
) );
1506 typedef typeof points_ ListType
;
1507 ListType::const_iterator i
= points_
.begin( );
1508 Concrete::Coords2D p0
= i
->transformed( tf
).make2DAutomatic( eyez
);
1510 Concrete::Coords2D p1
= i
->transformed( tf
).make2DAutomatic( eyez
);
1512 for( ; i
!= points_
.end( ); ++i
)
1514 Concrete::Coords2D p2
= i
->transformed( tf
).make2DAutomatic( eyez
);
1515 // This tolerance test assures that we don't produce tiny-tiny triangles. It is an inscribed circle test.
1516 if( Computation::triangleArea( p0
, p1
, p2
) > Computation::theTrixelizeOverlapTol
* Computation::triangleSemiPerimeter( p0
, p1
, p2
) )
1518 triangleQueue
->push_back( Computation::ZBufTriangle( this,
1528 Computation::PaintedPolygon3D::computeMean( ) const
1530 Concrete::Coords3D
res( 0, 0, 0 );
1531 typedef typeof points_ ListType
;
1532 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
1536 return ( 1. / points_
.size( ) ) * res
;
1539 const Computation::FacetLatticeVertex
*
1540 Computation::FacetLatticeEdge::getOther( const FacetLatticeEdge
* e
) const
1542 if( p0_
== e
->p0_
|| p0_
== e
->p1_
)
1550 Computation::FacetLatticeEdge::sharePoint( const FacetLatticeEdge
* e
) const
1561 Computation::FacetLatticeEdge::split( const Concrete::Length eyez
,
1562 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeEdge
* > > * edgeMem
,
1563 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeVertex
* > > * vertexMem
,
1564 const Computation::FacetLatticeEdge
** child1
, const Computation::FacetLatticeEdge
** child2
) const
1573 if( eyez
== Concrete::HUGE_LENGTH
)
1575 FacetLatticeVertex
* pNew
= new FacetLatticeVertex( 0.5 * ( p0_
->p3D_
+ p1_
->p3D_
), eyez
, vertexMem
->size( ) );
1576 vertexMem
->push_back( pNew
);
1577 child1_
= new Computation::FacetLatticeEdge( p0_
, pNew
);
1578 edgeMem
->push_back( child1_
);
1579 child2_
= new Computation::FacetLatticeEdge( pNew
, p1_
);
1580 edgeMem
->push_back( child2_
);
1584 // We compute the midpoint _in_view_, and then find where this is along the 3D line.
1585 Concrete::Coords2D mid2D
= 0.5 * ( p0_
->p2D_
+ p1_
->p2D_
);
1587 // If we write the point we seek in 3D as
1588 // p0_ + lambda * ( p1_ - p0_ )
1589 // then <lambda> must solve the overdetermined system
1592 const double ra
= ( p1_
->p3D_
.z_
- p0_
->p3D_
.z_
) / eyez
;
1593 Concrete::Coords2D
a( p1_
->p3D_
.x_
- p0_
->p3D_
.x_
+ mid2D
.x_
* ra
,
1594 p1_
->p3D_
.y_
- p0_
->p3D_
.y_
+ mid2D
.y_
* ra
);
1595 const double rb
= static_cast< double >( p0_
->p3D_
.z_
/ eyez
) - 1;
1596 Concrete::Coords2D
b( p0_
->p3D_
.x_
+ mid2D
.x_
* rb
,
1597 p0_
->p3D_
.y_
+ mid2D
.y_
* rb
);
1598 const double lambda
= - Concrete::innerScalar( a
, b
) / Concrete::innerScalar( a
, a
);
1600 FacetLatticeVertex
* pNew
= new FacetLatticeVertex( ( 1 - lambda
) * p0_
->p3D_
+ lambda
* p1_
->p3D_
, eyez
, vertexMem
->size( ) );
1601 vertexMem
->push_back( pNew
);
1602 child1_
= new Computation::FacetLatticeEdge( p0_
, pNew
);
1603 edgeMem
->push_back( child1_
);
1604 child2_
= new Computation::FacetLatticeEdge( pNew
, p1_
);
1605 edgeMem
->push_back( child2_
);
1613 Computation::FacetLatticeVertex::FacetLatticeVertex( const Concrete::Coords3D
& p3D
, const Concrete::Length eyez
, const size_t i
)
1614 : p3D_( p3D
), p2D_( p3D
.make2DAutomatic( eyez
) ), i_( i
)
1617 const Computation::FacetLatticeEdge
*
1618 Computation::FacetLatticeTriangle::getOther( const Computation::FacetLatticeEdge
*ea
, const Computation::FacetLatticeEdge
*eb
) const
1628 else if( ea
== e1_
)
1636 else if( ea
== e2_
)
1645 throw Exceptions::InternalError( "FacetTriangle::getOther called with alien edge." );
1649 Computation::FacetLatticeTriangle::fitsResolution( const Concrete::Length resolution
, const Concrete::Length eyez
,
1650 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeEdge
* > > * edgeMem
,
1651 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeVertex
* > > * vertexMem
,
1652 const Computation::FacetLatticeTriangle
** child1
, const Computation::FacetLatticeTriangle
** child2
) const
1654 const Computation::FacetLatticeEdge
* ec1
;
1655 const Computation::FacetLatticeEdge
* ec2
;
1657 Concrete::Length l0
= e0_
->length2D( );
1658 Concrete::Length l1
= e1_
->length2D( );
1659 Concrete::Length l2
= e2_
->length2D( );
1660 Concrete::Length lMax
= std::max( l0
, std::max( l1
, l2
) );
1662 if( lMax
< resolution
)
1667 const Computation::FacetLatticeEdge
* ea
= e0_
;
1668 const Computation::FacetLatticeEdge
* eb
= e1_
;
1669 const Computation::FacetLatticeEdge
* ec
= e2_
;
1676 else if( l2
== lMax
)
1684 ea
->split( eyez
, edgeMem
, vertexMem
, & ec1
, & ec2
);
1685 Computation::FacetLatticeEdge
* newEdge
= new Computation::FacetLatticeEdge( ea
->midpoint( ), eb
->getOther( ea
) );
1686 edgeMem
->push_back( newEdge
);
1687 if( eb
->sharePoint( ec2
) )
1689 *child1
= new Computation::FacetLatticeTriangle( ec2
, eb
, newEdge
);
1690 *child2
= new Computation::FacetLatticeTriangle( newEdge
, ec
, ec1
);
1694 *child1
= new Computation::FacetLatticeTriangle( ec1
, eb
, newEdge
);
1695 *child2
= new Computation::FacetLatticeTriangle( newEdge
, ec
, ec2
);
1702 RefCountPtr
< const Lang::Drawable2D
>
1703 Computation::FacetLatticeTriangle::paint( const RefCountPtr
< const Computation::FacetInterpolatorGray
> & interpolator
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
, const Concrete::Length eyez
) const
1705 Kernel::GraphicsState
* metaStatePtr
= new Kernel::GraphicsState( true );
1707 metaStatePtr
->nonStrokingColor_
= interpolator
->compute( Lang::THE_3D_IDENTITY
, lights
,
1708 Computation::triangleIncenter( v0_
->p3D_
, v1_
->p3D_
, v2_
->p3D_
),
1711 RefCountPtr
< const Kernel::GraphicsState
> metaState( metaStatePtr
);
1713 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
1715 // It's a pity we have to copy duplicate those points...
1716 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v0_
->p2D_
) ) );
1717 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v1_
->p2D_
) ) );
1718 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v2_
->p2D_
) ) );
1720 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::PaintedPolygon2D( metaState
, path
) );
1723 RefCountPtr
< const Lang::Drawable2D
>
1724 Computation::FacetLatticeTriangle::paint( const RefCountPtr
< const Computation::FacetInterpolatorRGB
> & interpolator
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
, const Concrete::Length eyez
) const
1726 Kernel::GraphicsState
* metaStatePtr
= new Kernel::GraphicsState( true );
1728 metaStatePtr
->nonStrokingColor_
= interpolator
->compute( Lang::THE_3D_IDENTITY
, lights
,
1729 Computation::triangleIncenter( v0_
->p3D_
, v1_
->p3D_
, v2_
->p3D_
),
1732 RefCountPtr
< const Kernel::GraphicsState
> metaState( metaStatePtr
);
1734 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
1736 // It's a pity we have to copy duplicate those points...
1737 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v0_
->p2D_
) ) );
1738 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v1_
->p2D_
) ) );
1739 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v2_
->p2D_
) ) );
1741 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::PaintedPolygon2D( metaState
, path
) );
1745 Computation::FacetLatticeTriangle::getVertexes( const Computation::FacetLatticeVertex
** va
, const Computation::FacetLatticeVertex
** vb
, const Computation::FacetLatticeVertex
** vc
) const
1752 // This function is very close to the PDF definition of a free-form triangle mesh.
1753 // If this triangle is an extension of va--vb--vc, then va, vb, vc are updated and the corresponding flag (se PDF spec) is returned.
1754 // If this is not an extension, the value 3 is returned (which is not a legal falg value), and va, vb, vc are left unchanged.
1756 Computation::FacetLatticeTriangle::extendLattice( const Computation::FacetLatticeVertex
** va
, const Computation::FacetLatticeVertex
** vb
, const Computation::FacetLatticeVertex
** vc
) const
1758 // vc must be part of this triangle if we are to extend va--vb--vc.
1759 if( v0_
== *vc
|| v1_
== *vc
|| v2_
== *vc
)
1761 // First, we try to extend vb--vc (corresponding to flag=1)
1762 if( v0_
== *vb
|| v1_
== *vb
|| v2_
== *vb
)
1764 // We now update va and vb so that they define the edge that is extended.
1768 // Now we need to find which of our corners that is the added one.
1769 if( v0_
!= *va
&& v0_
!= *vb
)
1773 else if( v1_
!= *va
&& v1_
!= *vb
)
1784 // Then, we try to extend va--vc (corresponding to flag=2)
1785 if( v0_
== *va
|| v1_
== *va
|| v2_
== *va
)
1787 // We now update va and vb so that they define the edge that is extended.
1791 // Now we need to find which of our corners that is the added one.
1792 if( v0_
!= *va
&& v0_
!= *vb
)
1796 else if( v1_
!= *va
&& v1_
!= *vb
)
1812 Computation::FacetLatticeTriangle::display2D( std::ostream
& os
) const
1814 Concrete::Length lMax
= Concrete::ZERO_LENGTH
;
1816 Concrete::Length tmp
= v0_
->p2D_
.distanceTo( v1_
->p2D_
);
1823 Concrete::Length tmp
= v1_
->p2D_
.distanceTo( v2_
->p2D_
);
1830 Concrete::Length tmp
= v2_
->p2D_
.distanceTo( v0_
->p2D_
);
1837 os
<< "Triangle ( " << v0_
->p2D_
<< " -- " << v1_
->p2D_
<< " -- " << v2_
->p2D_
<< " ) "
1838 << " with 2D area " << Concrete::Area::offtype( Computation::triangleArea( v0_
->p2D_
, v1_
->p2D_
, v2_
->p2D_
) )
1839 << " and longest side " << Lang::Length( lMax
) ;
1843 Computation::FacetLatticeTriangle::display3D( std::ostream
& os
) const
1845 os
<< "Triangle ( " << v0_
->p3D_
<< " -- " << v1_
->p3D_
<< " -- " << v2_
->p3D_
<< " )" ;
1850 Computation::PaintedPolygon3D::makeLattice( PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeTriangle
* > > * lattice
,
1851 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeEdge
* > > * edgeMem
,
1852 PtrOwner_back_Access
< std::list
< const FacetLatticeVertex
* > > * vertexMem
,
1853 const Concrete::Length viewResolution
,
1854 const Concrete::Length eyez
, const Lang::Transform3D
& tf
) const
1856 if( points_
.size( ) < 3 )
1858 throw Exceptions::InternalError( "Less than three points in PaintedPolygon3D::makeLattice!" );
1861 std::list
< const Computation::FacetLatticeTriangle
* > jobQueue
;
1863 typedef typeof points_ ListType
;
1865 if( points_
.size( ) == 3 )
1867 ListType::const_iterator i
= points_
.begin( );
1868 Computation::FacetLatticeVertex
* p0
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1869 vertexMem
->push_back( p0
);
1871 Computation::FacetLatticeVertex
* p1
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1872 vertexMem
->push_back( p1
);
1874 Computation::FacetLatticeVertex
* p2
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1875 vertexMem
->push_back( p2
);
1877 Computation::FacetLatticeEdge
* e0
= new Computation::FacetLatticeEdge( p0
, p1
);
1878 edgeMem
->push_back( e0
);
1879 Computation::FacetLatticeEdge
* e1
= new Computation::FacetLatticeEdge( p1
, p2
);
1880 edgeMem
->push_back( e1
);
1881 Computation::FacetLatticeEdge
* e2
= new Computation::FacetLatticeEdge( p2
, p0
);
1882 edgeMem
->push_back( e2
);
1884 jobQueue
.push_back( new Computation::FacetLatticeTriangle( e0
, e1
, e2
) );
1888 ListType::const_iterator i
= points_
.begin( );
1889 Computation::FacetLatticeVertex
* p0
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1890 vertexMem
->push_back( p0
);
1892 Computation::FacetLatticeVertex
* p1
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1893 vertexMem
->push_back( p1
);
1896 Computation::FacetLatticeEdge
* e0
= new Computation::FacetLatticeEdge( p0
, p1
);
1897 edgeMem
->push_back( e0
);
1899 for( ; i
!= points_
.end( ); ++i
)
1901 Computation::FacetLatticeVertex
* p2
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1902 vertexMem
->push_back( p2
);
1904 Computation::FacetLatticeEdge
* e1
= new Computation::FacetLatticeEdge( p1
, p2
);
1905 edgeMem
->push_back( e1
);
1907 Computation::FacetLatticeEdge
* e2
= new Computation::FacetLatticeEdge( p2
, p0
);
1908 edgeMem
->push_back( e2
);
1910 jobQueue
.push_back( new Computation::FacetLatticeTriangle( e0
, e1
, e2
) );
1917 while( ! jobQueue
.empty( ) )
1919 // std::cerr << "Triangles in queue: " << jobQueue.size( ) << " Triangles in lattice: " << lattice->size( ) << std::endl ;
1920 const Computation::FacetLatticeTriangle
* currentTriangle
= jobQueue
.front( );
1921 jobQueue
.pop_front( );
1922 const Computation::FacetLatticeTriangle
* child1
= 0;
1923 const Computation::FacetLatticeTriangle
* child2
= 0;
1924 if( currentTriangle
->fitsResolution( viewResolution
, eyez
, edgeMem
, vertexMem
, & child1
, & child2
) )
1926 lattice
->push_back( currentTriangle
);
1930 jobQueue
.push_back( child1
);
1931 jobQueue
.push_back( child2
);
1932 delete currentTriangle
;
1937 Computation::StrokedLine3D::StrokedLine3D( const Concrete::Coords3D
& p0
, const Concrete::Coords3D
& p1
, const RefCountPtr
< const Kernel::GraphicsState
> metaState
)
1938 : p0_( p0
), p1_( p1
), metaState_( metaState
)
1941 Computation::StrokedLine3D::~StrokedLine3D( )
1945 Computation::StrokedLine3D::push_zBufLine( const Lang::Transform3D
& tf
, const Concrete::Length eyez
, std::list
< const Computation::ZBufLine
* > * lineQueue
) const
1947 typedef Computation::ZBufLine::ZMap ZMapType
;
1948 typedef const Bezier::PolyCoeffs
< Concrete::Coords2D
> ViewType
;
1949 RefCountPtr
< ViewType
> nullView
= RefCountPtr
< ViewType
>( NullPtr
< ViewType
>( ) );
1950 if( tf
.isIdentity( ) )
1952 Concrete::Coords3D d
= p1_
- p0_
;
1953 RefCountPtr
< const ZMapType
> zMap( new ZMapType( p0_
, d
.directionNoFail( ), eyez
) );
1954 lineQueue
->push_back( new Computation::ZBufLine( this, zMap
, nullView
, p0_
.make2DAutomatic( eyez
), p1_
.make2DAutomatic( eyez
) ) );
1958 Concrete::Coords3D tfp0
= p0_
.transformed( tf
);
1959 Concrete::Coords3D tfp1
= p1_
.transformed( tf
);
1960 Concrete::Coords3D d
= tfp1
- tfp0
;
1961 RefCountPtr
< const ZMapType
> zMap( new ZMapType( tfp0
, d
.directionNoFail( ), eyez
) );
1962 lineQueue
->push_back( new Computation::ZBufLine( this, zMap
, nullView
, tfp0
.make2DAutomatic( eyez
), tfp1
.make2DAutomatic( eyez
) ) );
1967 Computation::StrokedSplineSegment3D::StrokedSplineSegment3D( const Concrete::Coords3D
& p0
, const Concrete::Coords3D
& p0front
, const Concrete::Coords3D
& p1rear
, const Concrete::Coords3D
& p1
, const RefCountPtr
< const Kernel::GraphicsState
> metaState
)
1968 : Computation::StrokedLine3D( p0
, p1
, metaState
),
1969 p0front_( p0front
),
1973 Computation::StrokedSplineSegment3D::~StrokedSplineSegment3D( )
1977 Computation::StrokedSplineSegment3D::push_zBufLine( const Lang::Transform3D
& tf
, const Concrete::Length eyez
, std::list
< const Computation::ZBufLine
* > * lineQueue
) const
1979 typedef Computation::ZBufLine::ZMap ZMapType
;
1980 typedef const Bezier::PolyCoeffs
< Concrete::Coords2D
> ViewType
;
1981 if( tf
.isIdentity( ) )
1983 Concrete::Coords3D d
= p1_
- p0_
;
1984 RefCountPtr
< const ZMapType
> zMap( new ZMapType( p0_
, d
.directionNoFail( ), eyez
) );
1985 RefCountPtr
< ViewType
> bezierView
= RefCountPtr
< ViewType
>( new ViewType( Bezier::ControlPoints
< Concrete::Coords2D
>( p0_
.make2DAutomatic( eyez
), p0front_
.make2DAutomatic( eyez
), p1rear_
.make2DAutomatic( eyez
), p1_
.make2DAutomatic( eyez
) ) ) );
1986 lineQueue
->push_back( new Computation::ZBufLine( this, zMap
, bezierView
, p0_
.make2DAutomatic( eyez
), p1_
.make2DAutomatic( eyez
) ) );
1990 Concrete::Coords3D tfp0
= p0_
.transformed( tf
);
1991 Concrete::Coords3D tfp0front
= p0front_
.transformed( tf
);
1992 Concrete::Coords3D tfp1rear
= p1rear_
.transformed( tf
);
1993 Concrete::Coords3D tfp1
= p1_
.transformed( tf
);
1994 Concrete::Coords3D d
= tfp1
- tfp0
;
1995 RefCountPtr
< const ZMapType
> zMap( new ZMapType( tfp0
, d
.directionNoFail( ), eyez
) );
1996 RefCountPtr
< ViewType
> bezierView
= RefCountPtr
< ViewType
>( new ViewType( Bezier::ControlPoints
< Concrete::Coords2D
>( tfp0
.make2DAutomatic( eyez
), tfp0front
.make2DAutomatic( eyez
), tfp1rear
.make2DAutomatic( eyez
), tfp1
.make2DAutomatic( eyez
) ) ) );
1997 lineQueue
->push_back( new Computation::ZBufLine( this, zMap
, bezierView
, tfp0
.make2DAutomatic( eyez
), tfp1
.make2DAutomatic( eyez
) ) );
2002 Computation::FilledPolygon3D::FilledPolygon3D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
,
2003 const Concrete::UnitFloatTriple
& normal
, Concrete::Length m
,
2004 Concrete::Length tiebreaker
)
2005 : Computation::PaintedPolygon3D( false, normal
, m
, tiebreaker
), metaState_( metaState
) // false means not single-sided.
2008 Computation::FilledPolygon3D::~FilledPolygon3D( )
2011 RefCountPtr
< const Lang::PaintedPolygon2D
>
2012 Computation::FilledPolygon3D::polygon_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
) const
2014 // A FilledPolygon3D is characterized by that it doesn't take notice about the lights or orientation.
2016 Concrete::Length eyez
= dyn
->getEyeZ( );
2018 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
2020 if( tf
.isIdentity( ) )
2022 typedef typeof points_ ListType
;
2023 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
2025 path
->push_back( new Concrete::PathPoint2D( i
->make2D( eyez
) ) );
2030 typedef typeof points_ ListType
;
2031 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
2033 path
->push_back( new Concrete::PathPoint2D( i
->transformed( tf
).make2D( eyez
) ) );
2037 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::PaintedPolygon2D( metaState_
, path
) );
2040 RefCountPtr
< const Lang::Color
>
2041 Computation::FilledPolygon3D::getColor( ) const
2043 return metaState_
->nonStrokingColor_
;
2047 Computation::FilledPolygon3D::gcMark( Kernel::GCMarkedSet
& marked
)
2049 // const_cast< Kernel::GraphicsState * >( metaState_.getPtr( ) )->gcMark( marked );
2052 Computation::NullPolygon3D::NullPolygon3D( )
2053 : Computation::PaintedPolygon3D( true, Concrete::UnitFloatTriple( 1., 0., 0., 1. ), 0, Concrete::ZERO_LENGTH
)
2056 Computation::NullPolygon3D::~NullPolygon3D( )
2059 RefCountPtr
< const Lang::PaintedPolygon2D
>
2060 Computation::NullPolygon3D::polygon_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
) const
2062 throw Exceptions::InternalError( "NullPolygon3D::polygon_to2D was invoked!" );
2063 // return Lang::THE_NULL_POLYGON2D;
2066 RefCountPtr
< const Lang::Color
>
2067 Computation::NullPolygon3D::getColor( ) const
2069 return Lang::THE_BLACK
;
2073 Computation::NullPolygon3D::gcMark( Kernel::GCMarkedSet
& marked
)
2077 Lang::PaintedPolygon2D::PaintedPolygon2D( RefCountPtr
< const Kernel::GraphicsState
> metaState
, RefCountPtr
< const Lang::ElementaryPath2D
> path
)
2078 : Lang::PaintedPath2D( metaState
, "E" ) // "E" for "extended fill"
2080 if( ! path
->isClosed( ) )
2082 throw Exceptions::InternalError( "Attempt to create PaintedPolygon2D with non-closed path." );
2087 Lang::PaintedPolygon2D::~PaintedPolygon2D( )
2090 RefCountPtr
< const Lang::Drawable2D
>
2091 Lang::PaintedPolygon2D::clip( std::list
< Computation::ZBufTriangle
> * regions
, const RefCountPtr
< const Lang::PaintedPolygon2D
> selfRef
) const
2093 if( regions
->empty( ) )
2095 throw Exceptions::InternalError( "Empty list of regions in PaintedPolygon2D::clip. (This triangle should not have been generated at all!)" );
2097 if( regions
->size( ) == 1 )
2099 const Computation::ZBufTriangle
& theClip
= regions
->front( );
2100 const Lang::ElementaryPath2D
& paintPath
= * path_
.front( );
2101 bool isInside
= true;
2102 for( Lang::ElementaryPath2D::const_iterator i
= paintPath
.begin( ); i
!= paintPath
.end( ); ++i
)
2104 if( ! theClip
.contains( *((*i
)->mid_
), Computation::theTrixelizeOverlapTol
) )
2116 // If we reach here, clipping shall be done
2117 Lang::Clipped2D
* resPtr
= new Lang::Clipped2D( selfRef
, "W" );
2118 Lang::ZBuf::trianglesToPolys( regions
, resPtr
);
2119 RefCountPtr
< const Lang::Clipped2D
> res( resPtr
);
2121 if( selfRef
->isContainedIn( resPtr
) )
2126 const bool SHOW_POLYS
= false;
2129 return res
->debugPolys( );
2137 Lang::PaintedPath2D::isContainedIn( const Lang::Clipped2D
* clipping
) const
2139 if( ! clipping
->isSingleConvexPoly( Computation::theTrixelizeOverlapTol
) )
2144 typedef typeof path_ PathType
;
2145 for( PathType::const_iterator subpath
= path_
.begin( ); subpath
!= path_
.end( ); ++subpath
)
2147 typedef typeof **subpath SubpathType
;
2148 for( SubpathType::const_iterator i
= (*subpath
)->begin( ); i
!= (*subpath
)->end( ); ++i
)
2150 Concrete::PathPoint2D
* pathPoint
= *i
;
2151 if( pathPoint
->rear_
!= pathPoint
->mid_
||
2152 pathPoint
->front_
!= pathPoint
->mid_
)
2156 if( ! clipping
->convexPolyContains( *(pathPoint
->mid_
), Computation::theTrixelizeOverlapTol
) )
2167 Lang::PaintedPath3D::PaintedPath3D( RefCountPtr
< const Kernel::GraphicsState
> metaState
,
2168 const char * paintCmd
, Concrete::Length tiebreaker
)
2169 : metaState_( metaState
), paintCmd_( paintCmd
), tiebreaker_( tiebreaker
)
2172 Lang::PaintedPath3D::PaintedPath3D( RefCountPtr
< const Kernel::GraphicsState
> metaState
,
2173 RefCountPtr
< const Lang::ElementaryPath3D
> path
,
2174 const char * paintCmd
, Concrete::Length tiebreaker
)
2175 : metaState_( metaState
), paintCmd_( paintCmd
), tiebreaker_( tiebreaker
)
2180 Lang::PaintedPath3D::PaintedPath3D( RefCountPtr
< const Kernel::GraphicsState
> metaState
,
2181 RefCountPtr
< const Lang::MultiPath3D
> paths
,
2182 const char * paintCmd
, Concrete::Length tiebreaker
)
2183 : metaState_( metaState
), paintCmd_( paintCmd
), tiebreaker_( tiebreaker
)
2185 for( Lang::MultiPath3D::const_iterator i
= paths
->begin( ); i
!= paths
->end( ); ++i
)
2188 typedef const Lang::ElementaryPath3D ArgType
;
2189 RefCountPtr
< ArgType
> subpath
= (*i
).down_cast
< ArgType
>( );
2190 if( subpath
!= NullPtr
< ArgType
>( ) )
2192 addSubPath( subpath
);
2198 typedef const Lang::CompositePath3D ArgType
;
2199 ArgType
* subpath
= dynamic_cast< ArgType
* >( (*i
).getPtr( ) );
2202 addSubPath( subpath
->getElementaryPath( ) );
2206 throw Exceptions::InternalError( "Painting 3D path: Encountered a subpath of unexpected type" );
2210 Lang::PaintedPath3D::~PaintedPath3D( )
2213 RefCountPtr
< const Lang::Class
> Lang::PaintedPath3D::TypeID( new Lang::SystemFinalClass( strrefdup( "PaintedPath3D" ) ) );
2214 TYPEINFOIMPL( PaintedPath3D
);
2217 Lang::PaintedPath3D::addSubPath( RefCountPtr
< const Lang::ElementaryPath3D
> subpath
)
2219 path_
.push_back( subpath
);
2222 RefCountPtr
< const Lang::Drawable2D
>
2223 Lang::PaintedPath3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2225 Concrete::Length eyez
= dyn
->getEyeZ( );
2227 RefCountPtr
< const Lang::Group2D
> res( Lang::THE_NULL2D
);
2229 if( tf
.isIdentity( ) )
2231 if( ! metaState_
->dash_
->isSolid( ) && *paintCmd_
== 'S' )
2233 for( std::list
< RefCountPtr
< const Lang::ElementaryPath3D
> >::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
2235 (*i
)->dashifyIn2D( & res
, eyez
, metaState_
);
2240 for( std::list
< RefCountPtr
< const Lang::ElementaryPath3D
> >::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
2242 res
= RefCountPtr
< const Lang::Group2D
>( new Lang::GroupPair2D( RefCountPtr
< const Lang::Drawable2D
>( new Lang::PaintedPath2D( metaState_
, (*i
)->make2D( eyez
), paintCmd_
) ),
2250 if( ! metaState_
->dash_
->isSolid( ) && *paintCmd_
== 'S' )
2252 for( std::list
< RefCountPtr
< const Lang::ElementaryPath3D
> >::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
2254 (*i
)->elementaryTransformed( tf
)->dashifyIn2D( & res
, eyez
, metaState_
);
2259 for( std::list
< RefCountPtr
< const Lang::ElementaryPath3D
> >::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
2261 res
= RefCountPtr
< const Lang::Group2D
>( new Lang::GroupPair2D( RefCountPtr
< const Lang::Drawable2D
>( new Lang::PaintedPath2D( metaState_
,
2262 (*i
)->elementaryTransformed( tf
)->make2D( eyez
),
2273 Lang::PaintedPath3D::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2275 if( strcmp( paintCmd_
, "S" ) == 0 )
2277 typedef typeof path_ ListType
;
2278 for( ListType::const_iterator subi
= path_
.begin( ); subi
!= path_
.end( ); ++subi
)
2280 const RefCountPtr
< const Lang::ElementaryPath3D
> & theSub
= *subi
;
2282 if( theSub
->size( ) < 2 )
2287 typedef typeof *theSub SubListType
;
2288 SubListType::const_iterator i
= theSub
->begin( );
2289 Concrete::Coords3D p0
= (*i
)->mid_
->transformed( tf
);
2290 SubListType::const_iterator iLast
= i
;
2292 for( ; i
!= theSub
->end( ); iLast
= i
, ++i
)
2294 Concrete::Coords3D p1
= (*i
)->mid_
->transformed( tf
);
2295 if( (*iLast
)->front_
!= (*iLast
)->mid_
|| (*i
)->rear_
!= (*i
)->mid_
)
2297 linePile
->push_back( RefCountPtr
< Computation::StrokedSplineSegment3D
>
2298 ( new Computation::StrokedSplineSegment3D( p0
, (*iLast
)->front_
->transformed( tf
), (*i
)->rear_
->transformed( tf
), p1
, metaState_
) ) );
2302 linePile
->push_back( RefCountPtr
< Computation::StrokedLine3D
>
2303 ( new Computation::StrokedLine3D( p0
, p1
, metaState_
) ) );
2307 if( theSub
->isClosed( ) )
2309 i
= theSub
->begin( );
2310 Concrete::Coords3D p1
= (*i
)->mid_
->transformed( tf
);
2311 if( (*iLast
)->front_
!= (*iLast
)->mid_
|| (*i
)->rear_
!= (*i
)->mid_
)
2313 linePile
->push_back( RefCountPtr
< Computation::StrokedSplineSegment3D
>
2314 ( new Computation::StrokedSplineSegment3D( p0
, (*iLast
)->front_
->transformed( tf
), (*i
)->rear_
->transformed( tf
), p1
, metaState_
) ) );
2318 linePile
->push_back( RefCountPtr
< Computation::StrokedLine3D
>
2319 ( new Computation::StrokedLine3D( p0
, p1
, metaState_
) ) );
2327 if( ! ( strcmp( paintCmd_
, "f" ) == 0 ||
2328 strcmp( paintCmd_
, "B" ) == 0 ) )
2330 throw Exceptions::MiscellaneousRequirement( "Only stroked and (non-*) filled polygons can be put i a z buffer." );
2334 // When we get here we know that the paintCmd_ is "f" or "B", that is, a plain fill.
2336 // if( path.size( ) > 1 )
2338 // std::cerr << "Warning: The result from triangularizing a composite path may not be what is expected." << std::endl ;
2341 typedef typeof path_ ListType
;
2342 for( ListType::const_iterator subi
= path_
.begin( ); subi
!= path_
.end( ); ++subi
)
2344 const RefCountPtr
< const Lang::ElementaryPath3D
> & theSub
= *subi
;
2346 if( theSub
->size( ) < 3 )
2350 if( ! theSub
->isClosed( ) )
2355 typedef typeof *theSub SubListType
;
2357 RefCountPtr
< Computation::FilledPolygon3D
> newPoly
= RefCountPtr
< Computation::FilledPolygon3D
>( NullPtr
< Computation::FilledPolygon3D
>( ) );
2359 // First we must compute an equation for the polygon!
2361 Concrete::Coords3D
p0( 0, 0, 0 );
2362 Concrete::Coords3D
p1( 0, 0, 0 );
2363 Concrete::Coords3D
p2( 0, 0, 0 );
2364 theSub
->getRepresentativePoints( tf
, & p0
, & p1
, & p2
);
2368 Concrete::UnitFloatTriple normal
= Concrete::crossDirection( p2
- p0
, p1
- p0
);
2369 Concrete::Length m
= Concrete::inner( normal
, p0
);
2370 newPoly
= RefCountPtr
< Computation::FilledPolygon3D
>( new Computation::FilledPolygon3D( metaState_
, normal
, m
, tiebreaker_
) );
2372 catch( const NonLocalExit::CrossDirectionOfParallel
& ball
)
2374 // This means that the crossDirection called failed because the vectors were parallel.
2375 // A polygon of lower dimension is invisible, so we may just continue
2380 zBufPile
->push_back( newPoly
);
2382 for( SubListType::const_iterator i
= theSub
->begin( ); i
!= theSub
->end( ); ++i
)
2384 if( (*i
)->front_
!= (*i
)->mid_
|| (*i
)->rear_
!= (*i
)->mid_
)
2386 throw "Corner has handle";
2388 newPoly
->pushPoint( (*i
)->mid_
->transformed( tf
) );
2394 Lang::PaintedPath3D::gcMark( Kernel::GCMarkedSet
& marked
)
2398 Lang::SingleSided3DGray::SingleSided3DGray( const RefCountPtr
< const Lang::ElementaryPath3D
> & points
,
2399 const RefCountPtr
< const Computation::FacetInterpolatorGray
> & interpolator
,
2401 const Concrete::UnitFloatTriple
& polygonUnitNormal
,
2403 Concrete::Length tiebreaker
,
2404 Concrete::Length viewResolution
,
2405 Computation::FacetShadeOrder shadeOrder
)
2406 : points_( points
), interpolator_( interpolator
), singleSided_( singleSided
), polygonUnitNormal_( polygonUnitNormal
), m_( m
), tiebreaker_( tiebreaker
),
2407 viewResolution_( viewResolution
), shadeOrder_( shadeOrder
)
2410 Lang::SingleSided3DGray::~SingleSided3DGray( )
2413 RefCountPtr
< const Lang::Class
> Lang::SingleSided3DGray::TypeID( new Lang::SystemFinalClass( strrefdup( "SingleSided3D(gray)" ) ) );
2414 TYPEINFOIMPL( SingleSided3DGray
);
2416 RefCountPtr
< const Lang::Drawable2D
>
2417 Lang::SingleSided3DGray::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2419 throw Exceptions::NotImplemented( "SingleSided3DGray::typed_to2D; What light scene should be used?" );
2423 Lang::SingleSided3DGray::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2425 Concrete::UnitFloatTriple Tnormal
= tf
.transformPlaneUnitNormal( polygonUnitNormal_
);
2427 double ax
= fabs( polygonUnitNormal_
.x_
);
2428 double ay
= fabs( polygonUnitNormal_
.y_
);
2429 double az
= fabs( polygonUnitNormal_
.z_
);
2430 Concrete::Coords3D
x0( 0, 0, 0 );
2431 if( ax
>= ay
&& ax
>= az
)
2433 x0
= Concrete::Coords3D( m_
/ polygonUnitNormal_
.x_
, 0, 0 );
2437 x0
= Concrete::Coords3D( 0, m_
/ polygonUnitNormal_
.y_
, 0 );
2441 x0
= Concrete::Coords3D( 0, 0, m_
/ polygonUnitNormal_
.z_
);
2443 Concrete::Length Tm
= Concrete::inner( Tnormal
, x0
.transformed( tf
) );
2445 RefCountPtr
< Computation::SingleSidedPolygon3DGray
> res
=
2446 RefCountPtr
< Computation::SingleSidedPolygon3DGray
>
2447 ( new Computation::SingleSidedPolygon3DGray( interpolator_
->transformed( tf
),
2455 typedef Lang::ElementaryPath3D ListType
;
2456 for( ListType::const_iterator i
= points_
->begin( ); i
!= points_
->end( ); ++i
)
2458 // The creator of *this is responsible for asserting that there are no handles at the pathpoints.
2459 res
->pushPoint( (*i
)->mid_
->transformed( tf
) );
2463 zBufPile
->push_back( res
);
2467 Lang::SingleSided3DGray::gcMark( Kernel::GCMarkedSet
& marked
)
2469 const_cast< Lang::ElementaryPath3D
* >( points_
.getPtr( ) )->gcMark( marked
);
2470 const_cast< Computation::FacetInterpolatorGray
* >( interpolator_
.getPtr( ) )->gcMark( marked
);
2474 Lang::SingleSided3DRGB::SingleSided3DRGB( const RefCountPtr
< const Lang::ElementaryPath3D
> & points
,
2475 const RefCountPtr
< const Computation::FacetInterpolatorRGB
> & interpolator
,
2477 const Concrete::UnitFloatTriple
& polygonUnitNormal
,
2479 Concrete::Length tiebreaker
,
2480 Concrete::Length viewResolution
,
2481 Computation::FacetShadeOrder shadeOrder
)
2482 : points_( points
), interpolator_( interpolator
), singleSided_( singleSided
), polygonUnitNormal_( polygonUnitNormal
), m_( m
), tiebreaker_( tiebreaker
),
2483 viewResolution_( viewResolution
), shadeOrder_( shadeOrder
)
2486 Lang::SingleSided3DRGB::~SingleSided3DRGB( )
2489 RefCountPtr
< const Lang::Class
> Lang::SingleSided3DRGB::TypeID( new Lang::SystemFinalClass( strrefdup( "SingleSided3D(RGB)" ) ) );
2490 TYPEINFOIMPL( SingleSided3DRGB
);
2492 RefCountPtr
< const Lang::Drawable2D
>
2493 Lang::SingleSided3DRGB::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2495 throw Exceptions::NotImplemented( "SingleSided3DRGB::typed_to2D; What light scene should be used?" );
2499 Lang::SingleSided3DRGB::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2501 Concrete::UnitFloatTriple Tnormal
= tf
.transformPlaneUnitNormal( polygonUnitNormal_
);
2503 double ax
= fabs( polygonUnitNormal_
.x_
);
2504 double ay
= fabs( polygonUnitNormal_
.y_
);
2505 double az
= fabs( polygonUnitNormal_
.z_
);
2506 Concrete::Coords3D
x0( 0, 0, 0 );
2507 if( ax
>= ay
&& ax
>= az
)
2509 x0
= Concrete::Coords3D( m_
/ polygonUnitNormal_
.x_
, 0, 0 );
2513 x0
= Concrete::Coords3D( 0, m_
/ polygonUnitNormal_
.y_
, 0 );
2517 x0
= Concrete::Coords3D( 0, 0, m_
/ polygonUnitNormal_
.z_
);
2519 Concrete::Length Tm
= Concrete::inner( Tnormal
, x0
.transformed( tf
) );
2521 RefCountPtr
< Computation::SingleSidedPolygon3DRGB
> res
=
2522 RefCountPtr
< Computation::SingleSidedPolygon3DRGB
>
2523 ( new Computation::SingleSidedPolygon3DRGB( interpolator_
->transformed( tf
),
2531 typedef Lang::ElementaryPath3D ListType
;
2532 for( ListType::const_iterator i
= points_
->begin( ); i
!= points_
->end( ); ++i
)
2534 // The creator of *this is responsible for asserting that there are no handles at the pathpoints.
2535 res
->pushPoint( (*i
)->mid_
->transformed( tf
) );
2539 zBufPile
->push_back( res
);
2543 Lang::SingleSided3DRGB::gcMark( Kernel::GCMarkedSet
& marked
)
2545 const_cast< Lang::ElementaryPath3D
* >( points_
.getPtr( ) )->gcMark( marked
);
2546 const_cast< Computation::FacetInterpolatorRGB
* >( interpolator_
.getPtr( ) )->gcMark( marked
);
2551 Lang::ZBuf::ZBuf( const RefCountPtr
< std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > > & pile
, const RefCountPtr
< std::list
< RefCountPtr
< Computation::StrokedLine3D
> > > & linePile
, const RefCountPtr
< std::list
< RefCountPtr
< const Lang::LightSource
> > > & lightPile
, const RefCountPtr
< const Kernel::GraphicsState
> & metaState
)
2552 : metaState_( metaState
), pile_( pile
), linePile_( linePile
), lightPile_( lightPile
)
2555 Lang::ZBuf::~ZBuf( )
2559 Lang::ZBuf::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2562 typedef typeof *pile_ ListType
;
2563 for( ListType::const_iterator i
= pile_
->begin( ); i
!= pile_
->end( ); ++i
)
2565 zBufPile
->push_back( *i
);
2569 typedef typeof *linePile_ ListType
;
2570 for( ListType::const_iterator i
= linePile_
->begin( ); i
!= linePile_
->end( ); ++i
)
2572 linePile
->push_back( *i
);
2578 Lang::ZBuf::gcMark( Kernel::GCMarkedSet
& marked
)
2580 // At the time of writing, PaintedPolygon3D is not involved in gc.
2584 Lang::ZSorter::ZSorter( const RefCountPtr
< std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > > & pile
, const RefCountPtr
< std::list
< RefCountPtr
< Computation::StrokedLine3D
> > > & linePile
, const RefCountPtr
< std::list
< RefCountPtr
< const Lang::LightSource
> > > & lightPile
, const RefCountPtr
< const Kernel::GraphicsState
> & metaState
)
2585 : metaState_( metaState
), pile_( pile
), linePile_( linePile
), lightPile_( lightPile
)
2588 Lang::ZSorter::~ZSorter( )
2592 Lang::ZSorter::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2595 typedef typeof *pile_ ListType
;
2596 for( ListType::const_iterator i
= pile_
->begin( ); i
!= pile_
->end( ); ++i
)
2598 zBufPile
->push_back( *i
);
2602 typedef typeof *linePile_ ListType
;
2603 for( ListType::const_iterator i
= linePile_
->begin( ); i
!= linePile_
->end( ); ++i
)
2605 linePile
->push_back( *i
);
2611 Lang::ZSorter::gcMark( Kernel::GCMarkedSet
& marked
)
2613 // At the time of writing, PaintedPolygon3D is not involved in gc.
2617 Lang::Transformed3D::Transformed3D( RefCountPtr
< const Lang::Drawable3D
> element
, const Lang::Transform3D
& mytf
)
2618 : mytf_( mytf
), element_( element
)
2621 Lang::Transformed3D::~Transformed3D( )
2624 RefCountPtr
< const Lang::Drawable2D
>
2625 Lang::Transformed3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2627 return element_
->typed_to2D( dyn
, Lang::Transform3D( tf
, mytf_
), element_
);
2631 Lang::Transformed3D::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2633 element_
->polygonize( zBufPile
, linePile
, dyn
, Lang::Transform3D( tf
, mytf_
), element_
);
2637 Lang::Transformed3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
2639 element_
->findTags( dst
, dyn
, key
, Lang::Transform3D( tf
, mytf_
) );
2643 Lang::Transformed3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
2646 element_
->findOneTag( evalState
, key
, Lang::Transform3D( tf
, mytf_
) );
2650 Lang::Transformed3D::gcMark( Kernel::GCMarkedSet
& marked
)
2652 const_cast< Lang::Drawable3D
* >( element_
.getPtr( ) )->gcMark( marked
);
2655 Lang::Text::Text( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
, const RefCountPtr
< const Kernel::TextState
> & textState
, const RefCountPtr
< const std::list
< RefCountPtr
< const Lang::TextOperation
> > > & elements
, const RefCountPtr
< const Lang::ElementaryPath2D
> & mybbox
)
2656 : metaState_( metaState
), textState_( textState
), elements_( elements
), mybbox_( mybbox
)
2659 Lang::Text::~Text( )
2663 Lang::Text::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
2665 pdfState
->resources_
->requireProcedureSet( SimplePDF::PDF_Resources::PROC_SET_TEXT
);
2667 pdfState
->graphics_
.synchForNonStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
2668 os
<< "BT" << std::endl
;
2669 if( ! tf
.isIdentity( ) )
2672 os
<< " Tm" << std::endl
;
2675 pdfState
->text_
.synchKnockout( os
, textState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
2677 typedef typeof *elements_ ListType
;
2678 for( ListType::const_iterator i
= elements_
->begin( ); i
!= elements_
->end( ); ++i
)
2680 (*i
)->shipout( os
, pdfState
, tf
);
2682 os
<< "ET" << std::endl
;
2686 Lang::Text::shipout_clip( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
2688 pdfState
->resources_
->requireProcedureSet( SimplePDF::PDF_Resources::PROC_SET_TEXT
);
2690 os
<< "BT" << std::endl
;
2691 if( ! tf
.isIdentity( ) )
2694 os
<< " Tm" << std::endl
;
2697 pdfState
->text_
.synchKnockout( os
, textState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
2699 typedef typeof *elements_ ListType
;
2700 for( ListType::const_iterator i
= elements_
->begin( ); i
!= elements_
->end( ); ++i
)
2702 (*i
)->shipout( os
, pdfState
, tf
, true ); /* true means "clip" */
2704 os
<< "ET" << std::endl
;
2707 RefCountPtr
< const Lang::ElementaryPath2D
>
2708 Lang::Text::bbox( Lang::Drawable2D::BoxType boxType
) const
2714 Lang::Text::gcMark( Kernel::GCMarkedSet
& marked
)
2716 typedef typeof *elements_ ListType
;
2717 for( ListType::const_iterator i
= elements_
->begin( ); i
!= elements_
->end( ); ++i
)
2719 const_cast< Lang::TextOperation
* >( i
->getPtr( ) )->gcMark( marked
);
2726 RefCountPtr
< const Lang::TransparencyGroup
>
2727 Helpers::newSolidTransparencyGroup( const RefCountPtr
< const Lang::Drawable2D
> & obj2
, const RefCountPtr
< const Lang::Drawable2D
> & obj1
)
2729 return Helpers::newTransparencyGroup( Helpers::newGroup2D( Kernel::THE_DEFAULT_STATE
, obj2
, obj1
),
2732 Lang::THE_INHERITED_COLOR_SPACE
);
2735 RefCountPtr
< const Lang::TransparencyGroup
>
2736 Helpers::newSolidTransparencyGroup( const RefCountPtr
< const Lang::Drawable2D
> & obj3
, const RefCountPtr
< const Lang::Drawable2D
> & obj2
, const RefCountPtr
< const Lang::Drawable2D
> & obj1
)
2738 return Helpers::newTransparencyGroup( Helpers::newGroup2D( Kernel::THE_DEFAULT_STATE
, obj3
, obj2
, obj1
),
2741 Lang::THE_INHERITED_COLOR_SPACE
);
2746 Computation::operator < ( const Computation::UndirectedEdge
& p1
, const Computation::UndirectedEdge
& p2
)
2748 if( p1
.low( ) < p2
.low( ) )
2752 if( p1
.low( ) > p2
.low( ) )
2756 return p1
.high( ) < p2
.high( );