]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/ogl/ogldiag.cpp
updates from Adrián González Alba
[wxWidgets.git] / contrib / src / ogl / ogldiag.cpp
CommitLineData
1fc25a89
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: ogldiag.cpp
3// Purpose: wxDiagram
4// Author: Julian Smart
5// Modified by:
6// Created: 12/07/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
2ba06d5a 9// Licence: wxWindows licence
1fc25a89
JS
10/////////////////////////////////////////////////////////////////////////////
11
1fc25a89 12// For compilers that support precompilation, includes "wx.h".
92a19c2e 13#include "wx/wxprec.h"
1fc25a89
JS
14
15#ifdef __BORLANDC__
16#pragma hdrstop
17#endif
18
19#ifndef WX_PRECOMP
6b62c9ad 20#include "wx/wx.h"
1fc25a89
JS
21#endif
22
5f331691 23#if wxUSE_PROLOGIO
6b62c9ad 24#include "wx/deprecated/wxexpr.h"
fd657b8a 25#endif
1fc25a89 26
3f1802b5
JS
27#ifdef new
28#undef new
29#endif
30
1fc25a89
JS
31#include <ctype.h>
32#include <math.h>
33#include <stdlib.h>
34
5f331691
RD
35#include "wx/ogl/ogl.h"
36
1fc25a89
JS
37
38IMPLEMENT_DYNAMIC_CLASS(wxDiagram, wxObject)
39
40// Object canvas
41wxDiagram::wxDiagram()
42{
43 m_diagramCanvas = NULL;
2ba06d5a
WS
44 m_quickEditMode = false;
45 m_snapToGrid = true;
1fc25a89
JS
46 m_gridSpacing = 5.0;
47 m_shapeList = new wxList;
48 m_mouseTolerance = DEFAULT_MOUSE_TOLERANCE;
49}
50
51wxDiagram::~wxDiagram()
52{
53 if (m_shapeList)
54 delete m_shapeList;
55}
56
57void wxDiagram::SetSnapToGrid(bool snap)
58{
59 m_snapToGrid = snap;
60}
61
62void wxDiagram::SetGridSpacing(double spacing)
63{
64 m_gridSpacing = spacing;
65}
66
67void wxDiagram::Snap(double *x, double *y)
68{
69 if (m_snapToGrid)
70 {
71 *x = m_gridSpacing * ((int)(*x/m_gridSpacing + 0.5));
72 *y = m_gridSpacing * ((int)(*y/m_gridSpacing + 0.5));
73 }
74}
75
76
77void wxDiagram::Redraw(wxDC& dc)
78{
79 if (m_shapeList)
80 {
81 if (GetCanvas())
82 GetCanvas()->SetCursor(* wxHOURGLASS_CURSOR);
b9ac87bc 83 wxNode *current = m_shapeList->GetFirst();
1fc25a89
JS
84
85 while (current)
86 {
b9ac87bc 87 wxShape *object = (wxShape *)current->GetData();
1fc25a89
JS
88 if (!object->GetParent())
89 object->Draw(dc);
90
b9ac87bc 91 current = current->GetNext();
1fc25a89
JS
92 }
93 if (GetCanvas())
94 GetCanvas()->SetCursor(* wxSTANDARD_CURSOR);
95 }
96}
97
98void wxDiagram::Clear(wxDC& dc)
99{
100 dc.Clear();
101}
102
103// Insert object after addAfter, or at end of list.
104void wxDiagram::AddShape(wxShape *object, wxShape *addAfter)
105{
106 wxNode *nodeAfter = NULL;
107 if (addAfter)
108 nodeAfter = m_shapeList->Member(addAfter);
109
110 if (!m_shapeList->Member(object))
111 {
112 if (nodeAfter)
113 {
b9ac87bc
RD
114 if (nodeAfter->GetNext())
115 m_shapeList->Insert(nodeAfter->GetNext(), object);
1fc25a89
JS
116 else
117 m_shapeList->Append(object);
118 }
119 else
120 m_shapeList->Append(object);
121 object->SetCanvas(GetCanvas());
122 }
123}
124
125void wxDiagram::InsertShape(wxShape *object)
126{
127 m_shapeList->Insert(object);
128 object->SetCanvas(GetCanvas());
129}
130
131void wxDiagram::RemoveShape(wxShape *object)
132{
133 m_shapeList->DeleteObject(object);
134}
135
136// Should this delete the actual objects too? I think not.
137void wxDiagram::RemoveAllShapes()
138{
139 m_shapeList->Clear();
140}
141
142void wxDiagram::DeleteAllShapes()
143{
b9ac87bc 144 wxNode *node = m_shapeList->GetFirst();
1fc25a89
JS
145 while (node)
146 {
b9ac87bc 147 wxShape *shape = (wxShape *)node->GetData();
1fc25a89
JS
148 if (!shape->GetParent())
149 {
150 RemoveShape(shape);
151 delete shape;
b9ac87bc 152 node = m_shapeList->GetFirst();
1fc25a89
JS
153 }
154 else
b9ac87bc 155 node = node->GetNext();
1fc25a89
JS
156 }
157}
158
159void wxDiagram::ShowAll(bool show)
160{
b9ac87bc 161 wxNode *current = m_shapeList->GetFirst();
1fc25a89
JS
162
163 while (current)
164 {
b9ac87bc 165 wxShape *object = (wxShape *)current->GetData();
1fc25a89
JS
166 object->Show(show);
167
b9ac87bc 168 current = current->GetNext();
1fc25a89
JS
169 }
170}
171
172void wxDiagram::DrawOutline(wxDC& dc, double x1, double y1, double x2, double y2)
173{
55c91e8a 174 wxPen dottedPen(*wxBLACK, 1, wxDOT);
1fc25a89
JS
175 dc.SetPen(dottedPen);
176 dc.SetBrush((* wxTRANSPARENT_BRUSH));
177
178 wxPoint points[5];
179
180 points[0].x = (int) x1;
181 points[0].y = (int) y1;
182
183 points[1].x = (int) x2;
184 points[1].y = (int) y1;
185
186 points[2].x = (int) x2;
187 points[2].y = (int) y2;
188
189 points[3].x = (int) x1;
190 points[3].y = (int) y2;
191
192 points[4].x = (int) x1;
193 points[4].y = (int) y1;
194 dc.DrawLines(5, points);
195}
196
197// Make sure all text that should be centred, is centred.
198void wxDiagram::RecentreAll(wxDC& dc)
199{
b9ac87bc 200 wxNode *object_node = m_shapeList->GetFirst();
1fc25a89
JS
201 while (object_node)
202 {
b9ac87bc 203 wxShape *obj = (wxShape *)object_node->GetData();
1fc25a89 204 obj->Recentre(dc);
b9ac87bc 205 object_node = object_node->GetNext();
1fc25a89
JS
206 }
207}
208
209// Input/output
2b5f62a0 210#if wxUSE_PROLOGIO
1fc25a89
JS
211bool wxDiagram::SaveFile(const wxString& filename)
212{
213 wxBeginBusyCursor();
214
215 wxExprDatabase *database = new wxExprDatabase;
216
217 // First write the diagram type
1484b5cc 218 wxExpr *header = new wxExpr(_T("diagram"));
1fc25a89
JS
219 OnHeaderSave(*database, *header);
220
221 database->Append(header);
222
b9ac87bc 223 wxNode *node = m_shapeList->GetFirst();
1fc25a89
JS
224 while (node)
225 {
b9ac87bc 226 wxShape *shape = (wxShape *)node->GetData();
1fc25a89
JS
227
228 if (!shape->IsKindOf(CLASSINFO(wxControlPoint)))
229 {
8552e6f0 230 wxExpr *expr;
1fc25a89 231 if (shape->IsKindOf(CLASSINFO(wxLineShape)))
1484b5cc 232 expr = new wxExpr(_T("line"));
1fc25a89 233 else
1484b5cc 234 expr = new wxExpr(_T("shape"));
1fc25a89
JS
235
236 OnShapeSave(*database, *shape, *expr);
237 }
8552e6f0 238 node = node->GetNext();
1fc25a89
JS
239 }
240 OnDatabaseSave(*database);
241
c1fa2fda
RD
242 wxString tempFile;
243 wxGetTempFileName(wxT("diag"), tempFile);
244 FILE* file = fopen(tempFile.mb_str(wxConvFile), "w");
1fc25a89
JS
245 if (! file)
246 {
247 wxEndBusyCursor();
248 delete database;
2ba06d5a 249 return false;
1fc25a89
JS
250 }
251
252 database->Write(file);
253 fclose(file);
254 delete database;
255
256/*
257 // Save backup
258 if (FileExists(filename))
259 {
260 char buf[400];
261#ifdef __X__
262 sprintf(buf, "%s.bak", filename);
263#endif
264#ifdef __WXMSW__
265 sprintf(buf, "_diagram.bak");
266#endif
267 if (FileExists(buf)) wxRemoveFile(buf);
268 if (!wxRenameFile(filename, buf))
269 {
270 wxCopyFile(filename, buf);
271 wxRemoveFile(filename);
272 }
273 }
274*/
275
276 // Copy the temporary file to the correct filename
277 if (!wxRenameFile(tempFile, filename))
278 {
279 wxCopyFile(tempFile, filename);
280 wxRemoveFile(tempFile);
281 }
282
283 wxEndBusyCursor();
2ba06d5a 284 return true;
1fc25a89
JS
285}
286
287bool wxDiagram::LoadFile(const wxString& filename)
288{
289 wxBeginBusyCursor();
290
1484b5cc 291 wxExprDatabase database(wxExprInteger, _T("id"));
1fc25a89
JS
292 if (!database.Read(filename))
293 {
294 wxEndBusyCursor();
2ba06d5a 295 return false;
1fc25a89
JS
296 }
297
298 DeleteAllShapes();
299
300 database.BeginFind();
1484b5cc 301 wxExpr *header = database.FindClauseByFunctor(_T("diagram"));
1fc25a89
JS
302
303 if (header)
304 OnHeaderLoad(database, *header);
305
306 // Scan through all clauses and register the ids
8552e6f0 307 wxNode *node = database.GetFirst();
1fc25a89
JS
308 while (node)
309 {
b9ac87bc 310 wxExpr *clause = (wxExpr *)node->GetData();
1fc25a89 311 long id = -1;
1484b5cc 312 clause->GetAttributeValue(_T("id"), id);
1fc25a89 313 wxRegisterId(id);
8552e6f0 314 node = node->GetNext();
1fc25a89
JS
315 }
316
317 ReadNodes(database);
318 ReadContainerGeometry(database);
319 ReadLines(database);
320
321 OnDatabaseLoad(database);
322
323 wxEndBusyCursor();
324
2ba06d5a 325 return true;
1fc25a89
JS
326}
327
328void wxDiagram::ReadNodes(wxExprDatabase& database)
329{
330 // Find and create the node images
331 database.BeginFind();
1484b5cc 332 wxExpr *clause = database.FindClauseByFunctor(_T("shape"));
1fc25a89
JS
333 while (clause)
334 {
c1fa2fda 335 wxChar *type = NULL;
1fc25a89
JS
336 long parentId = -1;
337
c1fa2fda
RD
338 clause->AssignAttributeValue(wxT("type"), &type);
339 clause->AssignAttributeValue(wxT("parent"), &parentId);
1fc25a89
JS
340 wxClassInfo *classInfo = wxClassInfo::FindClass(type);
341 if (classInfo)
342 {
343 wxShape *shape = (wxShape *)classInfo->CreateObject();
344 OnShapeLoad(database, *shape, *clause);
345
346 shape->SetCanvas(GetCanvas());
2ba06d5a 347 shape->Show(true);
1fc25a89
JS
348
349 m_shapeList->Append(shape);
350
351 // If child of composite, link up
352 if (parentId > -1)
353 {
1484b5cc 354 wxExpr *parentExpr = database.HashFind(_T("shape"), parentId);
1fc25a89
JS
355 if (parentExpr && parentExpr->GetClientData())
356 {
357 wxShape *parent = (wxShape *)parentExpr->GetClientData();
358 shape->SetParent(parent);
359 parent->GetChildren().Append(shape);
360 }
361 }
362
363 clause->SetClientData(shape);
364 }
365 if (type)
366 delete[] type;
367
1484b5cc 368 clause = database.FindClauseByFunctor(_T("shape"));
1fc25a89
JS
369 }
370 return;
371}
372
373void wxDiagram::ReadLines(wxExprDatabase& database)
374{
375 database.BeginFind();
1484b5cc 376 wxExpr *clause = database.FindClauseByFunctor(_T("line"));
1fc25a89
JS
377 while (clause)
378 {
c1fa2fda 379 wxString type;
1fc25a89
JS
380 long parentId = -1;
381
1484b5cc
VS
382 clause->GetAttributeValue(_T("type"), type);
383 clause->GetAttributeValue(_T("parent"), parentId);
c1fa2fda 384 wxClassInfo *classInfo = wxClassInfo::FindClass(type);
1fc25a89
JS
385 if (classInfo)
386 {
387 wxLineShape *shape = (wxLineShape *)classInfo->CreateObject();
2ba06d5a 388 shape->Show(true);
1fc25a89
JS
389
390 OnShapeLoad(database, *shape, *clause);
391 shape->SetCanvas(GetCanvas());
392
393 long image_to = -1; long image_from = -1;
1484b5cc
VS
394 clause->GetAttributeValue(_T("to"), image_to);
395 clause->GetAttributeValue(_T("from"), image_from);
1fc25a89 396
1484b5cc 397 wxExpr *image_to_expr = database.HashFind(_T("shape"), image_to);
1fc25a89
JS
398
399 if (!image_to_expr)
400 {
401 // Error
402 }
1484b5cc 403 wxExpr *image_from_expr = database.HashFind(_T("shape"), image_from);
1fc25a89
JS
404
405 if (!image_from_expr)
406 {
407 // Error
408 }
409
410 if (image_to_expr && image_from_expr)
411 {
412 wxShape *image_to_object = (wxShape *)image_to_expr->GetClientData();
413 wxShape *image_from_object = (wxShape *)image_from_expr->GetClientData();
414
415 if (image_to_object && image_from_object)
416 {
417 image_from_object->AddLine(shape, image_to_object, shape->GetAttachmentFrom(), shape->GetAttachmentTo());
418 }
419 }
420 clause->SetClientData(shape);
421
422 m_shapeList->Append(shape);
423 }
424
1484b5cc 425 clause = database.FindClauseByFunctor(_T("line"));
1fc25a89
JS
426 }
427}
428
429// Containers have divisions that reference adjoining divisions,
430// so we need a separate pass to link everything up.
431// Also used by Symbol Library.
432void wxDiagram::ReadContainerGeometry(wxExprDatabase& database)
433{
434 database.BeginFind();
1484b5cc 435 wxExpr *clause = database.FindClauseByFunctor(_T("shape"));
1fc25a89
JS
436 while (clause)
437 {
438 wxShape *image = (wxShape *)clause->GetClientData();
439 if (image && image->IsKindOf(CLASSINFO(wxCompositeShape)))
440 {
441 wxCompositeShape *composite = (wxCompositeShape *)image;
442 wxExpr *divisionExpr = NULL;
443
444 // Find the list of divisions in the composite
1484b5cc 445 clause->GetAttributeValue(_T("divisions"), &divisionExpr);
1fc25a89
JS
446 if (divisionExpr)
447 {
448 int i = 0;
7c9955d1 449 wxExpr *idExpr = divisionExpr->Nth(i);
1fc25a89
JS
450 while (idExpr)
451 {
452 long divisionId = idExpr->IntegerValue();
1484b5cc 453 wxExpr *childExpr = database.HashFind(_T("shape"), divisionId);
1fc25a89
JS
454 if (childExpr && childExpr->GetClientData())
455 {
456 wxDivisionShape *child = (wxDivisionShape *)childExpr->GetClientData();
457 composite->GetDivisions().Append(child);
458
459 // Find the adjoining shapes
460 long leftSideId = -1;
461 long topSideId = -1;
462 long rightSideId = -1;
463 long bottomSideId = -1;
1484b5cc
VS
464 childExpr->GetAttributeValue(_T("left_side"), leftSideId);
465 childExpr->GetAttributeValue(_T("top_side"), topSideId);
466 childExpr->GetAttributeValue(_T("right_side"), rightSideId);
467 childExpr->GetAttributeValue(_T("bottom_side"), bottomSideId);
1fc25a89
JS
468 if (leftSideId > -1)
469 {
1484b5cc 470 wxExpr *leftExpr = database.HashFind(_T("shape"), leftSideId);
1fc25a89
JS
471 if (leftExpr && leftExpr->GetClientData())
472 {
473 wxDivisionShape *leftSide = (wxDivisionShape *)leftExpr->GetClientData();
474 child->SetLeftSide(leftSide);
475 }
476 }
477 if (topSideId > -1)
478 {
1484b5cc 479 wxExpr *topExpr = database.HashFind(_T("shape"), topSideId);
1fc25a89
JS
480 if (topExpr && topExpr->GetClientData())
481 {
482 wxDivisionShape *topSide = (wxDivisionShape *)topExpr->GetClientData();
483 child->SetTopSide(topSide);
484 }
485 }
486 if (rightSideId > -1)
487 {
1484b5cc 488 wxExpr *rightExpr = database.HashFind(_T("shape"), rightSideId);
1fc25a89
JS
489 if (rightExpr && rightExpr->GetClientData())
490 {
491 wxDivisionShape *rightSide = (wxDivisionShape *)rightExpr->GetClientData();
492 child->SetRightSide(rightSide);
493 }
494 }
495 if (bottomSideId > -1)
496 {
1484b5cc 497 wxExpr *bottomExpr = database.HashFind(_T("shape"), bottomSideId);
1fc25a89
JS
498 if (bottomExpr && bottomExpr->GetClientData())
499 {
500 wxDivisionShape *bottomSide = (wxDivisionShape *)bottomExpr->GetClientData();
501 child->SetBottomSide(bottomSide);
502 }
503 }
504 }
505 i ++;
7c9955d1 506 idExpr = divisionExpr->Nth(i);
1fc25a89
JS
507 }
508 }
509 }
510
1484b5cc 511 clause = database.FindClauseByFunctor(_T("shape"));
1fc25a89
JS
512 }
513}
514
515// Allow for modifying file
1484b5cc 516bool wxDiagram::OnDatabaseLoad(wxExprDatabase& WXUNUSED(db))
1fc25a89 517{
2ba06d5a 518 return true;
1fc25a89
JS
519}
520
1484b5cc 521bool wxDiagram::OnDatabaseSave(wxExprDatabase& WXUNUSED(db))
1fc25a89 522{
2ba06d5a 523 return true;
1fc25a89
JS
524}
525
526bool wxDiagram::OnShapeSave(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
527{
528 shape.WriteAttributes(&expr);
529 db.Append(&expr);
530
531 if (shape.IsKindOf(CLASSINFO(wxCompositeShape)))
532 {
8552e6f0 533 wxNode *node = shape.GetChildren().GetFirst();
1fc25a89
JS
534 while (node)
535 {
b9ac87bc 536 wxShape *childShape = (wxShape *)node->GetData();
1484b5cc 537 wxExpr *childExpr = new wxExpr(_T("shape"));
1fc25a89 538 OnShapeSave(db, *childShape, *childExpr);
8552e6f0 539 node = node->GetNext();
1fc25a89
JS
540 }
541 }
542
2ba06d5a 543 return true;
1fc25a89
JS
544}
545
1484b5cc 546bool wxDiagram::OnShapeLoad(wxExprDatabase& WXUNUSED(db), wxShape& shape, wxExpr& expr)
1fc25a89
JS
547{
548 shape.ReadAttributes(&expr);
2ba06d5a 549 return true;
1fc25a89
JS
550}
551
1484b5cc 552bool wxDiagram::OnHeaderSave(wxExprDatabase& WXUNUSED(db), wxExpr& WXUNUSED(expr))
1fc25a89 553{
2ba06d5a 554 return true;
1fc25a89
JS
555}
556
1484b5cc 557bool wxDiagram::OnHeaderLoad(wxExprDatabase& WXUNUSED(db), wxExpr& WXUNUSED(expr))
1fc25a89 558{
2ba06d5a 559 return true;
1fc25a89
JS
560}
561
562#endif
563
564void wxDiagram::SetCanvas(wxShapeCanvas *can)
565{
566 m_diagramCanvas = can;
567}
568
569// Find a shape by its id
570wxShape* wxDiagram::FindShape(long id) const
571{
b9ac87bc 572 wxNode* node = GetShapeList()->GetFirst();
1fc25a89
JS
573 while (node)
574 {
b9ac87bc 575 wxShape* shape = (wxShape*) node->GetData();
1fc25a89
JS
576 if (shape->GetId() == id)
577 return shape;
b9ac87bc 578 node = node->GetNext();
1fc25a89
JS
579 }
580 return NULL;
581}
582
583
584//// Crossings classes
585
586wxLineCrossings::wxLineCrossings()
587{
588}
589
590wxLineCrossings::~wxLineCrossings()
591{
592 ClearCrossings();
593}
594
595void wxLineCrossings::FindCrossings(wxDiagram& diagram)
596{
597 ClearCrossings();
b9ac87bc 598 wxNode* node1 = diagram.GetShapeList()->GetFirst();
1fc25a89
JS
599 while (node1)
600 {
b9ac87bc 601 wxShape* shape1 = (wxShape*) node1->GetData();
1fc25a89
JS
602 if (shape1->IsKindOf(CLASSINFO(wxLineShape)))
603 {
604 wxLineShape* lineShape1 = (wxLineShape*) shape1;
605 // Iterate through the segments
606 wxList* pts1 = lineShape1->GetLineControlPoints();
1dde66dd 607 size_t i;
b9ac87bc 608 for (i = 0; i < (pts1->GetCount() - 1); i++)
1fc25a89 609 {
b9ac87bc
RD
610 wxRealPoint* pt1_a = (wxRealPoint*) (pts1->Item(i)->GetData());
611 wxRealPoint* pt1_b = (wxRealPoint*) (pts1->Item(i+1)->GetData());
1fc25a89
JS
612
613 // Now we iterate through the segments again
614
b9ac87bc 615 wxNode* node2 = diagram.GetShapeList()->GetFirst();
1fc25a89
JS
616 while (node2)
617 {
b9ac87bc 618 wxShape* shape2 = (wxShape*) node2->GetData();
1fc25a89
JS
619
620 // Assume that the same line doesn't cross itself
621 if (shape2->IsKindOf(CLASSINFO(wxLineShape)) && (shape1 != shape2))
622 {
623 wxLineShape* lineShape2 = (wxLineShape*) shape2;
624 // Iterate through the segments
625 wxList* pts2 = lineShape2->GetLineControlPoints();
626 int j;
1dde66dd 627 for (j = 0; j < (int) (pts2->GetCount() - 1); j++)
1fc25a89 628 {
b9ac87bc
RD
629 wxRealPoint* pt2_a = (wxRealPoint*) (pts2->Item(j)->GetData());
630 wxRealPoint* pt2_b = (wxRealPoint*) (pts2->Item(j+1)->GetData());
1fc25a89
JS
631
632 // Now let's see if these two segments cross.
633 double ratio1, ratio2;
634 oglCheckLineIntersection(pt1_a->x, pt1_a->y, pt1_b->x, pt1_b->y,
635 pt2_a->x, pt2_a->y, pt2_b->x, pt2_b->y,
636 & ratio1, & ratio2);
637
638 if ((ratio1 < 1.0) && (ratio1 > -1.0))
639 {
640 // Intersection!
641 wxLineCrossing* crossing = new wxLineCrossing;
642 crossing->m_intersect.x = (pt1_a->x + (pt1_b->x - pt1_a->x)*ratio1);
643 crossing->m_intersect.y = (pt1_a->y + (pt1_b->y - pt1_a->y)*ratio1);
644
645 crossing->m_pt1 = * pt1_a;
646 crossing->m_pt2 = * pt1_b;
647 crossing->m_pt3 = * pt2_a;
648 crossing->m_pt4 = * pt2_b;
649
650 crossing->m_lineShape1 = lineShape1;
651 crossing->m_lineShape2 = lineShape2;
652
653 m_crossings.Append(crossing);
654 }
655 }
656 }
b9ac87bc 657 node2 = node2->GetNext();
1fc25a89
JS
658 }
659 }
660 }
661
b9ac87bc 662 node1 = node1->GetNext();
1fc25a89
JS
663 }
664}
665
1484b5cc 666void wxLineCrossings::DrawCrossings(wxDiagram& WXUNUSED(diagram), wxDC& dc)
1fc25a89
JS
667{
668 dc.SetBrush(*wxTRANSPARENT_BRUSH);
669
670 long arcWidth = 8;
671
b9ac87bc 672 wxNode* node = m_crossings.GetFirst();
1fc25a89
JS
673 while (node)
674 {
b9ac87bc 675 wxLineCrossing* crossing = (wxLineCrossing*) node->GetData();
1fc25a89
JS
676// dc.DrawEllipse((long) (crossing->m_intersect.x - (arcWidth/2.0) + 0.5), (long) (crossing->m_intersect.y - (arcWidth/2.0) + 0.5),
677// arcWidth, arcWidth);
678
679
680 // Let's do some geometry to find the points on either end of the arc.
681/*
682
683(x1, y1)
684 |\
685 | \
686 | \
687 | \
688 | \
689 | |\ c c1
690 | a | \
691 | \
692 | - x <-- centre of arc
693 a1 | b |\
694 | | \ c2
695 | a2 | \
696 | - \
697 | b2 \
698 | \
699 |_______________\ (x2, y2)
700 b1
701
702*/
703
704 double a1 = wxMax(crossing->m_pt1.y, crossing->m_pt2.y) - wxMin(crossing->m_pt1.y, crossing->m_pt2.y) ;
705 double b1 = wxMax(crossing->m_pt1.x, crossing->m_pt2.x) - wxMin(crossing->m_pt1.x, crossing->m_pt2.x) ;
706 double c1 = sqrt( (a1*a1) + (b1*b1) );
707
708 double c = arcWidth / 2.0;
709 double a = c * a1/c1 ;
710 double b = c * b1/c1 ;
711
712 // I'm not sure this is right, since we don't know which direction we should be going in - need
713 // to know which way the line slopes and choose the sign appropriately.
714 double arcX1 = crossing->m_intersect.x - b;
715 double arcY1 = crossing->m_intersect.y - a;
716
717 double arcX2 = crossing->m_intersect.x + b;
718 double arcY2 = crossing->m_intersect.y + a;
719
720 dc.SetPen(*wxBLACK_PEN);
721 dc.DrawArc( (long) arcX1, (long) arcY1, (long) arcX2, (long) arcY2,
722 (long) crossing->m_intersect.x, (long) crossing->m_intersect.y);
723
724 dc.SetPen(*wxWHITE_PEN);
725 dc.DrawLine( (long) arcX1, (long) arcY1, (long) arcX2, (long) arcY2 );
726
b9ac87bc 727 node = node->GetNext();
1fc25a89
JS
728 }
729}
730
731void wxLineCrossings::ClearCrossings()
732{
b9ac87bc 733 wxNode* node = m_crossings.GetFirst();
1fc25a89
JS
734 while (node)
735 {
b9ac87bc 736 wxLineCrossing* crossing = (wxLineCrossing*) node->GetData();
1fc25a89 737 delete crossing;
b9ac87bc 738 node = node->GetNext();
1fc25a89
JS
739 }
740 m_crossings.Clear();
741}
742