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