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