X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ce109c530a49bd6d7b2ace416001d37846b76ee5..6ceef8efe9e38313dba9f7c8a64efcb344a0056e:/contrib/src/canvas/polygon.cpp diff --git a/contrib/src/canvas/polygon.cpp b/contrib/src/canvas/polygon.cpp deleted file mode 100644 index d7b159f683..0000000000 --- a/contrib/src/canvas/polygon.cpp +++ /dev/null @@ -1,1453 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// 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 "wx/canvas/polygon.h" -#include "wx/canvas/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 -} - - - - -