]> git.saurik.com Git - wxWidgets.git/blob - utils/ogl/src/misc.cpp
OGL improvements
[wxWidgets.git] / utils / ogl / src / misc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: misc.cpp
3 // Purpose: Miscellaneous OGL support functions
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 12/07/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "misc.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include <wx/wxprec.h>
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include <wx/wx.h>
25 #endif
26
27 #ifdef PROLOGIO
28 #include <wx/wxexpr.h>
29 #endif
30
31 #include <wx/types.h>
32
33 #if USE_IOSTREAMH
34 #include <iostream.h>
35 #else
36 #include <iostream>
37 #endif
38 #include <ctype.h>
39 #include <math.h>
40 #include <stdlib.h>
41
42 #include "basic.h"
43 #include "basicp.h"
44 #include "misc.h"
45 #include "constrnt.h"
46 #include "composit.h"
47
48 wxFont* g_oglNormalFont;
49 wxPen* g_oglBlackPen;
50 wxPen* g_oglWhiteBackgroundPen;
51 wxPen* g_oglTransparentPen;
52 wxBrush* g_oglWhiteBackgroundBrush;
53 wxPen* g_oglBlackForegroundPen;
54 wxCursor* g_oglBullseyeCursor = NULL;
55
56 char* oglBuffer = NULL;
57
58 wxList oglObjectCopyMapping(wxKEY_INTEGER);
59
60 void wxOGLInitialize()
61 {
62 g_oglBullseyeCursor = new wxCursor(wxCURSOR_BULLSEYE);
63
64 g_oglNormalFont = new wxFont(10, wxSWISS, wxNORMAL, wxNORMAL);
65
66 g_oglBlackPen = new wxPen("BLACK", 1, wxSOLID);
67
68 g_oglWhiteBackgroundPen = new wxPen("WHITE", 1, wxSOLID);
69 g_oglTransparentPen = new wxPen("WHITE", 1, wxTRANSPARENT);
70 g_oglWhiteBackgroundBrush = new wxBrush("WHITE", wxSOLID);
71 g_oglBlackForegroundPen = new wxPen("BLACK", 1, wxSOLID);
72
73 OGLInitializeConstraintTypes();
74
75 // Initialize big buffer used when writing images
76 oglBuffer = new char[3000];
77
78 if (!oglPopupDivisionMenu)
79 {
80 oglPopupDivisionMenu = new wxMenu("", (wxFunction)oglGraphicsDivisionMenuProc);
81 oglPopupDivisionMenu->Append(DIVISION_MENU_SPLIT_HORIZONTALLY, "Split horizontally");
82 oglPopupDivisionMenu->Append(DIVISION_MENU_SPLIT_VERTICALLY, "Split vertically");
83 oglPopupDivisionMenu->AppendSeparator();
84 oglPopupDivisionMenu->Append(DIVISION_MENU_EDIT_LEFT_EDGE, "Edit left edge");
85 oglPopupDivisionMenu->Append(DIVISION_MENU_EDIT_TOP_EDGE, "Edit top edge");
86 }
87 }
88
89 void wxOGLCleanUp()
90 {
91 if (oglBuffer)
92 {
93 delete[] oglBuffer;
94 oglBuffer = NULL;
95 }
96 oglBuffer = NULL;
97 if (oglPopupDivisionMenu)
98 {
99 delete oglPopupDivisionMenu;
100 oglPopupDivisionMenu = NULL;
101 }
102 if (g_oglBullseyeCursor)
103 {
104 delete g_oglBullseyeCursor;
105 g_oglBullseyeCursor = NULL;
106 }
107
108 if (g_oglNormalFont)
109 {
110 delete g_oglNormalFont;
111 g_oglNormalFont = NULL;
112 }
113 if (g_oglBlackPen)
114 {
115 delete g_oglBlackPen;
116 g_oglBlackPen = NULL;
117 }
118 if (g_oglWhiteBackgroundPen)
119 {
120 delete g_oglWhiteBackgroundPen;
121 g_oglWhiteBackgroundPen = NULL;
122 }
123 if (g_oglTransparentPen)
124 {
125 delete g_oglTransparentPen;
126 g_oglTransparentPen = NULL;
127 }
128 if (g_oglWhiteBackgroundBrush)
129 {
130 delete g_oglWhiteBackgroundBrush;
131 g_oglWhiteBackgroundBrush = NULL;
132 }
133 if (g_oglBlackForegroundPen)
134 {
135 delete g_oglBlackForegroundPen;
136 g_oglBlackForegroundPen = NULL;
137 }
138
139 OGLCleanUpConstraintTypes();
140 }
141
142 wxFont *oglMatchFont(int point_size)
143 {
144 wxFont *font = wxTheFontList->FindOrCreateFont(point_size, wxSWISS, wxNORMAL, wxNORMAL);
145 #if 0
146 switch (point_size)
147 {
148 case 4:
149 font = swiss_font_4;
150 break;
151 case 6:
152 font = swiss_font_6;
153 break;
154 case 8:
155 font = swiss_font_8;
156 break;
157 case 12:
158 font = swiss_font_12;
159 break;
160 case 14:
161 font = swiss_font_14;
162 break;
163 case 18:
164 font = swiss_font_18;
165 break;
166 case 24:
167 font = swiss_font_24;
168 break;
169 default:
170 case 10:
171 font = swiss_font_10;
172 break;
173 }
174 #endif
175 return font;
176 }
177
178 int FontSizeDialog(wxFrame *parent, int old_size)
179 {
180 if (old_size <= 0)
181 old_size = 10;
182 char buf[40];
183 sprintf(buf, "%d", old_size);
184 wxString ans = wxGetTextFromUser("Enter point size", "Font size", buf, parent);
185 if (ans == "")
186 return 0;
187
188 int new_size = atoi(ans);
189 if ((new_size <= 0) || (new_size > 40))
190 {
191 wxMessageBox("Invalid point size!", "Error", wxOK);
192 return 0;
193 }
194 return new_size;
195 /*
196 char *strings[8];
197 strings[0] = "4";
198 strings[1] = "6";
199 strings[2] = "8";
200 strings[3] = "10";
201 strings[4] = "12";
202 strings[5] = "14";
203 strings[6] = "18";
204 strings[7] = "24";
205 char *ans = wxGetSingleChoice("Choose", "Choose a font size", 8, strings, parent);
206 if (ans)
207 {
208 int size;
209 sscanf(ans, "%d", &size);
210 return oglMatchFont(size);
211 }
212 else return NULL;
213 */
214 }
215
216 // Centre a list of strings in the given box. xOffset and yOffset are the
217 // the positions that these lines should be relative to, and this might be
218 // the same as m_xpos, m_ypos, but might be zero if formatting from left-justifying.
219 void oglCentreText(wxDC& dc, wxList *text_list,
220 double m_xpos, double m_ypos, double width, double height,
221 int formatMode)
222 {
223 int n = text_list->Number();
224
225 if (!text_list || (n == 0))
226 return;
227
228 // First, get maximum dimensions of box enclosing text
229
230 long char_height = 0;
231 long max_width = 0;
232 long current_width = 0;
233
234 // Store text extents for speed
235 double *widths = new double[n];
236
237 wxNode *current = text_list->First();
238 int i = 0;
239 while (current)
240 {
241 wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
242 dc.GetTextExtent(line->GetText(), &current_width, &char_height);
243 widths[i] = current_width;
244
245 if (current_width > max_width)
246 max_width = current_width;
247 current = current->Next();
248 i ++;
249 }
250
251 double max_height = n*char_height;
252
253 double xoffset, yoffset, xOffset, yOffset;
254
255 if (formatMode & FORMAT_CENTRE_VERT)
256 {
257 if (max_height < height)
258 yoffset = (double)(m_ypos - (height/2.0) + (height - max_height)/2.0);
259 else
260 yoffset = (double)(m_ypos - (height/2.0));
261 yOffset = m_ypos;
262 }
263 else
264 {
265 yoffset = 0.0;
266 yOffset = 0.0;
267 }
268
269 if (formatMode & FORMAT_CENTRE_HORIZ)
270 {
271 xoffset = (double)(m_xpos - width/2.0);
272 xOffset = m_xpos;
273 }
274 else
275 {
276 xoffset = 0.0;
277 xOffset = 0.0;
278 }
279
280 current = text_list->First();
281 i = 0;
282
283 while (current)
284 {
285 wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
286
287 double x;
288 if ((formatMode & FORMAT_CENTRE_HORIZ) && (widths[i] < width))
289 x = (double)((width - widths[i])/2.0 + xoffset);
290 else
291 x = xoffset;
292 double y = (double)(i*char_height + yoffset);
293
294 line->SetX( x - xOffset ); line->SetY( y - yOffset );
295 current = current->Next();
296 i ++;
297 }
298
299 delete widths;
300 }
301
302 // Centre a list of strings in the given box
303 void oglCentreTextNoClipping(wxDC& dc, wxList *text_list,
304 double m_xpos, double m_ypos, double width, double height)
305 {
306 int n = text_list->Number();
307
308 if (!text_list || (n == 0))
309 return;
310
311 // First, get maximum dimensions of box enclosing text
312
313 long char_height = 0;
314 long max_width = 0;
315 long current_width = 0;
316
317 // Store text extents for speed
318 double *widths = new double[n];
319
320 wxNode *current = text_list->First();
321 int i = 0;
322 while (current)
323 {
324 wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
325 dc.GetTextExtent(line->GetText(), &current_width, &char_height);
326 widths[i] = current_width;
327
328 if (current_width > max_width)
329 max_width = current_width;
330 current = current->Next();
331 i ++;
332 }
333
334 double max_height = n*char_height;
335
336 double yoffset = (double)(m_ypos - (height/2.0) + (height - max_height)/2.0);
337
338 double xoffset = (double)(m_xpos - width/2.0);
339
340 current = text_list->First();
341 i = 0;
342
343 while (current)
344 {
345 wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
346
347 double x = (double)((width - widths[i])/2.0 + xoffset);
348 double y = (double)(i*char_height + yoffset);
349
350 line->SetX( x - m_xpos ); line->SetY( y - m_ypos );
351 current = current->Next();
352 i ++;
353 }
354 delete widths;
355 }
356
357 void oglGetCentredTextExtent(wxDC& dc, wxList *text_list,
358 double m_xpos, double m_ypos, double width, double height,
359 double *actual_width, double *actual_height)
360 {
361 int n = text_list->Number();
362
363 if (!text_list || (n == 0))
364 {
365 *actual_width = 0;
366 *actual_height = 0;
367 return;
368 }
369
370 // First, get maximum dimensions of box enclosing text
371
372 long char_height = 0;
373 long max_width = 0;
374 long current_width = 0;
375
376 wxNode *current = text_list->First();
377 int i = 0;
378 while (current)
379 {
380 wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
381 dc.GetTextExtent(line->GetText(), &current_width, &char_height);
382
383 if (current_width > max_width)
384 max_width = current_width;
385 current = current->Next();
386 i ++;
387 }
388
389 *actual_height = n*char_height;
390 *actual_width = max_width;
391 }
392
393 // Format a string to a list of strings that fit in the given box.
394 // Interpret %n and 10 or 13 as a new line.
395 wxStringList *oglFormatText(wxDC& dc, const wxString& text, double width, double height, int formatMode)
396 {
397 // First, parse the string into a list of words
398 wxStringList word_list;
399
400 // Make new lines into NULL strings at this point
401 int i = 0; int j = 0; int len = strlen(text);
402 char word[200]; word[0] = 0;
403 bool end_word = FALSE; bool new_line = FALSE;
404 while (i < len)
405 {
406 switch (text[i])
407 {
408 case '%':
409 {
410 i ++;
411 if (i == len)
412 { word[j] = '%'; j ++; }
413 else
414 {
415 if (text[i] == 'n')
416 { new_line = TRUE; end_word = TRUE; i++; }
417 else
418 { word[j] = '%'; j ++; word[j] = text[i]; j ++; i ++; }
419 }
420 break;
421 }
422 case 10:
423 {
424 new_line = TRUE; end_word = TRUE; i++;
425 break;
426 }
427 case 13:
428 {
429 new_line = TRUE; end_word = TRUE; i++;
430 }
431 case ' ':
432 {
433 end_word = TRUE;
434 i ++;
435 break;
436 }
437 default:
438 {
439 word[j] = text[i];
440 j ++; i ++;
441 break;
442 }
443 }
444 if (i == len) end_word = TRUE;
445 if (end_word)
446 {
447 word[j] = 0;
448 j = 0;
449 word_list.Append((wxObject *)copystring(word));
450 end_word = FALSE;
451 }
452 if (new_line)
453 {
454 word_list.Append((wxObject *)NULL);
455 new_line = FALSE;
456 }
457 }
458 // Now, make a list of strings which can fit in the box
459 wxStringList *string_list = new wxStringList;
460
461 char buffer[400];
462 buffer[0] = 0;
463 wxNode *node = word_list.First();
464 long x, y;
465
466 while (node)
467 {
468 wxString oldBuffer(buffer);
469
470 char *s = (char *)node->Data();
471 if (!s)
472 {
473 // FORCE NEW LINE
474 if (strlen(buffer) > 0)
475 string_list->Add(buffer);
476
477 buffer[0] = 0;
478 }
479 else
480 {
481 if (buffer[0] != 0)
482 strcat(buffer, " ");
483
484 strcat(buffer, s);
485 dc.GetTextExtent(buffer, &x, &y);
486
487 // Don't fit within the bounding box if we're fitting shape to contents
488 if ((x > width) && !(formatMode & FORMAT_SIZE_TO_CONTENTS))
489 {
490 // Deal with first word being wider than box
491 if (oldBuffer.Length() > 0)
492 string_list->Add(oldBuffer);
493
494 buffer[0] = 0;
495 strcat(buffer, s);
496 }
497 }
498
499 node = node->Next();
500 }
501 if (buffer[0] != 0)
502 string_list->Add(buffer);
503
504 return string_list;
505 }
506
507 void oglDrawFormattedText(wxDC& dc, wxList *text_list,
508 double m_xpos, double m_ypos, double width, double height,
509 int formatMode)
510 {
511 double xoffset, yoffset;
512 if (formatMode & FORMAT_CENTRE_HORIZ)
513 xoffset = m_xpos;
514 else
515 xoffset = (double)(m_xpos - (width / 2.0));
516
517 if (formatMode & FORMAT_CENTRE_VERT)
518 yoffset = m_ypos;
519 else
520 yoffset = (double)(m_ypos - (height / 2.0));
521
522 dc.SetClippingRegion(
523 (double)(m_xpos - width/2.0), (double)(m_ypos - height/2.0),
524 (double)width, (double)height);
525
526 wxNode *current = text_list->First();
527 while (current)
528 {
529 wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
530
531 dc.DrawText(line->GetText(), WXROUND(xoffset + line->GetX()), WXROUND(yoffset + line->GetY()));
532 current = current->Next();
533 }
534
535 dc.DestroyClippingRegion();
536 }
537
538 /*
539 * Find centroid given list of points comprising polyline
540 *
541 */
542
543 void oglFindPolylineCentroid(wxList *points, double *x, double *y)
544 {
545 double xcount = 0;
546 double ycount = 0;
547
548 wxNode *node = points->First();
549 while (node)
550 {
551 wxRealPoint *point = (wxRealPoint *)node->Data();
552 xcount += point->x;
553 ycount += point->y;
554 node = node->Next();
555 }
556
557 *x = (xcount/points->Number());
558 *y = (ycount/points->Number());
559 }
560
561 /*
562 * Check that (x1, y1) -> (x2, y2) hits (x3, y3) -> (x4, y4).
563 * If so, ratio1 gives the proportion along the first line
564 * that the intersection occurs (or something like that).
565 * Used by functions below.
566 *
567 */
568 void oglCheckLineIntersection(double x1, double y1, double x2, double y2,
569 double x3, double y3, double x4, double y4,
570 double *ratio1, double *ratio2)
571 {
572 double denominator_term = (y4 - y3)*(x2 - x1) - (y2 - y1)*(x4 - x3);
573 double numerator_term = (x3 - x1)*(y4 - y3) + (x4 - x3)*(y1 - y3);
574
575 double line_constant;
576 double length_ratio = 1.0;
577 double k_line = 1.0;
578
579 // Check for parallel lines
580 if ((denominator_term < 0.005) && (denominator_term > -0.005))
581 line_constant = -1.0;
582 else
583 line_constant = numerator_term/denominator_term;
584
585 // Check for intersection
586 if ((line_constant < 1.0) && (line_constant > 0.0))
587 {
588 // Now must check that other line hits
589 if (((y4 - y3) < 0.005) && ((y4 - y3) > -0.005))
590 k_line = ((x1 - x3) + line_constant*(x2 - x1))/(x4 - x3);
591 else
592 k_line = ((y1 - y3) + line_constant*(y2 - y1))/(y4 - y3);
593
594 if ((k_line >= 0.0) && (k_line < 1.0))
595 length_ratio = line_constant;
596 else
597 k_line = 1.0;
598 }
599 *ratio1 = length_ratio;
600 *ratio2 = k_line;
601 }
602
603 /*
604 * Find where (x1, y1) -> (x2, y2) hits one of the lines in xvec, yvec.
605 * (*x3, *y3) is the point where it hits.
606 *
607 */
608 void oglFindEndForPolyline(double n, double xvec[], double yvec[],
609 double x1, double y1, double x2, double y2, double *x3, double *y3)
610 {
611 int i;
612 double lastx = xvec[0];
613 double lasty = yvec[0];
614
615 double min_ratio = 1.0;
616 double line_ratio;
617 double other_ratio;
618
619 for (i = 1; i < n; i++)
620 {
621 oglCheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[i], yvec[i],
622 &line_ratio, &other_ratio);
623 lastx = xvec[i];
624 lasty = yvec[i];
625
626 if (line_ratio < min_ratio)
627 min_ratio = line_ratio;
628 }
629
630 // Do last (implicit) line if last and first doubles are not identical
631 if (!(xvec[0] == lastx && yvec[0] == lasty))
632 {
633 oglCheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[0], yvec[0],
634 &line_ratio, &other_ratio);
635
636 if (line_ratio < min_ratio)
637 min_ratio = line_ratio;
638 }
639
640 *x3 = (x1 + (x2 - x1)*min_ratio);
641 *y3 = (y1 + (y2 - y1)*min_ratio);
642
643 }
644
645 /*
646 * Find where the line hits the box.
647 *
648 */
649
650 void oglFindEndForBox(double width, double height,
651 double x1, double y1, // Centre of box (possibly)
652 double x2, double y2, // other end of line
653 double *x3, double *y3) // End on box edge
654 {
655 double xvec[5];
656 double yvec[5];
657
658 xvec[0] = (double)(x1 - width/2.0);
659 yvec[0] = (double)(y1 - height/2.0);
660 xvec[1] = (double)(x1 - width/2.0);
661 yvec[1] = (double)(y1 + height/2.0);
662 xvec[2] = (double)(x1 + width/2.0);
663 yvec[2] = (double)(y1 + height/2.0);
664 xvec[3] = (double)(x1 + width/2.0);
665 yvec[3] = (double)(y1 - height/2.0);
666 xvec[4] = (double)(x1 - width/2.0);
667 yvec[4] = (double)(y1 - height/2.0);
668
669 oglFindEndForPolyline(5, xvec, yvec, x2, y2, x1, y1, x3, y3);
670 }
671
672 /*
673 * Find where the line hits the circle.
674 *
675 */
676
677 void oglFindEndForCircle(double radius,
678 double x1, double y1, // Centre of circle
679 double x2, double y2, // Other end of line
680 double *x3, double *y3)
681 {
682 double H = (double)sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
683
684 if (H == 0.0)
685 {
686 *x3 = x1;
687 *y3 = y1;
688 }
689 else
690 {
691 *y3 = radius * (y2 - y1)/H + y1;
692 *x3 = radius * (x2 - x1)/H + x1;
693 }
694 }
695
696 /*
697 * Given the line (x1, y1) -> (x2, y2), and an arrow size of given length and width,
698 * return the position of the tip of the arrow and the left and right vertices of the arrow.
699 *
700 */
701
702 void oglGetArrowPoints(double x1, double y1, double x2, double y2,
703 double length, double width,
704 double *tip_x, double *tip_y,
705 double *side1_x, double *side1_y,
706 double *side2_x, double *side2_y)
707 {
708 double l = (double)sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
709
710 if (l < 0.01)
711 l = (double) 0.01;
712
713 double i_bar = (x2 - x1)/l;
714 double j_bar = (y2 - y1)/l;
715
716 double x3 = (- length*i_bar) + x2;
717 double y3 = (- length*j_bar) + y2;
718
719 *side1_x = width*(-j_bar) + x3;
720 *side1_y = width*i_bar + y3;
721
722 *side2_x = -width*(-j_bar) + x3;
723 *side2_y = -width*i_bar + y3;
724
725 *tip_x = x2; *tip_y = y2;
726 }
727
728 /*
729 * Given an ellipse and endpoints of a line, returns the point at which
730 * the line touches the ellipse in values x4, y4.
731 * This function assumes that the centre of the ellipse is at x1, y1, and the
732 * ellipse has a width of width1 and a height of height1. It also assumes you are
733 * wanting to draw an arc FROM point x2, y2 TOWARDS point x3, y3.
734 * This function calculates the x,y coordinates of the intersection point of
735 * the arc with the ellipse.
736 * Author: Ian Harrison
737 */
738
739 void oglDrawArcToEllipse(double x1, double y1, double width1, double height1, double x2, double y2, double x3, double y3,
740 double *x4, double *y4)
741 {
742 double a1 = (double)(width1/2.0);
743 double b1 = (double)(height1/2.0);
744
745 // These are required to give top left x and y coordinates for DrawEllipse
746 // double top_left_x1 = (double)(x1 - a1);
747 // double top_left_y1 = (double)(y1 - b1);
748 /*
749 // Check for vertical line
750 if (fabs(x2 - x3) < 0.05)
751 {
752 *x4 = x3;
753 if (y2 < y3)
754 *y4 = (double)(y1 - b1);
755 else
756 *y4 = (double)(y1 + b1);
757 return;
758 }
759 */
760 // Check that x2 != x3
761 if (fabs(x2 - x3) < 0.05)
762 {
763 *x4 = x2;
764 if (y3 > y2)
765 *y4 = (double)(y1 - sqrt((b1*b1 - (((x2-x1)*(x2-x1))*(b1*b1)/(a1*a1)))));
766 else
767 *y4 = (double)(y1 + sqrt((b1*b1 - (((x2-x1)*(x2-x1))*(b1*b1)/(a1*a1)))));
768 return;
769 }
770
771 // Calculate the x and y coordinates of the point where arc intersects ellipse
772
773 double A, B, C, D, E, F, G, H, K;
774 double ellipse1_x, ellipse1_y;
775
776 A = (double)(1/(a1 * a1));
777 B = (double)((y3 - y2) * (y3 - y2)) / ((x3 - x2) * (x3 - x2) * b1 * b1);
778 C = (double)(2 * (y3 - y2) * (y2 - y1)) / ((x3 - x2) * b1 * b1);
779 D = (double)((y2 - y1) * (y2 - y1)) / (b1 * b1);
780 E = (double)(A + B);
781 F = (double)(C - (2 * A * x1) - (2 * B * x2));
782 G = (double)((A * x1 * x1) + (B * x2 * x2) - (C * x2) + D - 1);
783 H = (double)((y3 - y2) / (x3 - x2));
784 K = (double)((F * F) - (4 * E * G));
785
786 if (K >= 0)
787 // In this case the line intersects the ellipse, so calculate intersection
788 {
789 if(x2 >= x1)
790 {
791 ellipse1_x = (double)(((F * -1) + sqrt(K)) / (2 * E));
792 ellipse1_y = (double)((H * (ellipse1_x - x2)) + y2);
793 }
794 else
795 {
796 ellipse1_x = (double)(((F * -1) - sqrt(K)) / (2 * E));
797 ellipse1_y = (double)((H * (ellipse1_x - x2)) + y2);
798 }
799 }
800 else
801 // in this case, arc does not intersect ellipse, so just draw arc
802 {
803 ellipse1_x = x3;
804 ellipse1_y = y3;
805 }
806 *x4 = ellipse1_x;
807 *y4 = ellipse1_y;
808
809 /*
810 // Draw a little circle (radius = 2) at the end of the arc where it hits
811 // the ellipse .
812
813 double circle_x = ellipse1_x - 2.0;
814 double circle_y = ellipse1_y - 2.0;
815 m_canvas->DrawEllipse(circle_x, circle_y, 4.0, 4.0);
816 */
817 }
818
819 // Update a list item from a list of strings
820 void UpdateListBox(wxListBox *item, wxList *list)
821 {
822 item->Clear();
823 if (!list)
824 return;
825
826 wxNode *node = list->First();
827 while (node)
828 {
829 char *s = (char *)node->Data();
830 item->Append(s);
831 node = node->Next();
832 }
833 }
834
835 bool oglRoughlyEqual(double val1, double val2, double tol)
836 {
837 return ( (val1 < (val2 + tol)) && (val1 > (val2 - tol)) &&
838 (val2 < (val1 + tol)) && (val2 > (val1 - tol)));
839 }
840
841 /*
842 * Hex<->Dec conversion
843 */
844
845 // Array used in DecToHex conversion routine.
846 static char sg_HexArray[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
847 'C', 'D', 'E', 'F' };
848
849 // Convert 2-digit hex number to decimal
850 unsigned int oglHexToDec(char* buf)
851 {
852 int firstDigit, secondDigit;
853
854 if (buf[0] >= 'A')
855 firstDigit = buf[0] - 'A' + 10;
856 else
857 firstDigit = buf[0] - '0';
858
859 if (buf[1] >= 'A')
860 secondDigit = buf[1] - 'A' + 10;
861 else
862 secondDigit = buf[1] - '0';
863
864 return firstDigit * 16 + secondDigit;
865 }
866
867 // Convert decimal integer to 2-character hex string
868 void oglDecToHex(unsigned int dec, char *buf)
869 {
870 int firstDigit = (int)(dec/16.0);
871 int secondDigit = (int)(dec - (firstDigit*16.0));
872 buf[0] = sg_HexArray[firstDigit];
873 buf[1] = sg_HexArray[secondDigit];
874 buf[2] = 0;
875 }
876
877 // 3-digit hex to wxColour
878 wxColour oglHexToColour(const wxString& hex)
879 {
880 if (hex.Length() == 6)
881 {
882 char buf[7];
883 strncpy(buf, hex, 7);
884 unsigned int r = oglHexToDec((char *)buf);
885 unsigned int g = oglHexToDec((char *)(buf+2));
886 unsigned int b = oglHexToDec((char *)(buf+4));
887 return wxColour(r, g, b);
888 }
889 else
890 return wxColour(0,0,0);
891 }
892
893 // RGB to 3-digit hex
894 wxString oglColourToHex(const wxColour& colour)
895 {
896 char buf[7];
897 unsigned int red = colour.Red();
898 unsigned int green = colour.Green();
899 unsigned int blue = colour.Blue();
900
901 oglDecToHex(red, buf);
902 oglDecToHex(green, buf+2);
903 oglDecToHex(blue, buf+4);
904
905 return wxString(buf);
906 }
907
908