00001 /*! \file wx/artbase/polyver.h 00002 \brief general vertexlist and array and vector path functions and classes. 00003 00004 All ways to have polygons and polylines stored and drawn by a drawing context 00005 are placed here. Polygon or polylines can be list based or array based. 00006 The vector path is the structure which can be used to drawn almost anything. 00007 Basic primtives can always be converted to a vector path, and drawn that way. 00008 00009 \author Klaas Holwerda, Michael Sögtrop, Faust Nijhuis 00010 \date Created 01/09/04 00011 00012 Copyright: 2001-2004 (C) Klaas Holwerda, Michael Sögtrop 00013 00014 Licence: wxWidgets licence 00015 00016 RCS-ID: $Id: polyver.h,v 1.37 2009/09/30 18:38:56 titato Exp $ 00017 */ 00018 00019 #ifndef _WX_POLYVERH__ 00020 #define _WX_POLYVERH__ 00021 00022 #include "wx/geometry.h" 00023 00024 #include "wx/general/gen.h" 00025 #include "wx/artbase/artglob.h" 00026 #include "wx/artbase/afmatrix.h" 00027 #include "wx/artbase/liner.h" 00028 #include "wx/artbase/bbox.h" 00029 00030 //! defines the way a polyline with a contour width is ended. 00031 enum a2dPATH_END_TYPE {a2dPATH_END_SQAURE, a2dPATH_END_ROUND, a2dPATH_END_SQAURE_EXT}; 00032 00033 //! is the angle within the arc segment taking into account drawing from 00034 //! start to end in clockwise or anti clocwise direction. 00035 A2DARTBASEDLLEXP bool InArc( double angle, double start, double end, bool clockwise ); 00036 00037 //! struct for how a single object on one layer was hit 00038 struct A2DARTBASEDLLEXP a2dHit 00039 { 00040 //! Basic hit type 00041 /*! For a object without childs, this is either hit_none, hit_stroke or hit_fill. 00042 A stroke hit is also given if the test-point has a margin distance from the strokes fill. 00043 This way 0-width strokes can also be hit. A distinction between a true stroke hit 00044 and a stroke margin hit is currently not possible. 00045 If the stroke or fill of a child or member is hit, the hit_child or hit_member flag is also set. 00046 Note: a2dHit is only used temporarily, so there is no need to save 00047 memory using bitfields. 00048 */ 00049 enum Hit 00050 { 00051 //! The object is not hit. This should not happen, because the parent should include hit childs 00052 hit_none = 0x00, 00053 //! The point is on the stroke or stroke margin 00054 hit_stroke = 0x01, 00055 //! The point is in the fill area 00056 hit_fill = 0x02, 00057 //! The point hits a child of the object 00058 hit_child = 0x04, 00059 //! The point hits a member of the object (e.g. line begin/end object) 00060 hit_member = 0x08, 00061 //! a hit which resulted into a captured object, and may now not hit the object itself, 00062 //! still the object will recieve mouse events. 00063 hit_captured = 0x10 00064 } m_hit; 00065 00066 friend inline Hit operator | ( Hit a, Hit b ) { return ( Hit )( ( int )a | ( int ) b ); } 00067 00068 //! How the point is on the stroke ( in stroke perpendicular direction ) 00069 enum Stroke1 00070 { 00071 stroke1_none, 00072 // the hit is on the outside (non-fill) margin of the stroke 00073 stroke1_outside, 00074 // the hit is on the inside (fill) margin of the stroke 00075 stroke1_inside 00076 } m_stroke1; 00077 00078 //! How the point is on the stroke ( in stroke parallel direction ) 00079 enum Stroke2 00080 { 00081 stroke2_none, 00082 stroke2_vertex, 00083 stroke2_edgehor, 00084 stroke2_edgevert, 00085 stroke2_edgeother 00086 } m_stroke2; 00087 00088 //! For edge/vertex hits the index of the edge / vertex 00089 unsigned int m_index; 00090 00091 //! For margin hits, the distance from the stroke center in fractions of the margin 00092 /*! Note: using a fraction of the margin makes the distance independent of local scaling */ 00093 float m_distance; 00094 00095 //! Default constructor 00096 a2dHit() { memset( this, 0, sizeof( *this ) ); } 00097 //! Standard constructor 00098 a2dHit( Hit hit, Stroke1 stroke1, Stroke2 stroke2, unsigned int index, float distance ) 00099 { 00100 m_hit = hit; 00101 m_stroke1 = stroke1; 00102 m_stroke2 = stroke2; 00103 m_distance = distance; 00104 m_index = index; 00105 } 00106 //! true if this is a hit 00107 bool IsHit() const { return m_hit != hit_none; } 00108 //! true if this is a stroke hit (parent or child/member stroke) 00109 bool IsStrokeHit() const { return ( m_hit & hit_stroke ) != 0; } 00110 //! true if this is a fill hit (parent or child/member fill) 00111 bool IsFillHit() const { return ( m_hit & hit_fill ) != 0; } 00112 //! true if this is a fill hit or an inside stroke hit (parent or child/member) 00113 bool IsInsideHit() const { return ( m_hit & hit_fill ) != 0 || ( m_hit & hit_stroke ) != 0 && m_stroke1 == stroke1_inside; } 00114 00115 //! true if this is a direct stroke hit (not a member or child object stroke hit ) 00116 bool IsDirectStrokeHit() const { return m_hit == hit_stroke; } 00117 //! true if this is a direct fill hit (not a member or child object fill hit ) 00118 bool IsDirectFillHit() const { return m_hit == hit_fill; } 00119 //! true if this is child hit 00120 bool IsChildHit() const { return ( m_hit & hit_child ) != 0; } 00121 //! true if this is member object hit (e.g. line begin/end object) 00122 bool IsMemberdHit() const { return ( m_hit & hit_member ) != 0; } 00123 00124 //! true if this is a stroke hit on an edge 00125 bool IsEdgeHit() const 00126 { 00127 return ( IsStrokeHit() && 00128 ( stroke2_edgehor || stroke2_edgevert || stroke2_edgeother ) ) != 0 ; 00129 } 00130 00131 //! Stock object for no hit 00132 static a2dHit stock_nohit; 00133 //! Stock object for a fill hit 00134 static a2dHit stock_fill; 00135 //! Stock object for an outer stroke hit on objects without vertices/edges (like circles) 00136 static a2dHit stock_strokeoutside; 00137 //! Stock object for an inner stroke hit on objects without vertices/edges (like circles) 00138 static a2dHit stock_strokeinside; 00139 }; 00140 00141 //! defines the type of a segment in a a2dLineSegment 00142 enum a2dSegType 00143 { 00144 //! not specific or part of outer contour 00145 a2dNORMAL_SEG = 0x0000, 00146 //! links an outside contour with a hole 00147 a2dLINK_SEG = 0x0001, 00148 //! this segmnet is part of a hole 00149 a2dHOLE_SEG = 0x0002 00150 }; 00151 00152 //! Normal straight line segment in a2dVertexList and a2dVertexArray 00153 /*! baseclass for segments in a a2dVertexList and a2dVertexArray 00154 Every segment type in a a2dVertexList and a2dVertexArray has this class as Baseclass. 00155 It has/maintains the end position of a segment. 00156 But for the first point it is a2dVertexList and a2dVertexArray to give the begin point too. 00157 00158 \ingroup vpath 00159 */ 00160 class A2DARTBASEDLLEXP a2dLineSegment 00161 { 00162 00163 #ifdef CLASS_MEM_MANAGEMENT 00164 00165 //! memory manager for speed up to replace system calls allocation and deallocation 00166 static a2dMemManager sm_memManager; 00167 public: 00168 //! overloaded operator new for this class and it all derived classes 00169 void* operator new( size_t bytes ) 00170 { 00171 return sm_memManager.Allocate( bytes ); 00172 } 00173 00174 //! overloaded operator delete for this class and it all derived classes 00175 /*! 00176 This function doesn't free to OS-system memory block by pointer 'space'. 00177 It adds memory block by pointer 'space' to internal lists. 00178 It is speed up. 00179 */ 00180 void operator delete( void *space, size_t bytes ) 00181 { 00182 sm_memManager.Deallocate( space, bytes ); 00183 } 00184 #endif //CLASS_MEM_MANAGEMENT 00185 00186 public: 00187 00188 //! constructor 00189 /*! 00190 \param x endpoint of line 00191 \param y endpoint of line 00192 */ 00193 a2dLineSegment( double x = 0, double y = 0 ); 00194 00195 a2dLineSegment( const a2dPoint2D& point ); 00196 00197 a2dLineSegment( const a2dLineSegment &other ); 00198 00199 virtual ~a2dLineSegment(); 00200 00201 //! create exact copy 00202 virtual a2dLineSegment* Clone(); 00203 00204 inline bool GetArc() const { return m_arc; } 00205 00206 //klion: it is for multipoint 00207 inline int GetPointCount() const { return m_pntCnt;} 00208 00209 inline bool GetBin() const { return m_bin; } 00210 00211 inline void SetBin( bool bin ) { m_bin = bin; } 00212 00213 //! calculate length 00214 virtual double Length( const a2dLineSegment& prev ); 00215 00216 a2dPoint2D GetPoint() { return a2dPoint2D( m_x, m_y ); } 00217 00218 //! Set the type of the segment 00219 void SetSegType( a2dSegType type ) { m_segtype = type; } 00220 00221 //! get the type of the segment 00222 a2dSegType GetSegType() { return m_segtype; } 00223 00224 virtual a2dBoundingBox GetBbox( const a2dLineSegment& prev, const a2dAffineMatrix& lworld = a2dIDENTITY_MATRIX ); 00225 00226 //!x endpoint of line 00227 double m_x; 00228 00229 //!y endpoint of line 00230 double m_y; 00231 00232 //! Marker for walking over the segments 00233 bool m_bin: 1; 00234 00235 //! arc segment 00236 bool m_arc: 1; 00237 00238 //klion: it is for multipoint 00239 unsigned int m_pntCnt: 2; 00240 00241 //! type of segment 00242 a2dSegType m_segtype: 3; 00243 00244 public: 00245 00246 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG) 00247 //! this is a list of all smart pointers pointing to this object 00248 a2dSmrtPtr<a2dLineSegment> *m_ownerlist; 00249 //! this is needed inside the smart pointer template code 00250 typedef a2dSmrtPtr<a2dLineSegment> TOwnerListClass; 00251 //! Make a Dump of the objects owner list to the Debug console 00252 /*! This function is usually called from the Debuggers watch window */ 00253 void DumpOwners(); 00254 #endif 00255 00256 private: 00257 //!how many references to this object do exist 00258 int m_refcount; 00259 00260 //! Call to have a new owner for this object 00261 /*! This function should only be called by a2dSmrtPtr 00262 00263 \remark owning mean that the object calling this member needs to call Release at some time, 00264 in order to actually release/delete the object. 00265 00266 \return The return value is the object itself, which is now owned on time extra. 00267 00268 increment refcount by 1 ( use when adding a reference to this object) 00269 */ 00270 a2dLineSegment* SmrtPtrOwn() { m_refcount++; return this; } 00271 00272 //!To release the object, it is not longer owned by the calling object. 00273 /*! This function should only be called by a2dSmrtPtr 00274 */ 00275 bool SmrtPtrRelease() 00276 { 00277 m_refcount--; 00278 wxASSERT_MSG( m_refcount >= 0, wxT( "a2dLineSegment Own/Release not matched (extra Release calls)" ) ); 00279 if ( m_refcount <= 0 ) 00280 { 00281 delete this; 00282 return true; 00283 } 00284 return false; 00285 } 00286 00287 private: 00288 friend class a2dSmrtPtrBase; 00289 }; 00290 00291 //! smart pointer to line segment 00292 typedef a2dSmrtPtr<a2dLineSegment> a2dLineSegmentPtr; 00293 00294 #if defined(WXART2D_USINGDLL) 00295 template class A2DARTBASEDLLEXP a2dSmrtPtr<a2dLineSegment>; 00296 #endif 00297 00298 #if defined(WXART2D_USINGDLL) 00299 // it must be after all internal template declarations 00300 template class A2DARTBASEDLLEXP std::allocator<class a2dSmrtPtr<class a2dLineSegment> >; 00301 template class A2DARTBASEDLLEXP std::allocator< std::_List_nod<class a2dSmrtPtr<class a2dLineSegment>, std::allocator<class a2dSmrtPtr<class a2dLineSegment> > >::_Node >; 00302 template class A2DARTBASEDLLEXP std::allocator< std::_List_ptr<class a2dSmrtPtr<class a2dLineSegment>, std::allocator<class a2dSmrtPtr<class a2dLineSegment> > >::_Nodeptr >; 00303 template class A2DARTBASEDLLEXP std::list<class a2dSmrtPtr<class a2dLineSegment> >::iterator; 00304 template class A2DARTBASEDLLEXP std::list<class a2dSmrtPtr<class a2dLineSegment> >; 00305 template class A2DARTBASEDLLEXP a2dlist< a2dSmrtPtr<a2dLineSegment> >; 00306 template class A2DARTBASEDLLEXP a2dSmrtPtrList<a2dLineSegment>; 00307 #endif 00308 00309 #if 0 00310 class a2dLineSegmentProperty; 00311 typedef a2dPropertyIdTyped< a2dLineSegment, a2dLineSegmentProperty> a2dPropertyIdLineSegment; 00312 00313 //! property to hold a pointer to a linesegment 00314 ///*! 00315 00316 a2dPolyHandle::PROPID_linesegment.SetPropertyObjectToObject( 00317 handle, new a2dLineSegmentProperty( a2dPolyHandle::PROPID_linesegment, seg ) ); 00318 00319 a2dLineSegment* segment = a2dHandle::PROPID_linesegment.GetPropertyValuePtr( handle ); 00320 00321 \ingroup property 00322 /// 00323 class a2dLineSegmentProperty: public a2dNamedProperty 00324 { 00325 public: 00326 00327 a2dLineSegmentProperty(); 00328 00329 a2dLineSegmentProperty( const a2dPropertyIdLineSegment &id, a2dLineSegment* segment ); 00330 00331 a2dLineSegmentProperty( const a2dLineSegmentProperty &other ); 00332 00333 virtual a2dNamedProperty *Clone( a2dObject::CloneOptions options ) const; 00334 00335 virtual void Assign( const a2dNamedProperty &other ); 00336 00337 virtual ~a2dLineSegmentProperty(); 00338 00339 //! Construct a new property object from a string 00340 //! If this is not appropriate, this may return NULL 00341 static a2dLineSegmentProperty *CreatePropertyFromString( const a2dPropertyIdLineSegment &id, const wxString &value ); 00342 00343 a2dLineSegment* GetValuePtr() { return m_segment; } 00344 00345 #if wxART2D_USE_CVGIO 00346 virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite ); 00347 virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts ); 00348 #endif //wxART2D_USE_CVGIO 00349 00350 DECLARE_DYNAMIC_CLASS( a2dLineSegmentProperty ) 00351 00352 protected: 00353 00354 a2dLineSegment* m_segment; 00355 }; 00356 #endif 00357 00358 //! Arc Segment in a2dVertexList 00359 /*! Create an circular Arc segment. 00360 From the previous segment to this segment position, create an arc 00361 passing through a thrid point. 00362 The Third point defines the Arc segment going clockwise or anticlockwise from begin to end point. 00363 00364 \ingroup vpath 00365 */ 00366 class A2DARTBASEDLLEXP a2dArcSegment : public a2dLineSegment 00367 { 00368 public: 00369 00370 //! create arc segment 00371 /*! 00372 Begin point of arc is position/endpoint of previous segment 00373 \param x1 x of arc endpoint 00374 \param y1 y of arc endpoint 00375 \param x2 x of arc midpoint 00376 \param y2 y of arc midpoint 00377 */ 00378 a2dArcSegment( double x1 = 0, double y1 = 0, double x2 = 0, double y2 = 0 ); 00379 00380 //! create arc segment 00381 /*! 00382 Begin point of arc is position/endpoint of previous segment 00383 \param prev previous segment 00384 \param xc x of arc center 00385 \param yc y of arc center 00386 \param angle angle of arc in degrees relative from the previous segment endpoint (negatif for clockwise) 00387 */ 00388 a2dArcSegment( const a2dLineSegment& prev, double xc, double yc, double angle ); 00389 00390 //! create arc segment 00391 /*! 00392 Begin point of arc is position/endpoint of previous segment 00393 \param prev previous segment 00394 \param xc x of arc center 00395 \param yc y of arc center 00396 \param x1 x of arc endpoint 00397 \param y1 y of arc endpoint 00398 \param x2 x (xc,yc) ( x2,y2) define a line which the arc will cross 00399 \param y2 y (xc,yc) ( x2,y2) define a line which the arc will cross 00400 00401 \remark radius is defined by prev segment endpoint and (xc,yc), x1,y1 is adjusted to fit radius. 00402 */ 00403 a2dArcSegment( const a2dLineSegment& prev, double xc, double yc, double x1, double y1, double x2, double y2 ); 00404 00405 //! copy constructor 00406 a2dArcSegment( const a2dArcSegment &other ); 00407 00408 //! destructor 00409 ~a2dArcSegment(); 00410 00411 //! create exact copy 00412 virtual a2dLineSegment* Clone(); 00413 00414 //! Calculation of center for the Arc 00415 /*! output : 00416 \param prev the previous segment, to get start point of arc. 00417 \param radius radius of the circle calculated 00418 \param center_x x of the center calculated 00419 \param center_y y of the center calculated 00420 \param beginrad calculated starting angle in radians 00421 \param midrad calculated middle angle in radians 00422 \param endrad calculated end angle in radians 00423 \param phit total calculated in radians (AntiClockwise positif, else negatif ) 00424 00425 \return true if the arc is indeed an Arc if a straight line return false. 00426 */ 00427 bool CalcR( const a2dLineSegment& prev, double& radius, double& center_x, double& center_y, double& beginrad, double& midrad, double& endrad, double& phit ) const; 00428 00429 //! calculate length 00430 virtual double Length( const a2dLineSegment& prev ); 00431 00432 //! calculate new mid point bsed on prev segment radius and center. 00433 /*! 00434 \param prev the previous segment, to get start point of arc. 00435 \param radius radius of the circle calculated 00436 \param center_x x of the center calculated 00437 \param center_y y of the center calculated 00438 \param clockwise if true a clockwise arc segment is assumed for creating the mid point 00439 */ 00440 void CalcMidPoint( const a2dLineSegment& prev, double center_x, double center_y, double radius, bool clockwise ); 00441 00442 //! get middle on arc segment between end and start 00443 a2dPoint2D GetMidPoint() const { return a2dPoint2D( m_x2, m_y2 ); } 00444 00445 //! set middle point of arc segment 00446 /*! 00447 \param prev the previous segment, to get start point of arc. 00448 \param xm x of middle point 00449 \param ym y of middle point 00450 */ 00451 void SetMidPoint( const a2dLineSegment& prev, double xm, double ym ); 00452 00453 //! Get origin X of arc 00454 double GetOx( const a2dLineSegment& prev ) const; 00455 00456 //! Get origin Y of arc 00457 double GetOy( const a2dLineSegment& prev ) const; 00458 00459 //! Get origin of arc 00460 a2dPoint2D GetOrigin( const a2dLineSegment& prev ) const; 00461 00462 //! Get bounding box of arc 00463 a2dBoundingBox GetBbox( const a2dLineSegment& prev, const a2dAffineMatrix& lworld = a2dIDENTITY_MATRIX ) const; 00464 00465 //! x2 x of arc midpoint 00466 double m_x2; 00467 //! y2 y of arc midpoint 00468 double m_y2; 00469 }; 00470 00471 #include <vector> 00472 #include <wx/listimpl.cpp> 00473 00474 //! array of polygon vertexes a2dLineSegment 00475 /*! 00476 \ingroup canvasobject 00477 */ 00478 00479 class A2DARTBASEDLLEXP a2dVertexList; 00480 class A2DARTBASEDLLEXP a2dVpath; 00481 00482 //! vertex array of line and arc segments. 00483 /*! 00484 Holds a wxArray of a2dLineSegment objects. 00485 Drawing the sequence of segments, represents the form of the shape. 00486 Shape depends on the type of segment and style of that segment. 00487 There are two type, straight line segments and arc segments 00488 */ 00489 class A2DARTBASEDLLEXP a2dVertexArray : public std::vector<a2dLineSegmentPtr> 00490 { 00491 public: 00492 00493 //! constructor 00494 a2dVertexArray(); 00495 00496 //! constructor 00497 a2dVertexArray( const a2dVertexArray &other ); 00498 00499 a2dVertexArray( const a2dVertexList &other ); 00500 00501 //! destructor 00502 ~a2dVertexArray(); 00503 00504 //! operator = 00505 a2dVertexArray& operator=( const a2dVertexArray &other ); 00506 00507 a2dVertexArray& operator=( const a2dVertexList &other ); 00508 00509 //! get the previous segment as a polygon ( GetLast() is no previous ) 00510 a2dLineSegmentPtr GetPreviousAround( wxUint32 index ) const; 00511 00512 //! get the next segment as a polygon ( GetFirst() is no next ) 00513 a2dLineSegmentPtr GetNextAround( wxUint32 index ) const; 00514 00515 a2dLineSegmentPtr Item( wxUint32 index ) { return this->operator[](index); } 00516 00517 a2dLineSegmentPtr Item( wxUint32 index ) const { return this->operator[](index); } 00518 00519 void RemoveAt(size_t index); 00520 00521 void Insert( a2dLineSegment* segment, size_t index ); 00522 00523 //! calculate length of path 00524 double Length() const; 00525 00526 //! add point to end or begin 00527 void AddPoint( const a2dPoint2D& point, bool atEnd = true ); 00528 00529 //! add point to end or begin 00530 void AddPoint( double x, double y, bool atEnd = true ); 00531 00532 //! sets a point of a segment and adjusts arc it midpoints. 00533 void SetPointAdjustArcs( unsigned int n, double x, double y, bool polygon ); 00534 00535 //! sets a point of a segment and adjusts arc it midpoints. 00536 void SetPointAdjustArcs( a2dLineSegmentPtr seg, double x, double y, bool polygon ); 00537 00538 //! calculate the area of simple polygons (not selfintersecting) 00539 //! coordinates may be negatif 00540 double CalcArea() const; 00541 00542 //! Convert complex segments to line segments. 00543 void ConvertToLines( double aberation = 0 ); 00544 00545 //! transform all segments with given matrix 00546 /*! \remark complex segments will be broken down to lines. */ 00547 void Transform( const a2dAffineMatrix& world ); 00548 00549 //! return true if there are a2dArcSegment segments. 00550 bool HasArcs() const; 00551 00552 //! return a boundingbox of a transformed vertexarray 00553 a2dBoundingBox GetBbox( const a2dAffineMatrix& lworld = a2dIDENTITY_MATRIX ); 00554 00555 //! create a contour around polygon/polyline 00556 a2dVertexArray* Contour( double distance, a2dPATH_END_TYPE pathtype ); 00557 00558 //!Spline conversion for polygon. 00559 a2dVertexArray* ConvertSplinedPolygon( double Aber ) const; 00560 00561 //!Spline conversion for polyline. 00562 a2dVertexArray* ConvertSplinedPolyline( double Aber ) const; 00563 00564 //! return converted vector Vpath, arc segments stay intact if arc is true 00565 a2dVpath* ConvertToVpath( bool arc, bool closed = false ); 00566 00567 //! extensive hittesting on vertex list seen as polygon. 00568 /*! 00569 \param ptest point to test against polygon. 00570 \param margin point with this margin around. 00571 */ 00572 a2dHit HitTestPolygon( const a2dPoint2D& ptest, double margin ); 00573 00574 //! extensive hittesting on vertex list seen as polyline. 00575 /*! 00576 \param ptest point to test against polyline. 00577 \param margin point with this margin around. 00578 */ 00579 a2dHit HitTestPolyline( const a2dPoint2D& ptest, double margin ); 00580 00581 //! line segments ( not arcs ) with same point are removed 00582 bool RemoveRedundant( bool polygon ); 00583 00584 //! line segments ( not arcs ) with same point are returned 00585 a2dVertexList* GetRedundant( bool polygon, double smallest = 0 ); 00586 }; 00587 00588 //! vertex list of line and arc segments. 00589 /*! 00590 Holds a wxList of a2dLineSegment objects. 00591 Drawing the sequence of segments, represents the form of the shape. 00592 Shape depends on the type of segment and style of that segment. 00593 There are two type, straight line segments and arc segments 00594 */ 00595 class A2DARTBASEDLLEXP a2dVertexList : public a2dSmrtPtrList< a2dLineSegment > 00596 { 00597 public: 00598 a2dVertexList(); 00599 00600 a2dVertexList( const a2dVertexList &other ); 00601 00602 a2dVertexList( const a2dVertexArray &other ); 00603 00604 ~a2dVertexList(); 00605 00606 a2dVertexList& operator=( const a2dVertexList &other ); 00607 00608 a2dVertexList& operator=( const a2dVertexArray &other ); 00609 00610 //! return true if there are a2dArcSegment segments. 00611 bool HasArcs() const; 00612 00613 //! get the previous segment as a polygon ( --end() is no previous ) 00614 a2dVertexList::iterator GetPreviousAround( a2dVertexList::iterator iter ); 00615 00616 //! get the next segment as a polygon ( begin() is no next ) 00617 a2dVertexList::iterator GetNextAround( a2dVertexList::iterator iter ); 00618 00619 //! get the previous segment as a polygon ( --end() is no previous ) 00620 a2dVertexList::const_iterator GetPreviousAround( a2dVertexList::const_iterator iter ) const; 00621 00622 //! get the next segment as a polygon ( begin() is no next ) 00623 a2dVertexList::const_iterator GetNextAround( a2dVertexList::const_iterator iter ) const; 00624 00625 //! make the segmenet where iter point to the beginning of the list and shift the rest 00626 void MakeBegin( a2dVertexList::iterator iter ); 00627 00628 //! calculate length of path 00629 double Length(); 00630 00631 //! Find the index of a specific object 00632 int IndexOf( a2dLineSegment* object ) const; 00633 00634 //! insert before segment with index given 00635 void Insert( unsigned int index, a2dLineSegmentPtr segin ); 00636 00637 //! sets a point of a segment and adjusts arc it midpoints. 00638 void SetPointAdjustArcs( unsigned int n, double x, double y, bool polygon ); 00639 00640 void SetPointAdjustArcs( a2dLineSegmentPtr segin, double x, double y, bool polygon ); 00641 00642 //! Convert complex segments to line segments. 00643 void ConvertToLines( double aberation = 0 ); 00644 00645 //! variation on ConvertToLines, this function converts an arc into segments were 00646 //! the number of segments is determined by dphi (maximum angle of a piece) and 00647 //! minseg (the arc will contain a minimum of minseg segments). 00648 //! e.g. if you specify dphi on 10 a circle will be converted into 36 segments, 00649 //! however if you specify minseg as 40, it will be converted to 40 segments. 00650 void ConvertToLines( double dphi, int minseg ); 00651 00652 //! calculate the area of simple polygons (not selfintersecting) 00653 //! coordinates may be negatif 00654 double CalcArea() const; 00655 00656 //! determines the direction of the polygon, all polygons must be in a 00657 //! clockwise order to avoid conflics with certain algortihms. When 00658 //! the polygon is in a non-clockwise order the area of the polygon is in 00659 //! a clockwise order. 00660 //! returns true if the polygon is in clockwise order 00661 bool DirectionIsClockWise(); 00662 00663 bool CheckForOneCircle( a2dPoint2D& middle, double& radius ); 00664 00665 //! The point on the polyline which form an arc meeting the constraints, will be replaced 00666 //! by an Arc segment. 00667 //! The Arc segment will be with the following 4 coordinates: 00668 //! - start point 00669 //! - end point 00670 //! - mid point (a point half way on the arc between start and end) 00671 //! - center point 00672 //! In principle only 3 point are need to define a circle, but if start and end point are the same, 00673 //! the center point will be needed to. 00674 //! 00675 //! \param iter start of first point 00676 //! \param n ( number of point2 to replace with arc ) 00677 //! \param center_x center_x (center point of the ARC) 00678 //! \param center_y center_y (center point of the ARC) 00679 void InsertArc( a2dVertexList::iterator& iter, int n, double center_x, double center_y ); 00680 00681 //! De punten van de polygon worden getest of ze converteerd kunnen 00682 //! worden naar ARC's. 00683 //! Conversie vind plaats als; aberatie < aber 00684 //! Rmin < radius < Rmax 00685 void ConvertPolylineToArc(double aber,double Rmin,double Rmax); 00686 00687 void ConvertPolygonToArc(double aber,double Rmin,double Rmax); 00688 00689 //! a row of point (minimum 4 ) will be tested to see if its an arc. 00690 /*! 00691 3 options: 00692 - aber > 0 arc should be within this margin to all points 00693 - aber = 0 arc points should be exact on the arc. The largets distance of segments to arc 00694 is not important. 00695 - aber < 0 combines the first two options. 00696 00697 Abberation means maximum distance along a segment towards the perfect arc. 00698 00699 \param iter start testing here 00700 \param aber see above 00701 \param Rmin (minimum radius) 00702 \param Rmax (maximum radius) 00703 \param center_p_old (centerpunt van circelboog) 00704 00705 \return number of points found to be an arc 00706 */ 00707 int TestArc( a2dVertexList::iterator& iter, double aber, double Rmin, double Rmax , a2dPoint2D& center_p_old ); 00708 00709 //! return a boundingbox of a transformed vertexarray 00710 a2dBoundingBox GetBbox( const a2dAffineMatrix& lworld = a2dIDENTITY_MATRIX ); 00711 00712 //! transform all segments with given matrix 00713 /*! \remark complex segments will be broken down to lines. */ 00714 void Transform( const a2dAffineMatrix& world ); 00715 00716 //!Spline conversion for polygon. 00717 a2dVertexList* ConvertSplinedPolygon( double Aber ) const; 00718 00719 //!Spline conversion for polyline. 00720 a2dVertexList* ConvertSplinedPolyline( double Aber ) const; 00721 00722 void ConvertIntoSplinedPolygon( double Aber ); 00723 00724 void ConvertIntoSplinedPolyline( double Aber ); 00725 00726 //! create a contour around polygon/polyline 00727 a2dVertexList* ConvertToContour( double distance, a2dPATH_END_TYPE pathtype, bool asPolygon = false ); 00728 00729 //! return converted vector Vpath, arc segments stay intact if arc is true 00730 a2dVpath* ConvertToVpath( bool arc, bool closed = false ); 00731 00732 //! create a contour around polygon/polyline 00733 void Contour( double distance, a2dPATH_END_TYPE pathtype, bool asPolygon = false ); 00734 00735 //! add point to end or begin 00736 void AddPoint( const a2dPoint2D& point, bool atEnd = true ); 00737 00738 //! add point to end or begin 00739 void AddPoint( double x, double y, bool atEnd = true ); 00740 00741 //! create an arc and add it to the graph 00742 /*! 00743 \param center of circle 00744 \param begin point of arc 00745 \param end point of arc 00746 \param radius of arc 00747 \param clock if true clockwise 00748 \param aber aberation for generating the segments 00749 \param addAtFront where to add this segment 00750 */ 00751 void CreateArc( const a2dPoint2D& center, const a2dPoint2D& begin, const a2dPoint2D& end, double radius, bool clock, double aber, bool addAtFront ); 00752 00753 //! create an arc and add it to the graph 00754 /*! 00755 \param center of circle 00756 \param incoming last segment starting this segment 00757 \param end point of arc 00758 \param radius of arc 00759 \param aber aberation for generating the segments 00760 \param addAtFront where to add this segment 00761 */ 00762 void CreateArc( const a2dPoint2D& center, const a2dLine& incoming, const a2dPoint2D& end, double radius, double aber, bool addAtFront ); 00763 00764 //! create a contour segements at a distance, using two segment 00765 /*! 00766 The angle of the two connected segments in combination with the factor is used to decide 00767 if the corner is rounded or straight. 00768 00769 \param currentline 00770 \param nextline 00771 \param factor 00772 \param addAtFront where to add this segment 00773 */ 00774 void OffsetContour_rounded( const a2dLine& currentline, const a2dLine& nextline, double factor, bool addAtFront ); 00775 00776 //! line segments ( not arcs ) with same point are removed 00777 bool RemoveRedundant( bool polygon ); 00778 00779 //! line segments ( not arcs ) with same point are returned 00780 a2dVertexList* GetRedundant( bool polygon, double smallest = 0 ); 00781 00782 //! extensive hittesting on vertex list seen as polygon. 00783 /*! 00784 \param ptest point to test against polygon. 00785 \param margin point with this margin around. 00786 */ 00787 a2dHit HitTestPolygon( const a2dPoint2D& ptest, double margin ); 00788 00789 //! extensive hittesting on vertex list seen as polyline. 00790 /*! 00791 \param ptest point to test against polyline. 00792 \param margin point with this margin around. 00793 */ 00794 a2dHit HitTestPolyline( const a2dPoint2D& ptest, double margin ); 00795 00796 private: 00797 //!how many references to this object do exist 00798 int m_refcount; 00799 00800 //! Call to have a new owner for this object 00801 /*! This function should only be called by a2dSmrtPtr 00802 00803 \remark owning mean that the object calling this member needs to call Release at some time, 00804 in order to actually release/delete the object. 00805 00806 \return The return value is the object itself, which is now owned on time extra. 00807 00808 increment refcount by 1 ( use when adding a reference to this object) 00809 */ 00810 a2dVertexList* SmrtPtrOwn() { m_refcount++; return this; } 00811 00812 //!To release the object, it is not longer owned by the calling object. 00813 /*! This function should only be called by a2dSmrtPtr 00814 */ 00815 bool SmrtPtrRelease() 00816 { 00817 m_refcount--; 00818 wxASSERT_MSG( m_refcount >= 0, wxT( "a2dLineSegment Own/Release not matched (extra Release calls)" ) ); 00819 if ( m_refcount <= 0 ) 00820 { 00821 delete this; 00822 return true; 00823 } 00824 return false; 00825 } 00826 00827 private: 00828 friend class a2dSmrtPtrBase; 00829 }; 00830 00831 typedef a2dSmrtPtr< a2dVertexList > a2dVertexListPtr; 00832 00833 typedef a2dVertexList::iterator a2dVertexListIter; 00834 00835 typedef a2dSmrtPtrList< a2dVertexList > a2dListOfa2dVertexList; 00836 00837 //! how do we move to the point of the segment 00838 /*! 00839 \ingroup vpath 00840 */ 00841 enum a2dPATHSEG { 00842 a2dPATHSEG_MOVETO, /*!< Move to point */ 00843 a2dPATHSEG_LINETO, /*!< Line to point */ 00844 a2dPATHSEG_LINETO_NOSTROKE, /*!< Line to point without stroke (if not closed as polygon, same as moveto) */ 00845 a2dPATHSEG_QBCURVETO, /*!< Quadratic Bezier Curve */ 00846 a2dPATHSEG_QBCURVETO_NOSTROKE, /*!< Quadratic Bezier Curve to point without stroke (if not closed as polygon, same as moveto) */ 00847 a2dPATHSEG_CBCURVETO, /*!< Cubic Bezier Curve */ 00848 a2dPATHSEG_CBCURVETO_NOSTROKE, /*!< Cubic Bezier Curve to point without stroke (if not closed as polygon, same as moveto) */ 00849 a2dPATHSEG_ARCTO, /*!< Arc */ 00850 a2dPATHSEG_ARCTO_NOSTROKE /*!< arc to point without stroke (if not closed as polygon, same as moveto) */ 00851 }; 00852 00853 //! end of a segment type 00854 /*! 00855 \ingroup vpath 00856 */ 00857 enum a2dPATHSEG_END { 00858 a2dPATHSEG_END_OPEN, /*!< Open end */ 00859 a2dPATHSEG_END_CLOSED, /*!< Closed to last a2dPATHSEG_MOVETO segment */ 00860 a2dPATHSEG_END_CLOSED_NOSTROKE, /*!< Closed to last a2dPATHSEG_MOVETO segment with No Stroke*/ 00861 }; 00862 00863 //! Normal straight line segment in a2dVpath 00864 /*! baseclass for segments in a a2dVpath 00865 Every segment type in a a2dVpath has this class as Baseclass. 00866 It has/maintains the end position of a segment. 00867 But for the first point it is a2dVpathSegment to give the begin point too. 00868 00869 \ingroup vpath 00870 */ 00871 class A2DARTBASEDLLEXP a2dVpathSegment 00872 { 00873 public: 00874 00875 //! constructor 00876 /*! 00877 \param x endpoint of line 00878 \param y endpoint of line 00879 \param type line type ( e.g line to, move to, no stroking ) 00880 \param close endpoint closes the shape. 00881 */ 00882 a2dVpathSegment( double x, double y, a2dPATHSEG type = a2dPATHSEG_LINETO, a2dPATHSEG_END close = a2dPATHSEG_END_OPEN ); 00883 00884 //! constructor 00885 a2dVpathSegment( const a2dVpathSegment &other ); 00886 00887 //! destructor 00888 virtual ~a2dVpathSegment(); 00889 00890 //! create exact copy 00891 virtual a2dVpathSegment* Clone(); 00892 00893 //! easy way to test type of segment 00894 inline a2dPATHSEG GetType() const { return m_type; } 00895 00896 //! used in processing 00897 inline bool GetBin() const { return m_bin; } 00898 00899 //! used in processing 00900 inline void SetBin( bool bin ) { m_bin = bin; } 00901 00902 //! is this segment the closing a part since the last move 00903 inline a2dPATHSEG_END GetClose() const { return m_close; } 00904 00905 //! set this segment is closing a part since the last move 00906 inline void SetClose( a2dPATHSEG_END close ) { m_close = close; } 00907 00908 //! calculate length 00909 virtual double Length( const a2dVpathSegment& prev ); 00910 00911 //!x endpoint of line 00912 double m_x1; 00913 00914 //!y endpoint of line 00915 double m_y1; 00916 00917 //! Marker for walking over the segments 00918 bool m_bin : 1; 00919 00920 //! easy way to test type of segment 00921 a2dPATHSEG m_type : 5; 00922 00923 //! is the path closing here or not 00924 a2dPATHSEG_END m_close : 3; 00925 }; 00926 00927 00928 //! Quadratic Bezier curve 00929 /*! Create a curved segment based on qaudratic Bezier spline 00930 let P0 be end point of previous segment 00931 let P1 be inbetween point of this segment (m_x2, m_y2) 00932 let P2 be end point of this segment (m_x1, m_y1) 00933 00934 Then the formula describing points on the curve are: 00935 00936 For ( 0 <= t <= 1 ) 00937 Point(t) = (1-t)^2*P0 + 2*t*(1-t)*P1 + t^2*P2 00938 00939 \ingroup vpath 00940 */ 00941 class A2DARTBASEDLLEXP a2dVpathQBCurveSegment : public a2dVpathSegment 00942 { 00943 public: 00944 00945 //! constructor 00946 /*! 00947 \param x1 endpoint of curve 00948 \param y1 endpoint of curve 00949 \param x2 first control point coming from previous segment in path 00950 \param y2 first control point coming from previous segment in path 00951 \param type draw or move towards point 00952 \param close if true close this path with the last move command/segment 00953 */ 00954 a2dVpathQBCurveSegment( double x1, double y1, double x2, double y2, a2dPATHSEG type = a2dPATHSEG_QBCURVETO, a2dPATHSEG_END close = a2dPATHSEG_END_OPEN ); 00955 00956 //! constructor 00957 /*! 00958 \param prev previous segment 00959 \param x1 endpoint of curve 00960 \param y1 endpoint of curve 00961 \param type draw or move towards point 00962 \param close if true close this path with the last move command/segment 00963 */ 00964 a2dVpathQBCurveSegment( const a2dVpathSegment& prev, double x1, double y1, a2dPATHSEG type = a2dPATHSEG_QBCURVETO, a2dPATHSEG_END close = a2dPATHSEG_END_OPEN ); 00965 00966 //! copy constructor 00967 a2dVpathQBCurveSegment( const a2dVpathQBCurveSegment &other ); 00968 00969 //! destructor 00970 ~a2dVpathQBCurveSegment(); 00971 00972 //! create exact copy 00973 virtual a2dVpathSegment* Clone(); 00974 00975 //! calculate length 00976 virtual double Length( const a2dVpathSegment& prev ); 00977 00978 //! calculate position at t, used for length 00979 void PositionAt( const a2dVpathSegment& prev, double t, double& xt, double& yt ); 00980 00981 //! control point 00982 double m_x2; 00983 //! control point 00984 double m_y2; 00985 00986 }; 00987 00988 //! Cubic Bezier curve 00989 /*! Create a curved segment based on Cubic Bezier spline 00990 let P0 be end point of previous segment 00991 let P1 be inbetween point of this segment (m_x2, m_y2) 00992 let P2 be second inbetween point of this segment (m_x3, m_y3) 00993 let P3 be end point of this segment (m_x1, m_y1) 00994 00995 Then the formula describing points on the curve are: 00996 00997 For ( 0 <= t <= 1 ) 00998 Point(t) = (1-t)^3*P0 + 3*t*(1-t)^2*P1 + 3*t^2*(1-t)*P2 + t^3*P3 00999 01000 \ingroup vpath 01001 */ 01002 class A2DARTBASEDLLEXP a2dVpathCBCurveSegment : public a2dVpathSegment 01003 { 01004 public: 01005 01006 //! constructor 01007 /*! 01008 \param x1 endpoint of curve 01009 \param y1 endpoint of curve 01010 \param x2 first control point coming from previous segment in path 01011 \param y2 first control point coming from previous segment in path 01012 \param x3 second control point coming from previous segment in path 01013 \param y3 second control point coming from previous segment in path 01014 \param type draw or move towards point 01015 \param close if true close this path with the last move command/segment 01016 */ 01017 a2dVpathCBCurveSegment( double x1, double y1, double x2, double y2, double x3, double y3, a2dPATHSEG type = a2dPATHSEG_CBCURVETO, a2dPATHSEG_END close = a2dPATHSEG_END_OPEN ); 01018 01019 //! constructor 01020 /*! 01021 \param prev previous segment 01022 \param x1 endpoint of curve 01023 \param y1 endpoint of curve 01024 \param x3 second control point coming from previous segment in path 01025 \param y3 second control point coming from previous segment in path 01026 \param type draw or move towards point 01027 \param close if true close this path with the last move command/segment 01028 01029 \remark x2 first control point is mirror of second control point of previous segment in path, if Cubic else last endpoint 01030 \remark y2 first control point is mirror of second control point of previous segment in path, if Cubic else last endpoint 01031 */ 01032 a2dVpathCBCurveSegment( const a2dVpathSegment& prev, double x1, double y1, double x3, double y3, a2dPATHSEG type = a2dPATHSEG_CBCURVETO, a2dPATHSEG_END close = a2dPATHSEG_END_OPEN ); 01033 01034 //! copy constructor 01035 a2dVpathCBCurveSegment( const a2dVpathCBCurveSegment &other ); 01036 01037 //! destructor 01038 ~a2dVpathCBCurveSegment(); 01039 01040 //! create exact copy 01041 virtual a2dVpathSegment* Clone(); 01042 01043 //! calculate length 01044 virtual double Length( const a2dVpathSegment& prev ); 01045 01046 //! calculate position at t, used for length 01047 void PositionAt( const a2dVpathSegment& prev, double t, double& xt, double& yt ); 01048 01049 //! control point 1 01050 double m_x2; 01051 //! control point 1 01052 double m_y2; 01053 01054 //! control point 2 01055 double m_x3; 01056 //! control point 2 01057 double m_y3; 01058 01059 }; 01060 01061 //! Arc Segment 01062 /*! Create an circular Arc segment. 01063 From the previous segment to this segment position, create an arc 01064 passing through a thrid point. 01065 The Third point defines the Arc segment going clockwise or anticlockwise from begin to end point. 01066 01067 \ingroup vpath 01068 */ 01069 class A2DARTBASEDLLEXP a2dVpathArcSegment : public a2dVpathSegment 01070 { 01071 public: 01072 01073 //! create arc segment 01074 /*! 01075 Begin point of arc is position/endpoint of previous segment 01076 \param x1 x of arc endpoint 01077 \param y1 y of arc endpoint 01078 \param x2 x of arc midpoint 01079 \param y2 y of arc midpoint 01080 \param type draw or move towards point 01081 \param close if true close this path with the last move command/segment 01082 */ 01083 a2dVpathArcSegment( double x1, double y1, double x2, double y2, a2dPATHSEG type = a2dPATHSEG_ARCTO, a2dPATHSEG_END close = a2dPATHSEG_END_OPEN ); 01084 01085 //! create arc segment 01086 /*! 01087 Begin point of arc is position/endpoint of previous segment 01088 01089 \param prev previous segment 01090 \param xc x of arc center 01091 \param yc y of arc center 01092 \param angle angle of arc in degrees relative from the previous segment endpoint (negatif for clockwise) 01093 \param type draw or move towards point 01094 \param close if true close this path with the last move command/segment 01095 */ 01096 a2dVpathArcSegment( const a2dVpathSegment& prev, double xc, double yc, double angle, a2dPATHSEG type = a2dPATHSEG_ARCTO, a2dPATHSEG_END close = a2dPATHSEG_END_OPEN ); 01097 01098 //! create arc segment 01099 /*! 01100 Begin point of arc is position/endpoint of previous segment 01101 \param prev previous segment 01102 \param xc x of arc center 01103 \param yc y of arc center 01104 \param x1 x of arc endpoint 01105 \param y1 y of arc endpoint 01106 \param x2 x (xc,yc) ( x2,y2) define a line which the arc will cross 01107 \param y2 y (xc,yc) ( x2,y2) define a line which the arc will cross 01108 \param type draw or move towards point 01109 \param close if true close this path with the last move command/segment 01110 01111 \remark radius is defined by prev segment endpoint and (xc,yc), x1,y1 is adjusted to fit radius. 01112 */ 01113 a2dVpathArcSegment( const a2dVpathSegment& prev, double xc, double yc, double x1, double y1, double x2, double y2, a2dPATHSEG type = a2dPATHSEG_ARCTO, a2dPATHSEG_END close = a2dPATHSEG_END_OPEN ); 01114 01115 //! constructor 01116 a2dVpathArcSegment( const a2dVpathArcSegment &other ); 01117 01118 //! destructor 01119 ~a2dVpathArcSegment(); 01120 01121 //! create exact copy 01122 virtual a2dVpathSegment* Clone(); 01123 01124 //! Calculation of center for the Arc 01125 /*! output : 01126 \param prev the previous segment, to get start point of arc. 01127 \param radius radius of the circle calculated 01128 \param center_x x of the center calculated 01129 \param center_y y of the center calculated 01130 \param beginrad calculated starting angle in radians 01131 \param midrad calculated middle angle in radians 01132 \param endrad calculated end angle in radians 01133 \param phit total calculated in radians (AntiClockwise positif, else negatif ) 01134 01135 \return true if the arc is indeed an Arc if a straight line return false. 01136 */ 01137 bool CalcR( const a2dVpathSegment& prev, double& radius, double& center_x, double& center_y, double& beginrad, double& midrad, double& endrad, double& phit ); 01138 01139 //! calculate length 01140 virtual double Length( const a2dVpathSegment& prev ); 01141 01142 //! second control point 01143 double m_x2; 01144 //! second control point 01145 double m_y2; 01146 }; 01147 01148 01149 #include <wx/dynarray.h> 01150 WX_DECLARE_OBJARRAY_WITH_DECL( a2dVpathSegment, a2dVpathArray, class A2DARTBASEDLLEXP ); 01151 01152 01153 //!Vector Path 01154 /*! 01155 Holds a wxArray of a2dVpathSegment objects. 01156 Drawing the sequence of segments, represents the form of the shape. 01157 Shape depends on the type of segment and style of that segment. 01158 01159 With Vpath very complex shapes can be generated, also disjoint. 01160 e.g. polygons with holes, donuts. 01161 01162 a2dVpathSegment is the baseclass for several types of segments. 01163 01164 \sa a2dVpathQBCurveSegment 01165 \sa a2dVpathCBCurveSegment 01166 \sa a2dVpathArcSegment 01167 01168 \remark do use Shrink() after filling a a2dVpath, to reduce memory usage 01169 01170 \ingroup vpath 01171 */ 01172 class A2DARTBASEDLLEXP a2dVpath : public a2dVpathArray 01173 { 01174 public: 01175 01176 //constructor for a vector path array 01177 a2dVpath(); 01178 01179 //constructor for a vector path array, using as input a a2dVertexArray 01180 a2dVpath( a2dVertexArray& vertexArray, bool moveToFirst = true , bool closeLast = false ); 01181 01182 //constructor for a vector path array, using as input a a2dVertexList 01183 a2dVpath( a2dVertexList& vertexList, bool moveToFirst = true , bool closeLast = false ); 01184 01185 //! destructor 01186 ~a2dVpath(); 01187 01188 //! operator = 01189 a2dVpath& operator=( const a2dVpath &other ); 01190 01191 //! calculate length of path, assuming continues path. 01192 double Length(); 01193 01194 //! test if closed polygon ( a2dPATHSEG_MOVETO, a2dPATHSEG_LINETO, a2dPATHSEG_ARCTO ) 01195 bool IsPolygon( bool allowArc = true ); 01196 01197 //! test if polyline ( a2dPATHSEG_MOVETO, a2dPATHSEG_LINETO, a2dPATHSEG_ARCTO ) 01198 bool IsPolyline( bool allowArc = true ); 01199 01200 //! add a segment 01201 void Add( a2dVpathSegment* seg ) { a2dVpathArray::Add( seg ); } 01202 01203 //! add a vertexArray to an existing path 01204 void Add( a2dVertexArray& vertexArray, bool moveToFirst = true , bool closeLast = false ); 01205 01206 //! add a vertexlist to an existing path 01207 void Add( a2dVertexList& vertexList, bool moveToFirst = true , bool closeLast = false ); 01208 01209 //! add a MoveTo command to the path 01210 /*! 01211 \param x point to move to 01212 \param y point to move to 01213 */ 01214 void MoveTo( double x, double y ); 01215 01216 //! add a LineTo command to the path 01217 /*! 01218 \param x endpoint of line 01219 \param y endpoint of line 01220 \param withStroke Do stroke or not this line segment 01221 */ 01222 void LineTo( double x, double y, bool withStroke = true ); 01223 01224 //! add a quadratic bezier segment to the path 01225 /*! 01226 \param x1 endpoint of curve 01227 \param y1 endpoint of curve 01228 \param x2 first control point coming from previous segment in path 01229 \param y2 first control point coming from previous segment in path 01230 \param withStroke Do stroke or not this line segment 01231 */ 01232 void QBCurveTo( double x1, double y1, double x2, double y2, bool withStroke = true ); 01233 01234 //! add a quadratic bezier segment to the path, using the previous segment. 01235 /*! 01236 \param x1 endpoint of curve 01237 \param y1 endpoint of curve 01238 \param withStroke Do stroke or not this line segment 01239 */ 01240 void QBCurveTo( double x1, double y1, bool withStroke = true ); 01241 01242 //! add a quadratic bezier segment to the path 01243 /*! 01244 \param x1 endpoint of curve 01245 \param y1 endpoint of curve 01246 \param x2 first control point coming from previous segment in path 01247 \param y2 first control point coming from previous segment in path 01248 \param x3 second control point coming from previous segment in path 01249 \param y3 second control point coming from previous segment in path 01250 \param withStroke Do stroke or not this line segment 01251 */ 01252 void CBCurveTo( double x1, double y1, double x2, double y2, double x3, double y3, bool withStroke = true ); 01253 01254 //! add a quadratic bezier segment to the path, using the previous segment. 01255 /*! 01256 \param x1 endpoint of curve 01257 \param y1 endpoint of curve 01258 \param x3 second control point coming from previous segment in path 01259 \param y3 second control point coming from previous segment in path 01260 \param withStroke Do stroke or not this line segment 01261 01262 \remark x2 first control point is mirror of second control point of previous segment in path, if Cubic else last endpoint 01263 \remark y2 first control point is mirror of second control point of previous segment in path, if Cubic else last endpoint 01264 */ 01265 void CBCurveTo( double x1, double y1, double x3, double y3, bool withStroke = true ); 01266 01267 //! add an arc segment to the path 01268 /*! 01269 Begin point of arc is position/endpoint of previous segment 01270 \param x1 x of arc endpoint 01271 \param y1 y of arc endpoint 01272 \param x2 x of arc midpoint 01273 \param y2 y of arc midpoint 01274 \param withStroke Do stroke or not this line segment 01275 */ 01276 void ArcTo( double x1, double y1, double x2, double y2, bool withStroke = true ); 01277 01278 //! add an arc segment to the path, using the previous segment 01279 /*! 01280 Begin point of arc is position/endpoint of previous segment 01281 01282 \param xc x of arc center 01283 \param yc y of arc center 01284 \param angle angle of arc in degrees relative from the previous segment endpoint (negatif for clockwise) 01285 \param withStroke Do stroke or not this line segment 01286 */ 01287 void ArcTo( double xc, double yc, double angle, bool withStroke = true ); 01288 01289 //! add an arc segment to the path, using the previous segment 01290 /*! 01291 Begin point of arc is position/endpoint of previous segment 01292 \param xc x of arc center 01293 \param yc y of arc center 01294 \param x1 x of arc endpoint 01295 \param y1 y of arc endpoint 01296 \param x2 x (xc,yc) ( x2,y2) define a line which the arc will cross 01297 \param y2 y (xc,yc) ( x2,y2) define a line which the arc will cross 01298 \param withStroke Do stroke or not this line segment 01299 01300 \remark radius is defined by prev segment endpoint and (xc,yc), x1,y1 is adjusted to fit radius. 01301 */ 01302 void ArcTo( double xc, double yc, double x1, double y1, double x2, double y2, bool withStroke = true ); 01303 01304 //! Closing the path as a filled area 01305 /*! 01306 The part sinve the last move is close to that move vertex. 01307 01308 \param withStroke Do stroke or not this line segment 01309 */ 01310 void Close( bool withStroke = true ); 01311 01312 //! Convert complex segments to line segments. 01313 void ConvertToLines(); 01314 01315 //! Convert to a a2dVertexList, taking and assuming it has only closed contours in path. 01316 //! Replacing non line (and arc segments if arc is true) with line segments. 01317 void ConvertToPolygon( a2dListOfa2dVertexList& addTo, bool arc = true ); 01318 01319 //! create an offset contour at distance 01320 /*! 01321 From all path parts a version is created 01322 that surrounds the original part at the given distance. 01323 */ 01324 void Contour( double distance, a2dPATH_END_TYPE pathtype ); 01325 01326 //! transform all segments with given matrix 01327 /*! 01328 \remark complex segments will be broken down to lines. 01329 */ 01330 void Transform( const a2dAffineMatrix& world ); 01331 01332 //! return a boundingbox of a transformed a2dVpath 01333 a2dBoundingBox GetBbox( const a2dAffineMatrix& lworld = a2dIDENTITY_MATRIX ); 01334 01335 01336 private: 01337 01338 //! Create a path around this path, at a distance 01339 /*! 01340 This is used to create/draw paths with a thickness. 01341 The output is a polygon shape, which can be drawn filled as a polygon. 01342 */ 01343 void SingleContour( a2dVpath& converted, unsigned int start, unsigned int segments, double distance, a2dPATH_END_TYPE pathtype ); 01344 }; 01345 01346 //! Calculate the square distance between two points 01347 inline double ClclDistSqrPntPnt( const a2dPoint2D& a, const a2dPoint2D& b ) 01348 { 01349 double dx = a.m_x - b.m_x; 01350 double dy = a.m_y - b.m_y; 01351 01352 return dx*dx + dy*dy; 01353 } 01354 01355 //! Calculate the square distance between a point and a line 01356 /*! This returns DBL_MAX if the point is beyond the edges */ 01357 extern A2DARTBASEDLLEXP double ClclDistSqrPntLine( const a2dPoint2D& p, const a2dPoint2D& p1, const a2dPoint2D& p2 ); 01358 01359 //! Calculation of center for the Arc 01360 /*! 01361 \param begin_x x start point of arc. 01362 \param begin_y y start point of arc. 01363 \param middle_x x middle point of arc. 01364 \param middle_y y middle point of arc. 01365 \param end_x x end point of arc. 01366 \param end_y y end point of arc. 01367 \param radius radius of the circle calculated 01368 \param center_p the center calculated 01369 01370 \return true if the arc is indeed an Arc if a straight line return false. 01371 */ 01372 bool CalcR( double begin_x, double begin_y, double middle_x, double middle_y, double end_x, double end_y, 01373 double& radius, a2dPoint2D& center_p ); 01374 01375 //! Calculation of center for the Arc 01376 /*! 01377 \param begin_x x start point of arc. 01378 \param begin_y y start point of arc. 01379 \param middle_x x middle point of arc. 01380 \param middle_y y middle point of arc. 01381 \param end_x x end point of arc. 01382 \param end_y y end point of arc. 01383 \param radius radius of the circle calculated 01384 \param center_x x of the center calculated 01385 \param center_y y of the center calculated 01386 \param beginrad calculated starting angle in radians 01387 \param midrad calculated middle angle in radians 01388 \param endrad calculated end angle in radians 01389 \param phit total calculated in radians (AntiClockwise positif, else negatif ) 01390 01391 \return true if the arc is indeed an Arc if a straight line return false. 01392 */ 01393 bool CalcR( double begin_x, double begin_y, double middle_x, double middle_y, double end_x, double end_y, 01394 double& radius, double& center_x, double& center_y, double& beginrad, double& midrad, double& endrad, double& phit ); 01395 01396 01397 #endif 01398