+/////////////////////////////////////////////////////////////////////////////
+// Name: polygon.cpp
+// Author: Klaas Holwerda
+// Created: XX/XX/XX
+// Copyright: 2000 (c) Klaas Holwerda
+// Licence: wxWindows Licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+ #pragma implementation "polygon.cpp"
+#endif
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#include "polygon.h"
+#include "liner.h"
+
+void ConvertSplinedPolygon(wxList* list, double Aber);
+void ConvertSplinedPolyline(wxList* list,double Aber);
+void ConvertSplinedPolygon(int& n, wxPoint2DDouble* points[], double Aber);
+static void GetLRO(const wxPoint2DDouble& P, const wxPoint2DDouble& p1, const wxPoint2DDouble& p2, int &LRO1, int &LRO2,const double marge);
+
+//----------------------------------------------------------------------------
+// wxCanvasPolyline
+//----------------------------------------------------------------------------
+
+wxCanvasPolyline::wxCanvasPolyline( int n, wxPoint2DDouble points[])
+ : wxCanvasObject()
+{
+ m_n = n;
+ m_points = points;
+ m_pen = *wxBLACK_PEN;
+
+ CalcBoundingBox();
+}
+
+wxCanvasPolyline::~wxCanvasPolyline()
+{
+ delete m_points;
+}
+
+void wxCanvasPolyline::SetPosXY( double x, double y)
+{
+ double xo=m_points[0].m_x;
+ double yo=m_points[0].m_y;
+ int i;
+ for (i=0; i < m_n;i++)
+ {
+ m_points[i].m_x += (x-xo);
+ m_points[i].m_y += (y-yo);
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolyline::TransLate( double x, double y )
+{
+ int i;
+ for (i=0; i < m_n;i++)
+ {
+ m_points[i].m_x += x;
+ m_points[i].m_y += y;
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolyline::CalcBoundingBox()
+{
+ m_bbox.SetValid(FALSE);
+
+ int i;
+ for (i=0; i < m_n;i++)
+ {
+ m_bbox.Expand( m_points[i].m_x,m_points[i].m_y);
+ }
+
+ //include the pen width also
+ m_bbox.EnLarge(m_pen.GetWidth());
+}
+
+void wxCanvasPolyline::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+ if (!m_visible) return;
+
+ int start_y = clip_y;
+ int end_y = clip_y+clip_height;
+
+ int start_x = clip_x;
+ int end_x = clip_x+clip_width;
+
+#if IMAGE_CANVAS
+#else
+ wxPoint *cpoints = new wxPoint[m_n];
+ int i;
+ for (i = 0; i < m_n; i++)
+ {
+ double x1;
+ double y1;
+ //transform to absolute
+ cworld->TransformPoint( m_points[i].m_x, m_points[i].m_y, x1, y1 );
+ //transform to device
+ cpoints[i].x = m_admin->LogicalToDeviceX(x1);
+ cpoints[i].y = m_admin->LogicalToDeviceY(y1);
+ }
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
+ int pw=m_pen.GetWidth();
+ m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
+ dc->SetPen(m_pen);
+ dc->DrawLines(m_n, cpoints, 0,0);
+ delete [] cpoints;
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+ m_pen.SetWidth(pw);
+#endif
+}
+
+void wxCanvasPolyline::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+wxCanvasObject* wxCanvasPolyline::IsHitWorld( double x, double y, double margin )
+{
+ if ((x >= m_bbox.GetMinX()-margin) &&
+ (x <= m_bbox.GetMaxX()+margin) &&
+ (y >= m_bbox.GetMinY()-margin) &&
+ (y <= m_bbox.GetMaxY()+margin)
+ )
+ {
+ wxPoint2DDouble P=wxPoint2DDouble(x,y);
+ if (PointOnPolyline(P,m_pen.GetWidth()/2+margin))
+ return this;
+ else
+ return (wxCanvasObject*) NULL;
+ }
+ return (wxCanvasObject*) NULL;
+}
+
+bool wxCanvasPolyline::PointOnPolyline(const wxPoint2DDouble& P, double margin)
+{
+ bool result = FALSE;
+ double distance;
+ wxPoint2DDouble p1,p2;
+
+ p2=m_points[0];
+ int i;
+ for (i = 0; i < m_n-1; i++)
+ {
+ p1=p2;
+ p2=m_points[i+1];
+ if (margin > sqrt(pow(p1.m_x-P.m_x,2)+pow(p1.m_y-P.m_y,2)))
+ {
+ result=TRUE;
+ break;
+ }
+ else if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
+ {
+ wxLine line1(p1,p2);
+ if (line1.PointInLine(P,distance,margin) == R_IN_AREA)
+ {
+ result=TRUE;
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+//----------------------------------------------------------------------------
+// wxCanvasPolygon
+//----------------------------------------------------------------------------
+
+wxCanvasPolygon::wxCanvasPolygon( int n, wxPoint2DDouble points[],bool splined)
+ : wxCanvasObject()
+{
+ m_n = n;
+ m_points = points;
+ m_brush = *wxBLACK_BRUSH;
+ m_pen = *wxTRANSPARENT_PEN;
+ m_textfg=*wxBLACK;
+ m_textbg=*wxWHITE;
+ m_transp=FALSE;
+ m_gpen=*wxBLACK_PEN;
+ m_gdistance=0;
+ m_gradient=FALSE;
+ m_spline = splined;
+
+ if (m_spline)
+ {
+ ConvertSplinedPolygon(m_n, &m_points, 10 );
+ }
+
+ CalcBoundingBox();
+}
+
+wxCanvasPolygon::~wxCanvasPolygon()
+{
+ delete m_points;
+}
+
+void wxCanvasPolygon::SetPosXY( double x, double y)
+{
+ double xo=m_points[0].m_x;
+ double yo=m_points[0].m_y;
+ int i;
+ for (i=0; i < m_n;i++)
+ {
+ m_points[i].m_x += (x-xo);
+ m_points[i].m_y += (y-yo);
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolygon::TransLate( double x, double y )
+{
+ int i;
+ for (i=0; i < m_n;i++)
+ {
+ m_points[i].m_x += x;
+ m_points[i].m_y += y;
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolygon::CalcBoundingBox()
+{
+
+ m_bbox.SetValid(FALSE);
+
+ int i;
+ for (i=0; i < m_n;i++)
+ {
+ m_bbox.Expand( m_points[i].m_x,m_points[i].m_y);
+ }
+
+ //include the pen width also
+ m_bbox.EnLarge(m_pen.GetWidth());
+}
+
+void wxCanvasPolygon::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+ if (!m_visible) return;
+
+ int start_y = clip_y;
+ int end_y = clip_y+clip_height;
+
+ int start_x = clip_x;
+ int end_x = clip_x+clip_width;
+
+#if IMAGE_CANVAS
+#else
+ //one extra for drawlines in some cases
+ wxPoint *cpoints = new wxPoint[m_n+1];
+ int i;
+ for (i = 0; i < m_n; i++)
+ {
+ double x1;
+ double y1;
+ cworld->TransformPoint( m_points[i].m_x, m_points[i].m_y, x1, y1 );
+ cpoints[i].x = m_admin->LogicalToDeviceX(x1);
+ cpoints[i].y = m_admin->LogicalToDeviceY(y1);
+ }
+ double x1;
+ double y1;
+ cworld->TransformPoint( m_points[0].m_x, m_points[0].m_y, x1, y1 );
+ cpoints[m_n].x = m_admin->LogicalToDeviceX(x1);
+ cpoints[m_n].y = m_admin->LogicalToDeviceY(y1);
+
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
+ dc->SetBrush(m_brush);
+ int pw=m_pen.GetWidth();
+ m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
+ if ( m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE && m_transp)
+ {
+ //draw a transparent polygon
+ //leaf the pen not transparent, which i prefer
+ dc->SetPen( wxPen( *wxWHITE,m_admin->LogicalToDeviceXRel(pw), wxSOLID) );
+ dc->SetTextForeground(*wxBLACK);
+ dc->SetTextBackground(*wxWHITE);
+ dc->SetLogicalFunction(wxAND_INVERT);
+ // BLACK OUT the opaque pixels and leave the rest as is
+ dc->DrawPolygon(m_n, cpoints, 0,0,wxWINDING_RULE);
+ // Set background and foreground colors for fill pattern
+ //the previous blacked out pixels are now merged with the layer color
+ //while the non blacked out pixels stay as they are.
+ dc->SetTextForeground(*wxBLACK);
+ //now define what will be the color of the fillpattern parts that are not transparent
+ dc->SetTextBackground(m_textfg);
+ dc->SetLogicalFunction(wxOR);
+ //don't understand how but the outline is also depending on logicalfunction
+ dc->SetPen(m_pen);
+ dc->DrawPolygon(m_n, cpoints, 0,0,wxWINDING_RULE);
+ }
+ else if (m_gradient)
+ {
+ int pw2=m_gpen.GetWidth();
+ m_gpen.SetWidth(m_admin->LogicalToDeviceYRel(pw2));
+ FillPolygon(cworld,clip_x,clip_y,clip_width,clip_height );
+ if (m_pen.GetStyle() != wxTRANSPARENT)
+ {
+ dc->SetPen(m_pen);
+ dc->DrawLines(m_n+1, cpoints, 0,0);
+ }
+ m_gpen.SetWidth(pw2);
+ }
+ else
+ {
+ dc->SetPen(m_pen);
+ dc->DrawPolygon(m_n, cpoints, 0,0,wxWINDING_RULE);
+ }
+ delete [] cpoints;
+ dc->SetBrush(wxNullBrush);
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+ m_pen.SetWidth(pw);
+#endif
+}
+
+void wxCanvasPolygon::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+wxCanvasObject* wxCanvasPolygon::IsHitWorld( double x, double y, double margin )
+{
+ if ((x >= m_bbox.GetMinX()-margin) &&
+ (x <= m_bbox.GetMaxX()+margin) &&
+ (y >= m_bbox.GetMinY()-margin) &&
+ (y <= m_bbox.GetMaxY()+margin)
+ )
+ {
+ wxPoint2DDouble P=wxPoint2DDouble(x,y);
+ INOUTPOLY io=PointInPolygon(P, m_pen.GetWidth()/2+margin);
+ if (io == OUTSIDE_POLY)
+ return (wxCanvasObject*) NULL;
+ else
+ return this;
+ }
+ return (wxCanvasObject*) NULL;
+}
+
+INOUTPOLY wxCanvasPolygon::PointInPolygon(const wxPoint2DDouble& P, double marge)
+{
+ int R_tot = 0, L_tot = 0;
+ int p1_LRO, p2_LRO;
+ double px = P.m_x, py = P.m_y;
+ double Y_intersect;
+ wxPoint2DDouble p1,p2;
+
+ //iterate across points until we are sure that the given point is in or out
+ int i;
+ for (i = 0; i < m_n; i++)
+ {
+ p1 = m_points[i];
+ if (i == m_n-1)
+ p2 = m_points[0];
+ else
+ p2 = m_points[i+1];
+
+ //more accurate
+ GetLRO(P,p1,p2,p1_LRO,p2_LRO,marge/10);
+ if (p1_LRO != p2_LRO)
+ {
+ int L = 0, R = 0;
+ if (p2_LRO == -1) { R = -p1_LRO; L = 1; }
+ if (p2_LRO == 0) if (p1_LRO == 1) R = -1; else L = -1;
+ if (p2_LRO == 1) { R = 1; L = p1_LRO; }
+
+ // calculate intersection point with line for px
+ if (p1_LRO == 0)
+ {
+ if ((p1.m_y < (py + marge)) && (p1.m_y > (py - marge)))
+ return ON_POLY;
+ else
+ Y_intersect = p1.m_y;
+ }
+ else if (p2_LRO == 0)
+ {
+ if ((p2.m_y < (py + marge)) && (p2.m_y > (py - marge)))
+ return ON_POLY;
+ else
+ Y_intersect = p2.m_y;
+ }
+ else //both p2_LRO and p1_LRO not 0
+ {
+ if ((p1.m_y > (py + marge)) && (p2.m_y > (py + marge)))
+ Y_intersect = p1.m_y; //a save value to check later
+ else if ((p1.m_y < (py- marge)) && (p2.m_y < (py - marge)))
+ Y_intersect = p1.m_y; //a save value to check later
+ else //need to calculate intersection
+ {
+ if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
+ {
+ wxLine line1(p1,p2);
+ line1.CalculateLineParameters();
+ Y_intersect = line1.Calculate_Y(px);
+ }
+ else
+ continue;
+ }
+ }
+ if (Y_intersect > (py + marge))
+ {
+ R_tot += R;
+ L_tot += L;
+ }
+ else if ((Y_intersect <= (py + marge)) && (Y_intersect >= (py - marge)))
+ {
+ return ON_POLY;
+ }
+ }
+ }
+
+ // geef het juiste resultaat terug
+ if (R_tot == 0)
+ if (L_tot == 0) return OUTSIDE_POLY;
+ else return ON_POLY;
+ else
+ if (L_tot == 0) return ON_POLY;
+ else return INSIDE_POLY;
+}
+
+//----------------------------------------------------------------------------
+// wxCanvasPolylineL
+//----------------------------------------------------------------------------
+
+wxCanvasPolylineL::wxCanvasPolylineL( wxList* points, bool spline )
+ : wxCanvasObject()
+{
+ m_lpoints = points;
+ m_pen = *wxBLACK_PEN;
+ m_spline=spline;
+ if (m_spline)
+ ConvertSplinedPolyline(m_lpoints, 10);
+ CalcBoundingBox();
+}
+
+wxCanvasPolylineL::~wxCanvasPolylineL()
+{
+ m_lpoints->DeleteContents(TRUE);
+ delete m_lpoints;
+}
+
+double wxCanvasPolylineL::GetPosX()
+{
+ wxNode *node = m_lpoints->GetFirst();
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ return point->m_x;
+}
+
+double wxCanvasPolylineL::GetPosY()
+{
+ wxNode *node = m_lpoints->GetFirst();
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ return point->m_y;
+}
+
+void wxCanvasPolylineL::SetPosXY( double x, double y )
+{
+ wxNode *node = m_lpoints->GetFirst();
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ double xo=point->m_x;
+ double yo=point->m_y;
+ while (node)
+ {
+ point = (wxPoint2DDouble*)node->Data();
+ point->m_x = point->m_x + x-xo;
+ point->m_y = point->m_y + y-yo;
+ node = node->GetNext();
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolylineL::TransLate( double x, double y )
+{
+ wxNode *node = m_lpoints->GetFirst();
+ while (node)
+ {
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ point->m_x += x;
+ point->m_y += y;
+ node = node->GetNext();
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolylineL::CalcBoundingBox()
+{
+ m_bbox.SetValid(FALSE);
+
+ wxNode *node = m_lpoints->GetFirst();
+ while (node)
+ {
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ m_bbox.Expand( point->m_x,point->m_y);
+ node = node->GetNext();
+ }
+
+ //include the pen width also
+ m_bbox.EnLarge(m_pen.GetWidth());
+}
+
+void wxCanvasPolylineL::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+ if (!m_visible) return;
+
+ int start_y = clip_y;
+ int end_y = clip_y+clip_height;
+
+ int start_x = clip_x;
+ int end_x = clip_x+clip_width;
+
+#if IMAGE_CANVAS
+#else
+ int n=m_lpoints->GetCount();
+ wxPoint *cpoints = new wxPoint[n];
+
+ wxNode *node = m_lpoints->GetFirst();
+ int i=0;
+ while (node)
+ {
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ double x1;
+ double y1;
+ //transform to absolute
+ cworld->TransformPoint( point->m_x, point->m_y, x1, y1 );
+ //transform to device
+ cpoints[i].x = m_admin->LogicalToDeviceX(x1);
+ cpoints[i].y = m_admin->LogicalToDeviceY(y1);
+
+ node = node->GetNext();
+ i++;
+ }
+
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
+ int pw=m_pen.GetWidth();
+ m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
+ dc->SetPen(m_pen);
+ dc->DrawLines(n, cpoints, 0,0);
+ delete [] cpoints;
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+ m_pen.SetWidth(pw);
+#endif
+}
+
+void wxCanvasPolylineL::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+wxCanvasObject* wxCanvasPolylineL::IsHitWorld( double x, double y, double margin )
+{
+ if ((x >= m_bbox.GetMinX()-margin) &&
+ (x <= m_bbox.GetMaxX()+margin) &&
+ (y >= m_bbox.GetMinY()-margin) &&
+ (y <= m_bbox.GetMaxY()+margin)
+ )
+ {
+ wxPoint2DDouble P=wxPoint2DDouble(x,y);
+ if (PointOnPolyline(P,m_pen.GetWidth()/2+margin))
+ return this;
+ else
+ return (wxCanvasObject*) NULL;
+ }
+ return (wxCanvasObject*) NULL;
+}
+
+bool wxCanvasPolylineL::PointOnPolyline(const wxPoint2DDouble& P, double margin)
+{
+ bool result = FALSE;
+ double distance;
+ wxPoint2DDouble p1,p2;
+
+ wxNode *node = m_lpoints->GetFirst();
+ p2 = *(wxPoint2DDouble*)node->Data();
+ while (node && !result)
+ {
+ p1=p2;
+ node=node->GetNext();
+ if (!node) break;
+ p2 = *(wxPoint2DDouble*)node->Data();
+
+ if (margin > sqrt(pow(p1.m_x-P.m_x,2)+pow(p1.m_y-P.m_y,2)))
+ result=TRUE;
+ else if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
+ {
+ wxLine line1(p1,p2);
+ if (line1.PointInLine(P,distance,margin) == R_IN_AREA)
+ result=TRUE;
+ }
+ }
+
+ return result;
+}
+
+//----------------------------------------------------------------------------
+// wxCanvasPolygon
+//----------------------------------------------------------------------------
+
+wxCanvasPolygonL::wxCanvasPolygonL( wxList* points, bool spline )
+ : wxCanvasObject()
+{
+ m_lpoints = points;
+ m_brush = *wxBLACK_BRUSH;
+ m_pen = *wxTRANSPARENT_PEN;
+ m_spline=spline;
+ m_textfg=*wxBLACK;
+ m_textbg=*wxWHITE;
+ m_transp=FALSE;
+
+ if (m_spline)
+ ConvertSplinedPolyline(m_lpoints, 10);
+ CalcBoundingBox();
+}
+
+wxCanvasPolygonL::~wxCanvasPolygonL()
+{
+ m_lpoints->DeleteContents(TRUE);
+ delete m_lpoints;
+}
+
+double wxCanvasPolygonL::GetPosX()
+{
+ wxNode *node = m_lpoints->GetFirst();
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ return point->m_x;
+}
+
+double wxCanvasPolygonL::GetPosY()
+{
+ wxNode *node = m_lpoints->GetFirst();
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ return point->m_y;
+}
+
+void wxCanvasPolygonL::SetPosXY( double x, double y )
+{
+ wxNode *node = m_lpoints->GetFirst();
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ double xo=point->m_x;
+ double yo=point->m_y;
+ while (node)
+ {
+ point = (wxPoint2DDouble*)node->Data();
+ point->m_x = point->m_x + x-xo;
+ point->m_y = point->m_y + y-yo;
+ node = node->GetNext();
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolygonL::TransLate( double x, double y )
+{
+ wxNode *node = m_lpoints->GetFirst();
+ while (node)
+ {
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ point->m_x += x;
+ point->m_y += y;
+ node = node->GetNext();
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolygonL::CalcBoundingBox()
+{
+
+ m_bbox.SetValid(FALSE);
+
+ wxNode *node = m_lpoints->GetFirst();
+ while (node)
+ {
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ m_bbox.Expand( point->m_x,point->m_y);
+ node = node->GetNext();
+ }
+
+ //include the pen width also
+ m_bbox.EnLarge(m_pen.GetWidth());
+}
+
+void wxCanvasPolygonL::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+ if (!m_visible) return;
+
+ int start_y = clip_y;
+ int end_y = clip_y+clip_height;
+
+ int start_x = clip_x;
+ int end_x = clip_x+clip_width;
+
+#if IMAGE_CANVAS
+#else
+ int n=m_lpoints->GetCount();
+ wxPoint *cpoints = new wxPoint[n];
+
+ wxNode *node = m_lpoints->GetFirst();
+ int i=0;
+ while (node)
+ {
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ double x1;
+ double y1;
+ //transform to absolute
+ cworld->TransformPoint( point->m_x, point->m_y, x1, y1 );
+ //transform to device
+ cpoints[i].x = m_admin->LogicalToDeviceX(x1);
+ cpoints[i].y = m_admin->LogicalToDeviceY(y1);
+
+ node = node->GetNext();
+ i++;
+ }
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
+ dc->SetBrush(m_brush);
+ int pw=m_pen.GetWidth();
+ m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
+ if ( m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE && m_transp)
+ {
+ //draw a transparent polygon
+ //leaf the pen not transparent, which i prefer
+ dc->SetPen( wxPen( *wxWHITE,m_admin->LogicalToDeviceXRel(pw), wxSOLID) );
+ dc->SetTextForeground(*wxBLACK);
+ dc->SetTextBackground(*wxWHITE);
+ dc->SetLogicalFunction(wxAND_INVERT);
+ // BLACK OUT the opaque pixels and leave the rest as is
+ dc->DrawPolygon(n, cpoints, 0,0,wxWINDING_RULE);
+ // Set background and foreground colors for fill pattern
+ //the previous blacked out pixels are now merged with the layer color
+ //while the non blacked out pixels stay as they are.
+ dc->SetTextForeground(*wxBLACK);
+ //now define what will be the color of the fillpattern parts that are not transparent
+ dc->SetTextBackground(m_textfg);
+ dc->SetLogicalFunction(wxOR);
+ //don't understand how but the outline is also depending on logicalfunction
+ dc->SetPen(m_pen);
+ dc->DrawPolygon(n, cpoints, 0,0,wxWINDING_RULE);
+ dc->SetLogicalFunction(wxCOPY);
+ }
+ else
+ {
+ dc->SetPen(m_pen);
+ dc->SetTextForeground(m_textfg);
+ dc->SetTextBackground(m_textbg);
+ dc->DrawPolygon(n, cpoints, 0,0,wxWINDING_RULE);
+ }
+ delete [] cpoints;
+ dc->SetBrush(wxNullBrush);
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+ m_pen.SetWidth(pw);
+#endif
+}
+
+void wxCanvasPolygonL::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+static void GetLRO(const wxPoint2DDouble& P, const wxPoint2DDouble& p1, const wxPoint2DDouble& p2, int &LRO1, int &LRO2,const double marge)
+{
+ if (p1.m_x > (P.m_x + marge)) LRO1 = -1; // beginnode is right of P
+ else
+ if (p1.m_x < (P.m_x - marge)) LRO1 = 1; // beginnode is left of P
+ else LRO1 = 0; // beginnode is on vertical line through P
+
+ if (p2.m_x > (P.m_x + marge)) LRO2 = -1; // endnode is right of P
+ else
+ if (p2.m_x < (P.m_x - marge)) LRO2 = 1; // endnode is left of P
+ else LRO2 = 0; // endnode is on vertical line through P
+}
+
+wxCanvasObject* wxCanvasPolygonL::IsHitWorld( double x, double y, double margin )
+{
+ if ((x >= m_bbox.GetMinX()-margin) &&
+ (x <= m_bbox.GetMaxX()+margin) &&
+ (y >= m_bbox.GetMinY()-margin) &&
+ (y <= m_bbox.GetMaxY()+margin)
+ )
+ {
+ wxPoint2DDouble P=wxPoint2DDouble(x,y);
+ INOUTPOLY io=PointInPolygon(P,m_pen.GetWidth()/2 + margin);
+ if (io == OUTSIDE_POLY)
+ return (wxCanvasObject*) NULL;
+ else
+ return this;
+ }
+ return (wxCanvasObject*) NULL;
+}
+
+INOUTPOLY wxCanvasPolygonL::PointInPolygon(const wxPoint2DDouble& P, double marge)
+{
+ int R_tot = 0, L_tot = 0;
+ int p1_LRO, p2_LRO;
+ double px = P.m_x, py = P.m_y;
+ double Y_intersect;
+ wxPoint2DDouble p1,p2;
+
+ //iterate across points until we are sure that the given point is in or out
+ wxNode *node = m_lpoints->GetFirst();
+
+ while (node)
+ {
+ p1 = *(wxPoint2DDouble*)node->Data();
+ if (m_lpoints->GetLast() == node)
+ {
+ p2 = *(wxPoint2DDouble*)m_lpoints->GetFirst();
+ }
+ else
+ {
+ p2 = *(wxPoint2DDouble*)node->GetNext()->Data();
+ }
+
+ //more accurate
+ GetLRO(P,p1,p2,p1_LRO,p2_LRO,marge/10);
+ if (p1_LRO != p2_LRO)
+ {
+ int L = 0, R = 0;
+ if (p2_LRO == -1) { R = -p1_LRO; L = 1; }
+ if (p2_LRO == 0) if (p1_LRO == 1) R = -1; else L = -1;
+ if (p2_LRO == 1) { R = 1; L = p1_LRO; }
+
+ // calculate intersection point with line for px
+ if (p1_LRO == 0)
+ {
+ if ((p1.m_y < (py + marge)) && (p1.m_y > (py - marge)))
+ return ON_POLY;
+ else
+ Y_intersect = p1.m_y;
+ }
+ else if (p2_LRO == 0)
+ {
+ if ((p2.m_y < (py + marge)) && (p2.m_y > (py - marge)))
+ return ON_POLY;
+ else
+ Y_intersect = p2.m_y;
+ }
+ else //both p2_LRO and p1_LRO not 0
+ {
+ if ((p1.m_y > (py + marge)) && (p2.m_y > (py + marge)))
+ Y_intersect = p1.m_y; //a save value to check later
+ else if ((p1.m_y < (py- marge)) && (p2.m_y < (py - marge)))
+ Y_intersect = p1.m_y; //a save value to check later
+ else //need to calculate intersection
+ {
+ if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
+ {
+ wxLine line1(p1,p2);
+ line1.CalculateLineParameters();
+ Y_intersect = line1.Calculate_Y(px);
+ }
+ else
+ continue;
+ }
+ }
+ if (Y_intersect > (py + marge))
+ {
+ R_tot += R;
+ L_tot += L;
+ }
+ else if ((Y_intersect <= (py + marge)) && (Y_intersect >= (py - marge)))
+ {
+ return ON_POLY;
+ }
+ }
+ node=node->Next();
+ }
+
+ // geef het juiste resultaat terug
+ if (R_tot == 0)
+ if (L_tot == 0) return OUTSIDE_POLY;
+ else return ON_POLY;
+ else
+ if (L_tot == 0) return ON_POLY;
+ else return INSIDE_POLY;
+}
+
+// ---------------------------------------------------------------------------
+// spline drawing code
+// ---------------------------------------------------------------------------
+
+static void gds_quadratic_spline(wxList *org,double a1, double b1, double a2, double b2,
+ double a3, double b3, double a4, double b4,double aber);
+static void gds_clear_stack();
+static int gds_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
+ double *y3, double *x4, double *y4);
+static void gds_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
+ double x4, double y4);
+
+void ConvertSplinedPolygon(int& n, wxPoint2DDouble* points[], double Aber)
+{
+ wxList h;
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ h.Append((wxObject*) new wxPoint2DDouble((*points)[i].m_x, (*points)[i].m_y));
+ }
+ delete *points;
+
+ ConvertSplinedPolygon(&h, Aber);
+
+ n=h.GetCount();
+ *points = new wxPoint2DDouble[n];
+ wxNode* node=h.GetFirst();
+ for (i = 0; i < n; i++)
+ {
+ wxNode* hh= node;
+ node = node->GetNext();
+ (*points)[i].m_x=((wxPoint2DDouble*) hh->GetData())->m_x;
+ (*points)[i].m_y=((wxPoint2DDouble*) hh->GetData())->m_y;
+ delete (wxPoint2DDouble*) hh->GetData();
+ h.DeleteNode(hh);
+ }
+}
+
+void ConvertSplinedPolygon(wxList* list, double Aber)
+{
+ wxPoint2DDouble* point;
+ double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
+ double x1, y1, x2, y2;
+
+ if (list->GetCount() <2)
+ return;
+
+ wxNode* iter=list->GetLast();
+ x1 = ((wxPoint2DDouble*)iter->Data())->m_x;
+ y1 = ((wxPoint2DDouble*)iter->Data())->m_y;
+
+ iter=list->GetFirst();
+ x2 = ((wxPoint2DDouble*)iter->Data())->m_x;
+ y2 = ((wxPoint2DDouble*)iter->Data())->m_y;
+
+ point = new wxPoint2DDouble(x2,y2);
+ list->Append((wxObject*)point);
+
+ cx1 = (x1 + x2) / 2.0;
+ cy1 = (y1 + y2) / 2.0;
+ cx2 = (cx1 + x2) / 2.0;
+ cy2 = (cy1 + y2) / 2.0;
+
+ delete (wxPoint2DDouble*) iter->Data();
+ delete iter;
+ iter=list->GetFirst();
+ x1 = ((wxPoint2DDouble*)iter->Data())->m_x;
+ y1 = ((wxPoint2DDouble*)iter->Data())->m_y;
+ point = new wxPoint2DDouble(x1,y1);
+ list->Append((wxObject*)point);
+
+ int i=1;
+ int count=list->GetCount();
+ while (i < count)
+ {
+ x1 = x2;
+ y1 = y2;
+ x2 = ((wxPoint2DDouble*)iter->Data())->m_x;
+ y2 = ((wxPoint2DDouble*)iter->Data())->m_y;
+ cx4 = (x1 + x2) / 2.0;
+ cy4 = (y1 + y2) / 2.0;
+ cx3 = (x1 + cx4) / 2.0;
+ cy3 = (y1 + cy4) / 2.0;
+
+ gds_quadratic_spline(list,cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4,Aber);
+
+ cx1 = cx4;
+ cy1 = cy4;
+ cx2 = (cx1 + x2) / 2.0;
+ cy2 = (cy1 + y2) / 2.0;
+ delete (wxPoint2DDouble*)iter->Data();
+ delete iter;
+ iter=list->GetFirst();
+ i++;
+ }
+
+ iter=list->GetFirst();
+ delete (wxPoint2DDouble*)iter->Data();
+ delete iter;
+}
+
+void ConvertSplinedPolyline(wxList* list,double Aber)
+{
+ double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
+ double x1, y1, x2, y2;
+
+
+ if (list->GetCount() <2)
+ return;
+
+
+
+ wxNode* iter=list->GetFirst();
+
+ x1 = ((wxPoint2DDouble*)iter->Data())->m_x;
+ y1 = ((wxPoint2DDouble*)iter->Data())->m_y;
+
+ delete (wxPoint2DDouble*)iter->Data();
+ delete iter;
+ iter=list->GetFirst();
+ x2 = ((wxPoint2DDouble*)iter->Data())->m_x;
+ y2 = ((wxPoint2DDouble*)iter->Data())->m_y;
+ cx1 = (x1 + x2) / 2.0;
+ cy1 = (y1 + y2) / 2.0;
+ cx2 = (cx1 + x2) / 2.0;
+ cy2 = (cy1 + y2) / 2.0;
+
+ wxPoint2DDouble* point = new wxPoint2DDouble(x1,y1);
+ list->Append((wxObject*)point);
+
+ delete (wxPoint2DDouble*)iter->Data();
+ delete iter;
+ iter=list->GetFirst();
+
+ int i=1;
+ int count=list->GetCount();
+ while (i < count)
+ {
+ x1 = x2;
+ y1 = y2;
+ x2 = ((wxPoint2DDouble*)iter->Data())->m_x;
+ y2 = ((wxPoint2DDouble*)iter->Data())->m_y;
+ cx4 = (x1 + x2) / 2.0;
+ cy4 = (y1 + y2) / 2.0;
+ cx3 = (x1 + cx4) / 2.0;
+ cy3 = (y1 + cy4) / 2.0;
+
+ gds_quadratic_spline(list,cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4,Aber);
+
+ cx1 = cx4;
+ cy1 = cy4;
+ cx2 = (cx1 + x2) / 2.0;
+ cy2 = (cy1 + y2) / 2.0;
+ delete (wxPoint2DDouble*)iter->Data();
+ delete iter;
+ iter=list->GetFirst();
+ i++;
+ }
+
+ point = new wxPoint2DDouble(cx1,cy1);
+ list->Append((wxObject*)point);
+
+ point = new wxPoint2DDouble(x2,y2);
+ list->Append((wxObject*)point);
+}
+
+/********************* CURVES FOR SPLINES *****************************
+
+ The following spline drawing routine is from
+
+ "An Algorithm for High-Speed Curve Generation"
+ by George Merrill Chaikin,
+ Computer Graphics and Image Processing, 3, Academic Press,
+ 1974, 346-349.
+
+ and
+
+ "On Chaikin's Algorithm" by R. F. Riesenfeld,
+ Computer Graphics and Image Processing, 4, Academic Press,
+ 1975, 304-310.
+
+***********************************************************************/
+
+#define half(z1, z2) ((z1+z2)/2.0)
+#define THRESHOLD 5
+
+/* iterative version */
+
+void gds_quadratic_spline(wxList *org,double a1, double b1, double a2, double b2, double a3, double b3, double a4,
+ double b4,double Aber)
+{
+ register double xmid, ymid;
+ double x1, y1, x2, y2, x3, y3, x4, y4;
+ wxPoint2DDouble* point;
+
+ gds_clear_stack();
+ gds_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
+
+ while (gds_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4))
+ {
+ xmid = half(x2, x3);
+ ymid = half(y2, y3);
+ if (fabs(x1 - xmid) < Aber && fabs(y1 - ymid) < Aber &&
+ fabs(xmid - x4) < Aber && fabs(ymid - y4) < Aber)
+ {
+ point = new wxPoint2DDouble(x1,y1);
+ org->Append((wxObject*)point);
+ point = new wxPoint2DDouble(xmid,ymid);
+ org->Append((wxObject*)point);
+ } else {
+ gds_spline_push(xmid, ymid, half(xmid, x3), half(ymid, y3),
+ half(x3, x4), half(y3, y4), x4, y4);
+ gds_spline_push(x1, y1, half(x1, x2), half(y1, y2),
+ half(x2, xmid), half(y2, ymid), xmid, ymid);
+ }
+ }
+}
+
+
+/* utilities used by spline drawing routines */
+
+
+typedef struct gds_spline_stack_struct {
+ double x1, y1, x2, y2, x3, y3, x4, y4;
+}
+Stack;
+
+#define SPLINE_STACK_DEPTH 20
+static Stack gds_spline_stack[SPLINE_STACK_DEPTH];
+static Stack *gds_stack_top;
+static int gds_stack_count;
+
+static void gds_clear_stack()
+{
+ gds_stack_top = gds_spline_stack;
+ gds_stack_count = 0;
+}
+
+static void gds_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
+{
+ gds_stack_top->x1 = x1;
+ gds_stack_top->y1 = y1;
+ gds_stack_top->x2 = x2;
+ gds_stack_top->y2 = y2;
+ gds_stack_top->x3 = x3;
+ gds_stack_top->y3 = y3;
+ gds_stack_top->x4 = x4;
+ gds_stack_top->y4 = y4;
+ gds_stack_top++;
+ gds_stack_count++;
+}
+
+int gds_spline_pop(double *x1, double *y1, double *x2, double *y2,
+ double *x3, double *y3, double *x4, double *y4)
+{
+ if (gds_stack_count == 0)
+ return (0);
+ gds_stack_top--;
+ gds_stack_count--;
+ *x1 = gds_stack_top->x1;
+ *y1 = gds_stack_top->y1;
+ *x2 = gds_stack_top->x2;
+ *y2 = gds_stack_top->y2;
+ *x3 = gds_stack_top->x3;
+ *y3 = gds_stack_top->y3;
+ *x4 = gds_stack_top->x4;
+ *y4 = gds_stack_top->y4;
+ return (1);
+}
+
+void wxAET::CalculateLineParameters( const wxPoint2DDouble& p1 , const wxPoint2DDouble& p2 )
+{
+ double A = p2.m_y - p1.m_y; //A (y2-y1)
+ if (A == 0)
+ {
+ m_horizontal=TRUE;
+ m_BdivA=0;
+ m_CdivA=0;
+ }
+ else
+ {
+ m_horizontal=FALSE;
+ m_BdivA= (p1.m_x - p2.m_x)/A; //B (x1-x2)
+ //normalize
+ m_CdivA= ((p2.m_x*p1.m_y) - (p1.m_x*p2.m_y)) /A ;
+ }
+}
+
+void wxAET::CalculateXs( double y )
+{
+ m_xs= -m_BdivA * y - m_CdivA;
+}
+
+//use by polygon filling
+//moves the scanline up
+//index is the index of the point where the search begins
+//direction is +1 or -1 and indicates if the segment ascends or decends
+bool wxCanvasPolygon::MoveUp( double horline, int& index, int direction)
+{
+ int walk = (index + direction + m_n) % m_n;
+ while ( m_points[walk].m_y < horline )
+ {
+ if (m_points[walk].m_y < m_points[index].m_y )
+ return FALSE;
+ else
+ {
+ //modify index
+ index=walk;
+ walk = (index + direction + m_n) % m_n;
+ }
+ }
+ return TRUE;
+}
+
+//a crictical point is a point between a decending and a ascending segment
+//collect those points for filling later
+void wxCanvasPolygon::DetectCriticalPoints()
+{
+ //candidate for critical point
+ //true if Y is getting lower, unchanged i Y is unchanged
+ //and if Y becomes higher and candidate was true: it is a critical point
+ bool candidate = FALSE;
+ int i,j;
+
+ for ( i=0; i < m_n; i++)
+ {
+ //j next point
+ j= (i+1) % m_n;
+
+ //check if Y is smaller
+ if (m_points[i].m_y > m_points[j].m_y)
+ //we have a candidate
+ candidate=TRUE;
+ else if ( (m_points[i].m_y < m_points[j].m_y) && candidate)
+ { //this is a critical point put in list
+ bool inserted=FALSE;
+ wxNode *node = m_CRlist.GetFirst();
+ while (node)
+ {
+ //sorted on smallest Y value
+ int* ind=(int*) node->GetData();
+ if (m_points[*ind].m_y > m_points[i].m_y)
+ {
+ m_CRlist.Insert(node,(wxObject*) new int(i));
+ inserted = TRUE;
+ break;
+ }
+ node = node->GetNext();
+ }
+ if (!inserted)
+ m_CRlist.Append((wxObject*) new int(i));
+ candidate = FALSE;
+ }
+ }
+ if (candidate)
+ {
+ for ( i=0; i < m_n; i++)
+ {
+ //j next point
+ j= (i+1) % m_n;
+
+ //check if Y is smaller
+ if (m_points[i].m_y > m_points[j].m_y)
+ //we have a candidate
+ candidate=TRUE;
+ else if ( (m_points[i].m_y < m_points[j].m_y) && candidate)
+ { //this is a critical point put in list
+ bool inserted=FALSE;
+ wxNode *node = m_CRlist.GetFirst();
+ while (node)
+ {
+ //sorted on smallest Y value
+ int* ind=(int*) node->GetData();
+ if (m_points[*ind].m_y > m_points[i].m_y)
+ {
+ m_CRlist.Insert(node,(wxObject*) new int(i));
+ inserted = TRUE;
+ break;
+ }
+ node = node->GetNext();
+ }
+ if (!inserted)
+ m_CRlist.Append((wxObject*) new int(i));
+ candidate = FALSE;
+ }
+ }
+ }
+}
+
+
+void wxCanvasPolygon::FillPolygon(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+#if IMAGE_CANVAS
+#else
+ int index;
+ //how much is on pixel in world coordinates
+
+ double scalefactor;
+ if (m_gdistance)
+ scalefactor=m_gdistance;
+ else
+ //abs here needed if yaxis is going up (always scan in world coordinates UP)
+ scalefactor=fabs(m_admin->DeviceToLogicalYRel(1)); //1 pixel height
+
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion( clip_x, clip_y, clip_width, clip_height );
+ wxPen gradientpen=m_gpen;
+
+ int dred = m_textbg.Red()-m_textfg.Red();
+ int dgreen = m_textbg.Green()-m_textfg.Green();
+ int dblue = m_textbg.Blue()-m_textfg.Blue();
+
+ //total number of lines to go from m_textbg to m_textfg
+ //gives the following number of steps for the gradient color
+ int stepcol = (int) (m_bbox.GetHeight()/scalefactor);
+
+ DetectCriticalPoints();
+
+ double min;
+ double max;
+ if (cworld->IsIdentity())
+ {
+ //TODO do something with clipping region (inverse transform?)
+ //the next does not work, i don't know why
+ //min = wxMin (m_admin->DeviceToLogicalY(clip_y),m_admin->DeviceToLogicalY(clip_y+clip_height));
+ //max = wxMax (m_admin->DeviceToLogicalY(clip_y),m_admin->DeviceToLogicalY(clip_y+clip_height));
+ min= m_bbox.GetMinY();
+ max= m_bbox.GetMaxY();
+ }
+ else
+ {
+ min= m_bbox.GetMinY();
+ max= m_bbox.GetMaxY();
+ }
+
+ int curcol = (int)( (min - m_bbox.GetMinY())/scalefactor );
+
+ double i;
+ for ( i = min; i < max; i+=scalefactor)
+ {
+ wxNode *node = m_AETlist.GetFirst();
+ int count= m_AETlist.GetCount();
+ while (count > 0)
+ {
+ wxAET* ele = ((wxAET*)node->GetData());
+ index= ele->m_index;
+ int direction = ele->m_direction;
+ if (!MoveUp(i,index,direction))
+ {
+ wxNode* h = node;
+ //remove this node
+ node = node->GetNext();
+ m_AETlist.DeleteNode(h);
+ }
+ else
+ {
+ if (ele->m_index != index)
+ {
+ ele->m_index=index;
+ int h = (index + direction + m_n) % m_n;
+ ele->CalculateLineParameters(m_points[h],m_points[index]);
+ }
+ if (ele->m_horizontal)
+ ele->m_xs=m_points[index].m_x;
+ else
+ ele->CalculateXs(i);
+ node = node->GetNext();
+ }
+ count--;
+ }
+
+ node = m_CRlist.GetFirst();
+ while (m_CRlist.GetCount() && m_points[*((int*)node->GetData())].m_y <=i )
+ {
+ int DI;
+ for ( DI = -1; DI <=1 ; DI+=2)
+ {
+ index=*((int*)node->GetData());
+ if (MoveUp(i,index,DI))
+ {
+ wxAET* ele = new wxAET();
+ ele->m_index=index;
+ ele->m_direction=DI;
+ int h = (index + DI + m_n) % m_n;
+ ele->CalculateLineParameters(m_points[h],m_points[index]);
+ if (ele->m_horizontal)
+ ele->m_xs=m_points[index].m_x;
+ else
+ ele->CalculateXs(i);
+
+ //insert in sorted order od m_xs
+ bool inserted=FALSE;
+ wxNode *node2 = m_AETlist.GetFirst();
+ while (node2)
+ {
+ //sorted on smallest xs value
+ if (ele->m_xs < ((wxAET*)node2->GetData())->m_xs)
+ {
+ m_AETlist.Insert(node2,(wxObject*) ele);
+ inserted = TRUE;
+ break;
+ }
+ node2 = node2->GetNext();
+ }
+ if (!inserted)
+ m_AETlist.Append((wxObject*)ele);
+ }
+ }
+
+ wxNode* h= node;
+ node = node->GetNext();
+ m_CRlist.DeleteNode(h);
+ }
+
+ curcol++;
+ wxColour gradcol(m_textbg.Red()+dred*curcol/stepcol,
+ m_textbg.Green()+dgreen*curcol/stepcol,
+ m_textbg.Blue()+dblue*curcol/stepcol);
+ gradientpen.SetColour(gradcol);
+
+ //m_AETlist must be sorted in m_xs at this moment
+ //now draw all the line parts on one horizontal scanline (Winding Rule)
+ int out= 0;
+ node = m_AETlist.GetFirst();
+ while (node)
+ {
+ wxAET* ele = ((wxAET*)node->GetData());
+ out+=ele->m_direction;
+ if (out != 0)
+ {
+ double x1=ele->m_xs;
+ node = node->GetNext();
+ ele = ((wxAET*)node->GetData());
+ double x2=ele->m_xs;
+ dc->SetPen( gradientpen );
+ double wx1,wy1,wx2,wy2;
+ cworld->TransformPoint( x1, i, wx1, wy1 );
+ cworld->TransformPoint( x2, i, wx2, wy2 );
+ int dx1,dy1,dx2,dy2;
+ dx1 = m_admin->LogicalToDeviceX( wx1 );
+ dy1 = m_admin->LogicalToDeviceY( wy1 );
+ dx2 = m_admin->LogicalToDeviceX( wx2 );
+ dy2 = m_admin->LogicalToDeviceY( wy2 );
+
+ //TODO KKK need real line clipping here since line can be rotated.
+ if (0 && cworld->IsIdentity())
+ {
+ if (dx1 < clip_x) dx1=clip_x;
+ if (dx2 > clip_x + clip_width) dx2=clip_x + clip_width;
+ if ((dy1 > clip_y) && dy1 < clip_y + clip_height)
+ dc->DrawLine( dx1, dy1, dx2, dy2 );
+ }
+ else
+ {
+ dc->DrawLine( dx1, dy1, dx2, dy2 );
+ }
+
+ }
+ else
+ node = node->GetNext();
+ }
+ }
+
+ dc->DestroyClippingRegion();
+#endif
+}
+
+
+
+
+