]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/canvas/polygon.cpp
Speed-up for wxCanvasImage.
[wxWidgets.git] / contrib / src / canvas / polygon.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: polygon.cpp
3 // Author: Klaas Holwerda
4 // Created: XX/XX/XX
5 // Copyright: 2000 (c) Klaas Holwerda
6 // Licence: wxWindows Licence
7 /////////////////////////////////////////////////////////////////////////////
8
9 #ifdef __GNUG__
10 #pragma implementation "polygon.cpp"
11 #endif
12
13 // For compilers that support precompilation, includes "wx/wx.h".
14 #include "wx/wxprec.h"
15
16 #ifdef __BORLANDC__
17 #pragma hdrstop
18 #endif
19
20 #include "wx/canvas/polygon.h"
21 #include "wx/canvas/liner.h"
22
23 void ConvertSplinedPolygon(wxList* list, double Aber);
24 void ConvertSplinedPolyline(wxList* list,double Aber);
25 void ConvertSplinedPolygon(int& n, wxPoint2DDouble* points[], double Aber);
26 static void GetLRO(const wxPoint2DDouble& P, const wxPoint2DDouble& p1, const wxPoint2DDouble& p2, int &LRO1, int &LRO2,const double marge);
27
28 //----------------------------------------------------------------------------
29 // wxCanvasPolyline
30 //----------------------------------------------------------------------------
31
32 wxCanvasPolyline::wxCanvasPolyline( int n, wxPoint2DDouble points[])
33 : wxCanvasObject()
34 {
35 m_n = n;
36 m_points = points;
37 m_pen = *wxBLACK_PEN;
38
39 CalcBoundingBox();
40 }
41
42 wxCanvasPolyline::~wxCanvasPolyline()
43 {
44 delete m_points;
45 }
46
47 void wxCanvasPolyline::SetPosXY( double x, double y)
48 {
49 double xo=m_points[0].m_x;
50 double yo=m_points[0].m_y;
51 int i;
52 for (i=0; i < m_n;i++)
53 {
54 m_points[i].m_x += (x-xo);
55 m_points[i].m_y += (y-yo);
56 }
57 CalcBoundingBox();
58 }
59
60 void wxCanvasPolyline::TransLate( double x, double y )
61 {
62 int i;
63 for (i=0; i < m_n;i++)
64 {
65 m_points[i].m_x += x;
66 m_points[i].m_y += y;
67 }
68 CalcBoundingBox();
69 }
70
71 void wxCanvasPolyline::CalcBoundingBox()
72 {
73 m_bbox.SetValid(FALSE);
74
75 int i;
76 for (i=0; i < m_n;i++)
77 {
78 m_bbox.Expand( m_points[i].m_x,m_points[i].m_y);
79 }
80
81 //include the pen width also
82 m_bbox.EnLarge(m_pen.GetWidth());
83 }
84
85 void wxCanvasPolyline::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
86 {
87 if (!m_visible) return;
88
89 int start_y = clip_y;
90 int end_y = clip_y+clip_height;
91
92 int start_x = clip_x;
93 int end_x = clip_x+clip_width;
94
95 #if IMAGE_CANVAS
96 #else
97 wxPoint *cpoints = new wxPoint[m_n];
98 int i;
99 for (i = 0; i < m_n; i++)
100 {
101 double x1;
102 double y1;
103 //transform to absolute
104 cworld->TransformPoint( m_points[i].m_x, m_points[i].m_y, x1, y1 );
105 //transform to device
106 cpoints[i].x = m_admin->LogicalToDeviceX(x1);
107 cpoints[i].y = m_admin->LogicalToDeviceY(y1);
108 }
109 wxDC *dc = m_admin->GetActive()->GetDC();
110 dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
111 int pw=m_pen.GetWidth();
112 m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
113 dc->SetPen(m_pen);
114 dc->DrawLines(m_n, cpoints, 0,0);
115 delete [] cpoints;
116 dc->SetPen(wxNullPen);
117 dc->DestroyClippingRegion();
118 m_pen.SetWidth(pw);
119 #endif
120 }
121
122 void wxCanvasPolyline::WriteSVG( wxTextOutputStream &stream )
123 {
124 }
125
126 wxCanvasObject* wxCanvasPolyline::IsHitWorld( double x, double y, double margin )
127 {
128 if ((x >= m_bbox.GetMinX()-margin) &&
129 (x <= m_bbox.GetMaxX()+margin) &&
130 (y >= m_bbox.GetMinY()-margin) &&
131 (y <= m_bbox.GetMaxY()+margin)
132 )
133 {
134 wxPoint2DDouble P=wxPoint2DDouble(x,y);
135 if (PointOnPolyline(P,m_pen.GetWidth()/2+margin))
136 return this;
137 else
138 return (wxCanvasObject*) NULL;
139 }
140 return (wxCanvasObject*) NULL;
141 }
142
143 bool wxCanvasPolyline::PointOnPolyline(const wxPoint2DDouble& P, double margin)
144 {
145 bool result = FALSE;
146 double distance;
147 wxPoint2DDouble p1,p2;
148
149 p2=m_points[0];
150 int i;
151 for (i = 0; i < m_n-1; i++)
152 {
153 p1=p2;
154 p2=m_points[i+1];
155 if (margin > sqrt(pow(p1.m_x-P.m_x,2)+pow(p1.m_y-P.m_y,2)))
156 {
157 result=TRUE;
158 break;
159 }
160 else if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
161 {
162 wxLine line1(p1,p2);
163 if (line1.PointInLine(P,distance,margin) == R_IN_AREA)
164 {
165 result=TRUE;
166 break;
167 }
168 }
169 }
170
171 return result;
172 }
173
174 //----------------------------------------------------------------------------
175 // wxCanvasPolygon
176 //----------------------------------------------------------------------------
177
178 wxCanvasPolygon::wxCanvasPolygon( int n, wxPoint2DDouble points[],bool splined)
179 : wxCanvasObject()
180 {
181 m_n = n;
182 m_points = points;
183 m_brush = *wxBLACK_BRUSH;
184 m_pen = *wxTRANSPARENT_PEN;
185 m_textfg=*wxBLACK;
186 m_textbg=*wxWHITE;
187 m_transp=FALSE;
188 m_gpen=*wxBLACK_PEN;
189 m_gdistance=0;
190 m_gradient=FALSE;
191 m_spline = splined;
192
193 if (m_spline)
194 {
195 ConvertSplinedPolygon(m_n, &m_points, 10 );
196 }
197
198 CalcBoundingBox();
199 }
200
201 wxCanvasPolygon::~wxCanvasPolygon()
202 {
203 delete m_points;
204 }
205
206 void wxCanvasPolygon::SetPosXY( double x, double y)
207 {
208 double xo=m_points[0].m_x;
209 double yo=m_points[0].m_y;
210 int i;
211 for (i=0; i < m_n;i++)
212 {
213 m_points[i].m_x += (x-xo);
214 m_points[i].m_y += (y-yo);
215 }
216 CalcBoundingBox();
217 }
218
219 void wxCanvasPolygon::TransLate( double x, double y )
220 {
221 int i;
222 for (i=0; i < m_n;i++)
223 {
224 m_points[i].m_x += x;
225 m_points[i].m_y += y;
226 }
227 CalcBoundingBox();
228 }
229
230 void wxCanvasPolygon::CalcBoundingBox()
231 {
232
233 m_bbox.SetValid(FALSE);
234
235 int i;
236 for (i=0; i < m_n;i++)
237 {
238 m_bbox.Expand( m_points[i].m_x,m_points[i].m_y);
239 }
240
241 //include the pen width also
242 m_bbox.EnLarge(m_pen.GetWidth());
243 }
244
245 void wxCanvasPolygon::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
246 {
247 if (!m_visible) return;
248
249 int start_y = clip_y;
250 int end_y = clip_y+clip_height;
251
252 int start_x = clip_x;
253 int end_x = clip_x+clip_width;
254
255 #if IMAGE_CANVAS
256 #else
257 //one extra for drawlines in some cases
258 wxPoint *cpoints = new wxPoint[m_n+1];
259 int i;
260 for (i = 0; i < m_n; i++)
261 {
262 double x1;
263 double y1;
264 cworld->TransformPoint( m_points[i].m_x, m_points[i].m_y, x1, y1 );
265 cpoints[i].x = m_admin->LogicalToDeviceX(x1);
266 cpoints[i].y = m_admin->LogicalToDeviceY(y1);
267 }
268 double x1;
269 double y1;
270 cworld->TransformPoint( m_points[0].m_x, m_points[0].m_y, x1, y1 );
271 cpoints[m_n].x = m_admin->LogicalToDeviceX(x1);
272 cpoints[m_n].y = m_admin->LogicalToDeviceY(y1);
273
274 wxDC *dc = m_admin->GetActive()->GetDC();
275 dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
276 dc->SetBrush(m_brush);
277 int pw=m_pen.GetWidth();
278 m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
279 if ( m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE && m_transp)
280 {
281 //draw a transparent polygon
282 //leaf the pen not transparent, which i prefer
283 dc->SetPen( wxPen( *wxWHITE,m_admin->LogicalToDeviceXRel(pw), wxSOLID) );
284 dc->SetTextForeground(*wxBLACK);
285 dc->SetTextBackground(*wxWHITE);
286 dc->SetLogicalFunction(wxAND_INVERT);
287 // BLACK OUT the opaque pixels and leave the rest as is
288 dc->DrawPolygon(m_n, cpoints, 0,0,wxWINDING_RULE);
289 // Set background and foreground colors for fill pattern
290 //the previous blacked out pixels are now merged with the layer color
291 //while the non blacked out pixels stay as they are.
292 dc->SetTextForeground(*wxBLACK);
293 //now define what will be the color of the fillpattern parts that are not transparent
294 dc->SetTextBackground(m_textfg);
295 dc->SetLogicalFunction(wxOR);
296 //don't understand how but the outline is also depending on logicalfunction
297 dc->SetPen(m_pen);
298 dc->DrawPolygon(m_n, cpoints, 0,0,wxWINDING_RULE);
299 }
300 else if (m_gradient)
301 {
302 int pw2=m_gpen.GetWidth();
303 m_gpen.SetWidth(m_admin->LogicalToDeviceYRel(pw2));
304 FillPolygon(cworld,clip_x,clip_y,clip_width,clip_height );
305 if (m_pen.GetStyle() != wxTRANSPARENT)
306 {
307 dc->SetPen(m_pen);
308 dc->DrawLines(m_n+1, cpoints, 0,0);
309 }
310 m_gpen.SetWidth(pw2);
311 }
312 else
313 {
314 dc->SetPen(m_pen);
315 dc->DrawPolygon(m_n, cpoints, 0,0,wxWINDING_RULE);
316 }
317 delete [] cpoints;
318 dc->SetBrush(wxNullBrush);
319 dc->SetPen(wxNullPen);
320 dc->DestroyClippingRegion();
321 m_pen.SetWidth(pw);
322 #endif
323 }
324
325 void wxCanvasPolygon::WriteSVG( wxTextOutputStream &stream )
326 {
327 }
328
329 wxCanvasObject* wxCanvasPolygon::IsHitWorld( double x, double y, double margin )
330 {
331 if ((x >= m_bbox.GetMinX()-margin) &&
332 (x <= m_bbox.GetMaxX()+margin) &&
333 (y >= m_bbox.GetMinY()-margin) &&
334 (y <= m_bbox.GetMaxY()+margin)
335 )
336 {
337 wxPoint2DDouble P=wxPoint2DDouble(x,y);
338 INOUTPOLY io=PointInPolygon(P, m_pen.GetWidth()/2+margin);
339 if (io == OUTSIDE_POLY)
340 return (wxCanvasObject*) NULL;
341 else
342 return this;
343 }
344 return (wxCanvasObject*) NULL;
345 }
346
347 INOUTPOLY wxCanvasPolygon::PointInPolygon(const wxPoint2DDouble& P, double marge)
348 {
349 int R_tot = 0, L_tot = 0;
350 int p1_LRO, p2_LRO;
351 double px = P.m_x, py = P.m_y;
352 double Y_intersect;
353 wxPoint2DDouble p1,p2;
354
355 //iterate across points until we are sure that the given point is in or out
356 int i;
357 for (i = 0; i < m_n; i++)
358 {
359 p1 = m_points[i];
360 if (i == m_n-1)
361 p2 = m_points[0];
362 else
363 p2 = m_points[i+1];
364
365 //more accurate
366 GetLRO(P,p1,p2,p1_LRO,p2_LRO,marge/10);
367 if (p1_LRO != p2_LRO)
368 {
369 int L = 0, R = 0;
370 if (p2_LRO == -1) { R = -p1_LRO; L = 1; }
371 if (p2_LRO == 0) if (p1_LRO == 1) R = -1; else L = -1;
372 if (p2_LRO == 1) { R = 1; L = p1_LRO; }
373
374 // calculate intersection point with line for px
375 if (p1_LRO == 0)
376 {
377 if ((p1.m_y < (py + marge)) && (p1.m_y > (py - marge)))
378 return ON_POLY;
379 else
380 Y_intersect = p1.m_y;
381 }
382 else if (p2_LRO == 0)
383 {
384 if ((p2.m_y < (py + marge)) && (p2.m_y > (py - marge)))
385 return ON_POLY;
386 else
387 Y_intersect = p2.m_y;
388 }
389 else //both p2_LRO and p1_LRO not 0
390 {
391 if ((p1.m_y > (py + marge)) && (p2.m_y > (py + marge)))
392 Y_intersect = p1.m_y; //a save value to check later
393 else if ((p1.m_y < (py- marge)) && (p2.m_y < (py - marge)))
394 Y_intersect = p1.m_y; //a save value to check later
395 else //need to calculate intersection
396 {
397 if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
398 {
399 wxLine line1(p1,p2);
400 line1.CalculateLineParameters();
401 Y_intersect = line1.Calculate_Y(px);
402 }
403 else
404 continue;
405 }
406 }
407 if (Y_intersect > (py + marge))
408 {
409 R_tot += R;
410 L_tot += L;
411 }
412 else if ((Y_intersect <= (py + marge)) && (Y_intersect >= (py - marge)))
413 {
414 return ON_POLY;
415 }
416 }
417 }
418
419 // geef het juiste resultaat terug
420 if (R_tot == 0)
421 if (L_tot == 0) return OUTSIDE_POLY;
422 else return ON_POLY;
423 else
424 if (L_tot == 0) return ON_POLY;
425 else return INSIDE_POLY;
426 }
427
428 //----------------------------------------------------------------------------
429 // wxCanvasPolylineL
430 //----------------------------------------------------------------------------
431
432 wxCanvasPolylineL::wxCanvasPolylineL( wxList* points, bool spline )
433 : wxCanvasObject()
434 {
435 m_lpoints = points;
436 m_pen = *wxBLACK_PEN;
437 m_spline=spline;
438 if (m_spline)
439 ConvertSplinedPolyline(m_lpoints, 10);
440 CalcBoundingBox();
441 }
442
443 wxCanvasPolylineL::~wxCanvasPolylineL()
444 {
445 m_lpoints->DeleteContents(TRUE);
446 delete m_lpoints;
447 }
448
449 double wxCanvasPolylineL::GetPosX()
450 {
451 wxNode *node = m_lpoints->GetFirst();
452 wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
453 return point->m_x;
454 }
455
456 double wxCanvasPolylineL::GetPosY()
457 {
458 wxNode *node = m_lpoints->GetFirst();
459 wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
460 return point->m_y;
461 }
462
463 void wxCanvasPolylineL::SetPosXY( double x, double y )
464 {
465 wxNode *node = m_lpoints->GetFirst();
466 wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
467 double xo=point->m_x;
468 double yo=point->m_y;
469 while (node)
470 {
471 point = (wxPoint2DDouble*)node->Data();
472 point->m_x = point->m_x + x-xo;
473 point->m_y = point->m_y + y-yo;
474 node = node->GetNext();
475 }
476 CalcBoundingBox();
477 }
478
479 void wxCanvasPolylineL::TransLate( double x, double y )
480 {
481 wxNode *node = m_lpoints->GetFirst();
482 while (node)
483 {
484 wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
485 point->m_x += x;
486 point->m_y += y;
487 node = node->GetNext();
488 }
489 CalcBoundingBox();
490 }
491
492 void wxCanvasPolylineL::CalcBoundingBox()
493 {
494 m_bbox.SetValid(FALSE);
495
496 wxNode *node = m_lpoints->GetFirst();
497 while (node)
498 {
499 wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
500 m_bbox.Expand( point->m_x,point->m_y);
501 node = node->GetNext();
502 }
503
504 //include the pen width also
505 m_bbox.EnLarge(m_pen.GetWidth());
506 }
507
508 void wxCanvasPolylineL::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
509 {
510 if (!m_visible) return;
511
512 int start_y = clip_y;
513 int end_y = clip_y+clip_height;
514
515 int start_x = clip_x;
516 int end_x = clip_x+clip_width;
517
518 #if IMAGE_CANVAS
519 #else
520 int n=m_lpoints->GetCount();
521 wxPoint *cpoints = new wxPoint[n];
522
523 wxNode *node = m_lpoints->GetFirst();
524 int i=0;
525 while (node)
526 {
527 wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
528 double x1;
529 double y1;
530 //transform to absolute
531 cworld->TransformPoint( point->m_x, point->m_y, x1, y1 );
532 //transform to device
533 cpoints[i].x = m_admin->LogicalToDeviceX(x1);
534 cpoints[i].y = m_admin->LogicalToDeviceY(y1);
535
536 node = node->GetNext();
537 i++;
538 }
539
540 wxDC *dc = m_admin->GetActive()->GetDC();
541 dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
542 int pw=m_pen.GetWidth();
543 m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
544 dc->SetPen(m_pen);
545 dc->DrawLines(n, cpoints, 0,0);
546 delete [] cpoints;
547 dc->SetPen(wxNullPen);
548 dc->DestroyClippingRegion();
549 m_pen.SetWidth(pw);
550 #endif
551 }
552
553 void wxCanvasPolylineL::WriteSVG( wxTextOutputStream &stream )
554 {
555 }
556
557 wxCanvasObject* wxCanvasPolylineL::IsHitWorld( double x, double y, double margin )
558 {
559 if ((x >= m_bbox.GetMinX()-margin) &&
560 (x <= m_bbox.GetMaxX()+margin) &&
561 (y >= m_bbox.GetMinY()-margin) &&
562 (y <= m_bbox.GetMaxY()+margin)
563 )
564 {
565 wxPoint2DDouble P=wxPoint2DDouble(x,y);
566 if (PointOnPolyline(P,m_pen.GetWidth()/2+margin))
567 return this;
568 else
569 return (wxCanvasObject*) NULL;
570 }
571 return (wxCanvasObject*) NULL;
572 }
573
574 bool wxCanvasPolylineL::PointOnPolyline(const wxPoint2DDouble& P, double margin)
575 {
576 bool result = FALSE;
577 double distance;
578 wxPoint2DDouble p1,p2;
579
580 wxNode *node = m_lpoints->GetFirst();
581 p2 = *(wxPoint2DDouble*)node->Data();
582 while (node && !result)
583 {
584 p1=p2;
585 node=node->GetNext();
586 if (!node) break;
587 p2 = *(wxPoint2DDouble*)node->Data();
588
589 if (margin > sqrt(pow(p1.m_x-P.m_x,2)+pow(p1.m_y-P.m_y,2)))
590 result=TRUE;
591 else if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
592 {
593 wxLine line1(p1,p2);
594 if (line1.PointInLine(P,distance,margin) == R_IN_AREA)
595 result=TRUE;
596 }
597 }
598
599 return result;
600 }
601
602 //----------------------------------------------------------------------------
603 // wxCanvasPolygon
604 //----------------------------------------------------------------------------
605
606 wxCanvasPolygonL::wxCanvasPolygonL( wxList* points, bool spline )
607 : wxCanvasObject()
608 {
609 m_lpoints = points;
610 m_brush = *wxBLACK_BRUSH;
611 m_pen = *wxTRANSPARENT_PEN;
612 m_spline=spline;
613 m_textfg=*wxBLACK;
614 m_textbg=*wxWHITE;
615 m_transp=FALSE;
616
617 if (m_spline)
618 ConvertSplinedPolyline(m_lpoints, 10);
619 CalcBoundingBox();
620 }
621
622 wxCanvasPolygonL::~wxCanvasPolygonL()
623 {
624 m_lpoints->DeleteContents(TRUE);
625 delete m_lpoints;
626 }
627
628 double wxCanvasPolygonL::GetPosX()
629 {
630 wxNode *node = m_lpoints->GetFirst();
631 wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
632 return point->m_x;
633 }
634
635 double wxCanvasPolygonL::GetPosY()
636 {
637 wxNode *node = m_lpoints->GetFirst();
638 wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
639 return point->m_y;
640 }
641
642 void wxCanvasPolygonL::SetPosXY( double x, double y )
643 {
644 wxNode *node = m_lpoints->GetFirst();
645 wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
646 double xo=point->m_x;
647 double yo=point->m_y;
648 while (node)
649 {
650 point = (wxPoint2DDouble*)node->Data();
651 point->m_x = point->m_x + x-xo;
652 point->m_y = point->m_y + y-yo;
653 node = node->GetNext();
654 }
655 CalcBoundingBox();
656 }
657
658 void wxCanvasPolygonL::TransLate( double x, double y )
659 {
660 wxNode *node = m_lpoints->GetFirst();
661 while (node)
662 {
663 wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
664 point->m_x += x;
665 point->m_y += y;
666 node = node->GetNext();
667 }
668 CalcBoundingBox();
669 }
670
671 void wxCanvasPolygonL::CalcBoundingBox()
672 {
673
674 m_bbox.SetValid(FALSE);
675
676 wxNode *node = m_lpoints->GetFirst();
677 while (node)
678 {
679 wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
680 m_bbox.Expand( point->m_x,point->m_y);
681 node = node->GetNext();
682 }
683
684 //include the pen width also
685 m_bbox.EnLarge(m_pen.GetWidth());
686 }
687
688 void wxCanvasPolygonL::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
689 {
690 if (!m_visible) return;
691
692 int start_y = clip_y;
693 int end_y = clip_y+clip_height;
694
695 int start_x = clip_x;
696 int end_x = clip_x+clip_width;
697
698 #if IMAGE_CANVAS
699 #else
700 int n=m_lpoints->GetCount();
701 wxPoint *cpoints = new wxPoint[n];
702
703 wxNode *node = m_lpoints->GetFirst();
704 int i=0;
705 while (node)
706 {
707 wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
708 double x1;
709 double y1;
710 //transform to absolute
711 cworld->TransformPoint( point->m_x, point->m_y, x1, y1 );
712 //transform to device
713 cpoints[i].x = m_admin->LogicalToDeviceX(x1);
714 cpoints[i].y = m_admin->LogicalToDeviceY(y1);
715
716 node = node->GetNext();
717 i++;
718 }
719 wxDC *dc = m_admin->GetActive()->GetDC();
720 dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
721 dc->SetBrush(m_brush);
722 int pw=m_pen.GetWidth();
723 m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
724 if ( m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE && m_transp)
725 {
726 //draw a transparent polygon
727 //leaf the pen not transparent, which i prefer
728 dc->SetPen( wxPen( *wxWHITE,m_admin->LogicalToDeviceXRel(pw), wxSOLID) );
729 dc->SetTextForeground(*wxBLACK);
730 dc->SetTextBackground(*wxWHITE);
731 dc->SetLogicalFunction(wxAND_INVERT);
732 // BLACK OUT the opaque pixels and leave the rest as is
733 dc->DrawPolygon(n, cpoints, 0,0,wxWINDING_RULE);
734 // Set background and foreground colors for fill pattern
735 //the previous blacked out pixels are now merged with the layer color
736 //while the non blacked out pixels stay as they are.
737 dc->SetTextForeground(*wxBLACK);
738 //now define what will be the color of the fillpattern parts that are not transparent
739 dc->SetTextBackground(m_textfg);
740 dc->SetLogicalFunction(wxOR);
741 //don't understand how but the outline is also depending on logicalfunction
742 dc->SetPen(m_pen);
743 dc->DrawPolygon(n, cpoints, 0,0,wxWINDING_RULE);
744 dc->SetLogicalFunction(wxCOPY);
745 }
746 else
747 {
748 dc->SetPen(m_pen);
749 dc->SetTextForeground(m_textfg);
750 dc->SetTextBackground(m_textbg);
751 dc->DrawPolygon(n, cpoints, 0,0,wxWINDING_RULE);
752 }
753 delete [] cpoints;
754 dc->SetBrush(wxNullBrush);
755 dc->SetPen(wxNullPen);
756 dc->DestroyClippingRegion();
757 m_pen.SetWidth(pw);
758 #endif
759 }
760
761 void wxCanvasPolygonL::WriteSVG( wxTextOutputStream &stream )
762 {
763 }
764
765 static void GetLRO(const wxPoint2DDouble& P, const wxPoint2DDouble& p1, const wxPoint2DDouble& p2, int &LRO1, int &LRO2,const double marge)
766 {
767 if (p1.m_x > (P.m_x + marge)) LRO1 = -1; // beginnode is right of P
768 else
769 if (p1.m_x < (P.m_x - marge)) LRO1 = 1; // beginnode is left of P
770 else LRO1 = 0; // beginnode is on vertical line through P
771
772 if (p2.m_x > (P.m_x + marge)) LRO2 = -1; // endnode is right of P
773 else
774 if (p2.m_x < (P.m_x - marge)) LRO2 = 1; // endnode is left of P
775 else LRO2 = 0; // endnode is on vertical line through P
776 }
777
778 wxCanvasObject* wxCanvasPolygonL::IsHitWorld( double x, double y, double margin )
779 {
780 if ((x >= m_bbox.GetMinX()-margin) &&
781 (x <= m_bbox.GetMaxX()+margin) &&
782 (y >= m_bbox.GetMinY()-margin) &&
783 (y <= m_bbox.GetMaxY()+margin)
784 )
785 {
786 wxPoint2DDouble P=wxPoint2DDouble(x,y);
787 INOUTPOLY io=PointInPolygon(P,m_pen.GetWidth()/2 + margin);
788 if (io == OUTSIDE_POLY)
789 return (wxCanvasObject*) NULL;
790 else
791 return this;
792 }
793 return (wxCanvasObject*) NULL;
794 }
795
796 INOUTPOLY wxCanvasPolygonL::PointInPolygon(const wxPoint2DDouble& P, double marge)
797 {
798 int R_tot = 0, L_tot = 0;
799 int p1_LRO, p2_LRO;
800 double px = P.m_x, py = P.m_y;
801 double Y_intersect;
802 wxPoint2DDouble p1,p2;
803
804 //iterate across points until we are sure that the given point is in or out
805 wxNode *node = m_lpoints->GetFirst();
806
807 while (node)
808 {
809 p1 = *(wxPoint2DDouble*)node->Data();
810 if (m_lpoints->GetLast() == node)
811 {
812 p2 = *(wxPoint2DDouble*)m_lpoints->GetFirst();
813 }
814 else
815 {
816 p2 = *(wxPoint2DDouble*)node->GetNext()->Data();
817 }
818
819 //more accurate
820 GetLRO(P,p1,p2,p1_LRO,p2_LRO,marge/10);
821 if (p1_LRO != p2_LRO)
822 {
823 int L = 0, R = 0;
824 if (p2_LRO == -1) { R = -p1_LRO; L = 1; }
825 if (p2_LRO == 0) if (p1_LRO == 1) R = -1; else L = -1;
826 if (p2_LRO == 1) { R = 1; L = p1_LRO; }
827
828 // calculate intersection point with line for px
829 if (p1_LRO == 0)
830 {
831 if ((p1.m_y < (py + marge)) && (p1.m_y > (py - marge)))
832 return ON_POLY;
833 else
834 Y_intersect = p1.m_y;
835 }
836 else if (p2_LRO == 0)
837 {
838 if ((p2.m_y < (py + marge)) && (p2.m_y > (py - marge)))
839 return ON_POLY;
840 else
841 Y_intersect = p2.m_y;
842 }
843 else //both p2_LRO and p1_LRO not 0
844 {
845 if ((p1.m_y > (py + marge)) && (p2.m_y > (py + marge)))
846 Y_intersect = p1.m_y; //a save value to check later
847 else if ((p1.m_y < (py- marge)) && (p2.m_y < (py - marge)))
848 Y_intersect = p1.m_y; //a save value to check later
849 else //need to calculate intersection
850 {
851 if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
852 {
853 wxLine line1(p1,p2);
854 line1.CalculateLineParameters();
855 Y_intersect = line1.Calculate_Y(px);
856 }
857 else
858 continue;
859 }
860 }
861 if (Y_intersect > (py + marge))
862 {
863 R_tot += R;
864 L_tot += L;
865 }
866 else if ((Y_intersect <= (py + marge)) && (Y_intersect >= (py - marge)))
867 {
868 return ON_POLY;
869 }
870 }
871 node=node->Next();
872 }
873
874 // geef het juiste resultaat terug
875 if (R_tot == 0)
876 if (L_tot == 0) return OUTSIDE_POLY;
877 else return ON_POLY;
878 else
879 if (L_tot == 0) return ON_POLY;
880 else return INSIDE_POLY;
881 }
882
883 // ---------------------------------------------------------------------------
884 // spline drawing code
885 // ---------------------------------------------------------------------------
886
887 static void gds_quadratic_spline(wxList *org,double a1, double b1, double a2, double b2,
888 double a3, double b3, double a4, double b4,double aber);
889 static void gds_clear_stack();
890 static int gds_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
891 double *y3, double *x4, double *y4);
892 static void gds_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
893 double x4, double y4);
894
895 void ConvertSplinedPolygon(int& n, wxPoint2DDouble* points[], double Aber)
896 {
897 wxList h;
898 int i;
899 for (i = 0; i < n; i++)
900 {
901 h.Append((wxObject*) new wxPoint2DDouble((*points)[i].m_x, (*points)[i].m_y));
902 }
903 delete *points;
904
905 ConvertSplinedPolygon(&h, Aber);
906
907 n=h.GetCount();
908 *points = new wxPoint2DDouble[n];
909 wxNode* node=h.GetFirst();
910 for (i = 0; i < n; i++)
911 {
912 wxNode* hh= node;
913 node = node->GetNext();
914 (*points)[i].m_x=((wxPoint2DDouble*) hh->GetData())->m_x;
915 (*points)[i].m_y=((wxPoint2DDouble*) hh->GetData())->m_y;
916 delete (wxPoint2DDouble*) hh->GetData();
917 h.DeleteNode(hh);
918 }
919 }
920
921 void ConvertSplinedPolygon(wxList* list, double Aber)
922 {
923 wxPoint2DDouble* point;
924 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
925 double x1, y1, x2, y2;
926
927 if (list->GetCount() <2)
928 return;
929
930 wxNode* iter=list->GetLast();
931 x1 = ((wxPoint2DDouble*)iter->Data())->m_x;
932 y1 = ((wxPoint2DDouble*)iter->Data())->m_y;
933
934 iter=list->GetFirst();
935 x2 = ((wxPoint2DDouble*)iter->Data())->m_x;
936 y2 = ((wxPoint2DDouble*)iter->Data())->m_y;
937
938 point = new wxPoint2DDouble(x2,y2);
939 list->Append((wxObject*)point);
940
941 cx1 = (x1 + x2) / 2.0;
942 cy1 = (y1 + y2) / 2.0;
943 cx2 = (cx1 + x2) / 2.0;
944 cy2 = (cy1 + y2) / 2.0;
945
946 delete (wxPoint2DDouble*) iter->Data();
947 delete iter;
948 iter=list->GetFirst();
949 x1 = ((wxPoint2DDouble*)iter->Data())->m_x;
950 y1 = ((wxPoint2DDouble*)iter->Data())->m_y;
951 point = new wxPoint2DDouble(x1,y1);
952 list->Append((wxObject*)point);
953
954 int i=1;
955 int count=list->GetCount();
956 while (i < count)
957 {
958 x1 = x2;
959 y1 = y2;
960 x2 = ((wxPoint2DDouble*)iter->Data())->m_x;
961 y2 = ((wxPoint2DDouble*)iter->Data())->m_y;
962 cx4 = (x1 + x2) / 2.0;
963 cy4 = (y1 + y2) / 2.0;
964 cx3 = (x1 + cx4) / 2.0;
965 cy3 = (y1 + cy4) / 2.0;
966
967 gds_quadratic_spline(list,cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4,Aber);
968
969 cx1 = cx4;
970 cy1 = cy4;
971 cx2 = (cx1 + x2) / 2.0;
972 cy2 = (cy1 + y2) / 2.0;
973 delete (wxPoint2DDouble*)iter->Data();
974 delete iter;
975 iter=list->GetFirst();
976 i++;
977 }
978
979 iter=list->GetFirst();
980 delete (wxPoint2DDouble*)iter->Data();
981 delete iter;
982 }
983
984 void ConvertSplinedPolyline(wxList* list,double Aber)
985 {
986 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
987 double x1, y1, x2, y2;
988
989
990 if (list->GetCount() <2)
991 return;
992
993
994
995 wxNode* iter=list->GetFirst();
996
997 x1 = ((wxPoint2DDouble*)iter->Data())->m_x;
998 y1 = ((wxPoint2DDouble*)iter->Data())->m_y;
999
1000 delete (wxPoint2DDouble*)iter->Data();
1001 delete iter;
1002 iter=list->GetFirst();
1003 x2 = ((wxPoint2DDouble*)iter->Data())->m_x;
1004 y2 = ((wxPoint2DDouble*)iter->Data())->m_y;
1005 cx1 = (x1 + x2) / 2.0;
1006 cy1 = (y1 + y2) / 2.0;
1007 cx2 = (cx1 + x2) / 2.0;
1008 cy2 = (cy1 + y2) / 2.0;
1009
1010 wxPoint2DDouble* point = new wxPoint2DDouble(x1,y1);
1011 list->Append((wxObject*)point);
1012
1013 delete (wxPoint2DDouble*)iter->Data();
1014 delete iter;
1015 iter=list->GetFirst();
1016
1017 int i=1;
1018 int count=list->GetCount();
1019 while (i < count)
1020 {
1021 x1 = x2;
1022 y1 = y2;
1023 x2 = ((wxPoint2DDouble*)iter->Data())->m_x;
1024 y2 = ((wxPoint2DDouble*)iter->Data())->m_y;
1025 cx4 = (x1 + x2) / 2.0;
1026 cy4 = (y1 + y2) / 2.0;
1027 cx3 = (x1 + cx4) / 2.0;
1028 cy3 = (y1 + cy4) / 2.0;
1029
1030 gds_quadratic_spline(list,cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4,Aber);
1031
1032 cx1 = cx4;
1033 cy1 = cy4;
1034 cx2 = (cx1 + x2) / 2.0;
1035 cy2 = (cy1 + y2) / 2.0;
1036 delete (wxPoint2DDouble*)iter->Data();
1037 delete iter;
1038 iter=list->GetFirst();
1039 i++;
1040 }
1041
1042 point = new wxPoint2DDouble(cx1,cy1);
1043 list->Append((wxObject*)point);
1044
1045 point = new wxPoint2DDouble(x2,y2);
1046 list->Append((wxObject*)point);
1047 }
1048
1049 /********************* CURVES FOR SPLINES *****************************
1050
1051 The following spline drawing routine is from
1052
1053 "An Algorithm for High-Speed Curve Generation"
1054 by George Merrill Chaikin,
1055 Computer Graphics and Image Processing, 3, Academic Press,
1056 1974, 346-349.
1057
1058 and
1059
1060 "On Chaikin's Algorithm" by R. F. Riesenfeld,
1061 Computer Graphics and Image Processing, 4, Academic Press,
1062 1975, 304-310.
1063
1064 ***********************************************************************/
1065
1066 #define half(z1, z2) ((z1+z2)/2.0)
1067 #define THRESHOLD 5
1068
1069 /* iterative version */
1070
1071 void gds_quadratic_spline(wxList *org,double a1, double b1, double a2, double b2, double a3, double b3, double a4,
1072 double b4,double Aber)
1073 {
1074 register double xmid, ymid;
1075 double x1, y1, x2, y2, x3, y3, x4, y4;
1076 wxPoint2DDouble* point;
1077
1078 gds_clear_stack();
1079 gds_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
1080
1081 while (gds_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4))
1082 {
1083 xmid = half(x2, x3);
1084 ymid = half(y2, y3);
1085 if (fabs(x1 - xmid) < Aber && fabs(y1 - ymid) < Aber &&
1086 fabs(xmid - x4) < Aber && fabs(ymid - y4) < Aber)
1087 {
1088 point = new wxPoint2DDouble(x1,y1);
1089 org->Append((wxObject*)point);
1090 point = new wxPoint2DDouble(xmid,ymid);
1091 org->Append((wxObject*)point);
1092 } else {
1093 gds_spline_push(xmid, ymid, half(xmid, x3), half(ymid, y3),
1094 half(x3, x4), half(y3, y4), x4, y4);
1095 gds_spline_push(x1, y1, half(x1, x2), half(y1, y2),
1096 half(x2, xmid), half(y2, ymid), xmid, ymid);
1097 }
1098 }
1099 }
1100
1101
1102 /* utilities used by spline drawing routines */
1103
1104
1105 typedef struct gds_spline_stack_struct {
1106 double x1, y1, x2, y2, x3, y3, x4, y4;
1107 }
1108 Stack;
1109
1110 #define SPLINE_STACK_DEPTH 20
1111 static Stack gds_spline_stack[SPLINE_STACK_DEPTH];
1112 static Stack *gds_stack_top;
1113 static int gds_stack_count;
1114
1115 static void gds_clear_stack()
1116 {
1117 gds_stack_top = gds_spline_stack;
1118 gds_stack_count = 0;
1119 }
1120
1121 static void gds_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
1122 {
1123 gds_stack_top->x1 = x1;
1124 gds_stack_top->y1 = y1;
1125 gds_stack_top->x2 = x2;
1126 gds_stack_top->y2 = y2;
1127 gds_stack_top->x3 = x3;
1128 gds_stack_top->y3 = y3;
1129 gds_stack_top->x4 = x4;
1130 gds_stack_top->y4 = y4;
1131 gds_stack_top++;
1132 gds_stack_count++;
1133 }
1134
1135 int gds_spline_pop(double *x1, double *y1, double *x2, double *y2,
1136 double *x3, double *y3, double *x4, double *y4)
1137 {
1138 if (gds_stack_count == 0)
1139 return (0);
1140 gds_stack_top--;
1141 gds_stack_count--;
1142 *x1 = gds_stack_top->x1;
1143 *y1 = gds_stack_top->y1;
1144 *x2 = gds_stack_top->x2;
1145 *y2 = gds_stack_top->y2;
1146 *x3 = gds_stack_top->x3;
1147 *y3 = gds_stack_top->y3;
1148 *x4 = gds_stack_top->x4;
1149 *y4 = gds_stack_top->y4;
1150 return (1);
1151 }
1152
1153 void wxAET::CalculateLineParameters( const wxPoint2DDouble& p1 , const wxPoint2DDouble& p2 )
1154 {
1155 double A = p2.m_y - p1.m_y; //A (y2-y1)
1156 if (A == 0)
1157 {
1158 m_horizontal=TRUE;
1159 m_BdivA=0;
1160 m_CdivA=0;
1161 }
1162 else
1163 {
1164 m_horizontal=FALSE;
1165 m_BdivA= (p1.m_x - p2.m_x)/A; //B (x1-x2)
1166 //normalize
1167 m_CdivA= ((p2.m_x*p1.m_y) - (p1.m_x*p2.m_y)) /A ;
1168 }
1169 }
1170
1171 void wxAET::CalculateXs( double y )
1172 {
1173 m_xs= -m_BdivA * y - m_CdivA;
1174 }
1175
1176 //use by polygon filling
1177 //moves the scanline up
1178 //index is the index of the point where the search begins
1179 //direction is +1 or -1 and indicates if the segment ascends or decends
1180 bool wxCanvasPolygon::MoveUp( double horline, int& index, int direction)
1181 {
1182 int walk = (index + direction + m_n) % m_n;
1183 while ( m_points[walk].m_y < horline )
1184 {
1185 if (m_points[walk].m_y < m_points[index].m_y )
1186 return FALSE;
1187 else
1188 {
1189 //modify index
1190 index=walk;
1191 walk = (index + direction + m_n) % m_n;
1192 }
1193 }
1194 return TRUE;
1195 }
1196
1197 //a crictical point is a point between a decending and a ascending segment
1198 //collect those points for filling later
1199 void wxCanvasPolygon::DetectCriticalPoints()
1200 {
1201 //candidate for critical point
1202 //true if Y is getting lower, unchanged i Y is unchanged
1203 //and if Y becomes higher and candidate was true: it is a critical point
1204 bool candidate = FALSE;
1205 int i,j;
1206
1207 for ( i=0; i < m_n; i++)
1208 {
1209 //j next point
1210 j= (i+1) % m_n;
1211
1212 //check if Y is smaller
1213 if (m_points[i].m_y > m_points[j].m_y)
1214 //we have a candidate
1215 candidate=TRUE;
1216 else if ( (m_points[i].m_y < m_points[j].m_y) && candidate)
1217 { //this is a critical point put in list
1218 bool inserted=FALSE;
1219 wxNode *node = m_CRlist.GetFirst();
1220 while (node)
1221 {
1222 //sorted on smallest Y value
1223 int* ind=(int*) node->GetData();
1224 if (m_points[*ind].m_y > m_points[i].m_y)
1225 {
1226 m_CRlist.Insert(node,(wxObject*) new int(i));
1227 inserted = TRUE;
1228 break;
1229 }
1230 node = node->GetNext();
1231 }
1232 if (!inserted)
1233 m_CRlist.Append((wxObject*) new int(i));
1234 candidate = FALSE;
1235 }
1236 }
1237 if (candidate)
1238 {
1239 for ( i=0; i < m_n; i++)
1240 {
1241 //j next point
1242 j= (i+1) % m_n;
1243
1244 //check if Y is smaller
1245 if (m_points[i].m_y > m_points[j].m_y)
1246 //we have a candidate
1247 candidate=TRUE;
1248 else if ( (m_points[i].m_y < m_points[j].m_y) && candidate)
1249 { //this is a critical point put in list
1250 bool inserted=FALSE;
1251 wxNode *node = m_CRlist.GetFirst();
1252 while (node)
1253 {
1254 //sorted on smallest Y value
1255 int* ind=(int*) node->GetData();
1256 if (m_points[*ind].m_y > m_points[i].m_y)
1257 {
1258 m_CRlist.Insert(node,(wxObject*) new int(i));
1259 inserted = TRUE;
1260 break;
1261 }
1262 node = node->GetNext();
1263 }
1264 if (!inserted)
1265 m_CRlist.Append((wxObject*) new int(i));
1266 candidate = FALSE;
1267 }
1268 }
1269 }
1270 }
1271
1272
1273 void wxCanvasPolygon::FillPolygon(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
1274 {
1275 #if IMAGE_CANVAS
1276 #else
1277 int index;
1278 //how much is on pixel in world coordinates
1279
1280 double scalefactor;
1281 if (m_gdistance)
1282 scalefactor=m_gdistance;
1283 else
1284 //abs here needed if yaxis is going up (always scan in world coordinates UP)
1285 scalefactor=fabs(m_admin->DeviceToLogicalYRel(1)); //1 pixel height
1286
1287 wxDC *dc = m_admin->GetActive()->GetDC();
1288 dc->SetClippingRegion( clip_x, clip_y, clip_width, clip_height );
1289 wxPen gradientpen=m_gpen;
1290
1291 int dred = m_textbg.Red()-m_textfg.Red();
1292 int dgreen = m_textbg.Green()-m_textfg.Green();
1293 int dblue = m_textbg.Blue()-m_textfg.Blue();
1294
1295 //total number of lines to go from m_textbg to m_textfg
1296 //gives the following number of steps for the gradient color
1297 int stepcol = (int) (m_bbox.GetHeight()/scalefactor);
1298
1299 DetectCriticalPoints();
1300
1301 double min;
1302 double max;
1303 if (cworld->IsIdentity())
1304 {
1305 //TODO do something with clipping region (inverse transform?)
1306 //the next does not work, i don't know why
1307 //min = wxMin (m_admin->DeviceToLogicalY(clip_y),m_admin->DeviceToLogicalY(clip_y+clip_height));
1308 //max = wxMax (m_admin->DeviceToLogicalY(clip_y),m_admin->DeviceToLogicalY(clip_y+clip_height));
1309 min= m_bbox.GetMinY();
1310 max= m_bbox.GetMaxY();
1311 }
1312 else
1313 {
1314 min= m_bbox.GetMinY();
1315 max= m_bbox.GetMaxY();
1316 }
1317
1318 int curcol = (int)( (min - m_bbox.GetMinY())/scalefactor );
1319
1320 double i;
1321 for ( i = min; i < max; i+=scalefactor)
1322 {
1323 wxNode *node = m_AETlist.GetFirst();
1324 int count= m_AETlist.GetCount();
1325 while (count > 0)
1326 {
1327 wxAET* ele = ((wxAET*)node->GetData());
1328 index= ele->m_index;
1329 int direction = ele->m_direction;
1330 if (!MoveUp(i,index,direction))
1331 {
1332 wxNode* h = node;
1333 //remove this node
1334 node = node->GetNext();
1335 m_AETlist.DeleteNode(h);
1336 }
1337 else
1338 {
1339 if (ele->m_index != index)
1340 {
1341 ele->m_index=index;
1342 int h = (index + direction + m_n) % m_n;
1343 ele->CalculateLineParameters(m_points[h],m_points[index]);
1344 }
1345 if (ele->m_horizontal)
1346 ele->m_xs=m_points[index].m_x;
1347 else
1348 ele->CalculateXs(i);
1349 node = node->GetNext();
1350 }
1351 count--;
1352 }
1353
1354 node = m_CRlist.GetFirst();
1355 while (m_CRlist.GetCount() && m_points[*((int*)node->GetData())].m_y <=i )
1356 {
1357 int DI;
1358 for ( DI = -1; DI <=1 ; DI+=2)
1359 {
1360 index=*((int*)node->GetData());
1361 if (MoveUp(i,index,DI))
1362 {
1363 wxAET* ele = new wxAET();
1364 ele->m_index=index;
1365 ele->m_direction=DI;
1366 int h = (index + DI + m_n) % m_n;
1367 ele->CalculateLineParameters(m_points[h],m_points[index]);
1368 if (ele->m_horizontal)
1369 ele->m_xs=m_points[index].m_x;
1370 else
1371 ele->CalculateXs(i);
1372
1373 //insert in sorted order od m_xs
1374 bool inserted=FALSE;
1375 wxNode *node2 = m_AETlist.GetFirst();
1376 while (node2)
1377 {
1378 //sorted on smallest xs value
1379 if (ele->m_xs < ((wxAET*)node2->GetData())->m_xs)
1380 {
1381 m_AETlist.Insert(node2,(wxObject*) ele);
1382 inserted = TRUE;
1383 break;
1384 }
1385 node2 = node2->GetNext();
1386 }
1387 if (!inserted)
1388 m_AETlist.Append((wxObject*)ele);
1389 }
1390 }
1391
1392 wxNode* h= node;
1393 node = node->GetNext();
1394 m_CRlist.DeleteNode(h);
1395 }
1396
1397 curcol++;
1398 wxColour gradcol(m_textbg.Red()+dred*curcol/stepcol,
1399 m_textbg.Green()+dgreen*curcol/stepcol,
1400 m_textbg.Blue()+dblue*curcol/stepcol);
1401 gradientpen.SetColour(gradcol);
1402
1403 //m_AETlist must be sorted in m_xs at this moment
1404 //now draw all the line parts on one horizontal scanline (Winding Rule)
1405 int out= 0;
1406 node = m_AETlist.GetFirst();
1407 while (node)
1408 {
1409 wxAET* ele = ((wxAET*)node->GetData());
1410 out+=ele->m_direction;
1411 if (out != 0)
1412 {
1413 double x1=ele->m_xs;
1414 node = node->GetNext();
1415 ele = ((wxAET*)node->GetData());
1416 double x2=ele->m_xs;
1417 dc->SetPen( gradientpen );
1418 double wx1,wy1,wx2,wy2;
1419 cworld->TransformPoint( x1, i, wx1, wy1 );
1420 cworld->TransformPoint( x2, i, wx2, wy2 );
1421 int dx1,dy1,dx2,dy2;
1422 dx1 = m_admin->LogicalToDeviceX( wx1 );
1423 dy1 = m_admin->LogicalToDeviceY( wy1 );
1424 dx2 = m_admin->LogicalToDeviceX( wx2 );
1425 dy2 = m_admin->LogicalToDeviceY( wy2 );
1426
1427 //TODO KKK need real line clipping here since line can be rotated.
1428 if (0 && cworld->IsIdentity())
1429 {
1430 if (dx1 < clip_x) dx1=clip_x;
1431 if (dx2 > clip_x + clip_width) dx2=clip_x + clip_width;
1432 if ((dy1 > clip_y) && dy1 < clip_y + clip_height)
1433 dc->DrawLine( dx1, dy1, dx2, dy2 );
1434 }
1435 else
1436 {
1437 dc->DrawLine( dx1, dy1, dx2, dy2 );
1438 }
1439
1440 }
1441 else
1442 node = node->GetNext();
1443 }
1444 }
1445
1446 dc->DestroyClippingRegion();
1447 #endif
1448 }
1449
1450
1451
1452
1453