]> git.saurik.com Git - wxWidgets.git/blame - utils/ogl/src/misc.cpp
Added SetFont to most controls and controls sample
[wxWidgets.git] / utils / ogl / src / misc.cpp
CommitLineData
0fc1a713
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".
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
42cfaf8c
JS
48wxFont* g_oglNormalFont;
49wxPen* g_oglBlackPen;
50wxPen* g_oglWhiteBackgroundPen;
51wxPen* g_oglTransparentPen;
52wxBrush* g_oglWhiteBackgroundBrush;
53wxPen* g_oglBlackForegroundPen;
54wxCursor* g_oglBullseyeCursor = NULL;
0fc1a713 55
42cfaf8c 56char* oglBuffer = NULL;
0fc1a713 57
42cfaf8c 58wxList oglObjectCopyMapping(wxKEY_INTEGER);
0fc1a713
JS
59
60void wxOGLInitialize()
61{
42cfaf8c 62 g_oglBullseyeCursor = new wxCursor(wxCURSOR_BULLSEYE);
0fc1a713 63
34138703 64 g_oglNormalFont = new wxFont(10, wxSWISS, wxNORMAL, wxNORMAL);
0fc1a713 65
42cfaf8c 66 g_oglBlackPen = new wxPen("BLACK", 1, wxSOLID);
0fc1a713 67
42cfaf8c
JS
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);
0fc1a713
JS
72
73 OGLInitializeConstraintTypes();
74
75 // Initialize big buffer used when writing images
42cfaf8c 76 oglBuffer = new char[3000];
0fc1a713
JS
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
89void wxOGLCleanUp()
90{
42cfaf8c 91 if (oglBuffer)
5de76427 92 {
42cfaf8c
JS
93 delete[] oglBuffer;
94 oglBuffer = NULL;
5de76427 95 }
42cfaf8c 96 oglBuffer = NULL;
5de76427
JS
97 if (oglPopupDivisionMenu)
98 {
99 delete oglPopupDivisionMenu;
100 oglPopupDivisionMenu = NULL;
101 }
42cfaf8c
JS
102 if (g_oglBullseyeCursor)
103 {
104 delete g_oglBullseyeCursor;
105 g_oglBullseyeCursor = NULL;
106 }
107
5de76427
JS
108 if (g_oglNormalFont)
109 {
110 delete g_oglNormalFont;
111 g_oglNormalFont = NULL;
112 }
42cfaf8c 113 if (g_oglBlackPen)
5de76427 114 {
42cfaf8c
JS
115 delete g_oglBlackPen;
116 g_oglBlackPen = NULL;
5de76427 117 }
42cfaf8c 118 if (g_oglWhiteBackgroundPen)
5de76427 119 {
42cfaf8c
JS
120 delete g_oglWhiteBackgroundPen;
121 g_oglWhiteBackgroundPen = NULL;
5de76427 122 }
42cfaf8c 123 if (g_oglTransparentPen)
5de76427 124 {
42cfaf8c
JS
125 delete g_oglTransparentPen;
126 g_oglTransparentPen = NULL;
5de76427 127 }
42cfaf8c 128 if (g_oglWhiteBackgroundBrush)
5de76427 129 {
42cfaf8c
JS
130 delete g_oglWhiteBackgroundBrush;
131 g_oglWhiteBackgroundBrush = NULL;
5de76427 132 }
42cfaf8c 133 if (g_oglBlackForegroundPen)
5de76427 134 {
42cfaf8c
JS
135 delete g_oglBlackForegroundPen;
136 g_oglBlackForegroundPen = NULL;
5de76427
JS
137 }
138
139 OGLCleanUpConstraintTypes();
0fc1a713
JS
140}
141
42cfaf8c 142wxFont *oglMatchFont(int point_size)
0fc1a713
JS
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
178int 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);
42cfaf8c 210 return oglMatchFont(size);
0fc1a713
JS
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.
42cfaf8c
JS
219void oglCentreText(wxDC& dc, wxList *text_list,
220 double m_xpos, double m_ypos, double width, double height,
0fc1a713
JS
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
42cfaf8c
JS
230 long char_height = 0;
231 long max_width = 0;
232 long current_width = 0;
0fc1a713
JS
233
234 // Store text extents for speed
42cfaf8c 235 double *widths = new double[n];
0fc1a713
JS
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
42cfaf8c 251 double max_height = n*char_height;
0fc1a713 252
42cfaf8c 253 double xoffset, yoffset, xOffset, yOffset;
0fc1a713
JS
254
255 if (formatMode & FORMAT_CENTRE_VERT)
256 {
257 if (max_height < height)
42cfaf8c 258 yoffset = (double)(m_ypos - (height/2.0) + (height - max_height)/2.0);
0fc1a713 259 else
42cfaf8c 260 yoffset = (double)(m_ypos - (height/2.0));
0fc1a713
JS
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 {
42cfaf8c 271 xoffset = (double)(m_xpos - width/2.0);
0fc1a713
JS
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
42cfaf8c 287 double x;
0fc1a713 288 if ((formatMode & FORMAT_CENTRE_HORIZ) && (widths[i] < width))
42cfaf8c 289 x = (double)((width - widths[i])/2.0 + xoffset);
0fc1a713
JS
290 else
291 x = xoffset;
42cfaf8c 292 double y = (double)(i*char_height + yoffset);
0fc1a713
JS
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
42cfaf8c
JS
303void oglCentreTextNoClipping(wxDC& dc, wxList *text_list,
304 double m_xpos, double m_ypos, double width, double height)
0fc1a713
JS
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
42cfaf8c
JS
313 long char_height = 0;
314 long max_width = 0;
315 long current_width = 0;
0fc1a713
JS
316
317 // Store text extents for speed
42cfaf8c 318 double *widths = new double[n];
0fc1a713
JS
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
42cfaf8c 334 double max_height = n*char_height;
0fc1a713 335
42cfaf8c 336 double yoffset = (double)(m_ypos - (height/2.0) + (height - max_height)/2.0);
0fc1a713 337
42cfaf8c 338 double xoffset = (double)(m_xpos - width/2.0);
0fc1a713
JS
339
340 current = text_list->First();
341 i = 0;
342
343 while (current)
344 {
345 wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
346
42cfaf8c
JS
347 double x = (double)((width - widths[i])/2.0 + xoffset);
348 double y = (double)(i*char_height + yoffset);
0fc1a713
JS
349
350 line->SetX( x - m_xpos ); line->SetY( y - m_ypos );
351 current = current->Next();
352 i ++;
353 }
354 delete widths;
355}
356
42cfaf8c
JS
357void oglGetCentredTextExtent(wxDC& dc, wxList *text_list,
358 double m_xpos, double m_ypos, double width, double height,
359 double *actual_width, double *actual_height)
0fc1a713
JS
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
42cfaf8c
JS
372 long char_height = 0;
373 long max_width = 0;
374 long current_width = 0;
0fc1a713
JS
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.
42cfaf8c 395wxStringList *oglFormatText(wxDC& dc, const wxString& text, double width, double height, int formatMode)
0fc1a713
JS
396{
397 // First, parse the string into a list of words
42cfaf8c 398 wxStringList word_list;
0fc1a713
JS
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
42cfaf8c 459 wxStringList *string_list = new wxStringList;
0fc1a713
JS
460
461 char buffer[400];
462 buffer[0] = 0;
463 wxNode *node = word_list.First();
42cfaf8c 464 long x, y;
0fc1a713
JS
465
466 while (node)
467 {
42cfaf8c 468 wxString oldBuffer(buffer);
0fc1a713
JS
469
470 char *s = (char *)node->Data();
471 if (!s)
472 {
473 // FORCE NEW LINE
42cfaf8c
JS
474 if (strlen(buffer) > 0)
475 string_list->Add(buffer);
0fc1a713
JS
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
42cfaf8c
JS
491 if (oldBuffer.Length() > 0)
492 string_list->Add(oldBuffer);
0fc1a713
JS
493
494 buffer[0] = 0;
495 strcat(buffer, s);
0fc1a713 496 }
0fc1a713
JS
497 }
498
499 node = node->Next();
500 }
501 if (buffer[0] != 0)
42cfaf8c 502 string_list->Add(buffer);
0fc1a713
JS
503
504 return string_list;
505}
506
42cfaf8c
JS
507void oglDrawFormattedText(wxDC& dc, wxList *text_list,
508 double m_xpos, double m_ypos, double width, double height,
0fc1a713
JS
509 int formatMode)
510{
42cfaf8c 511 double xoffset, yoffset;
0fc1a713
JS
512 if (formatMode & FORMAT_CENTRE_HORIZ)
513 xoffset = m_xpos;
514 else
42cfaf8c 515 xoffset = (double)(m_xpos - (width / 2.0));
0fc1a713
JS
516
517 if (formatMode & FORMAT_CENTRE_VERT)
518 yoffset = m_ypos;
519 else
42cfaf8c 520 yoffset = (double)(m_ypos - (height / 2.0));
0fc1a713
JS
521
522 dc.SetClippingRegion(
42cfaf8c
JS
523 (double)(m_xpos - width/2.0), (double)(m_ypos - height/2.0),
524 (double)width, (double)height);
0fc1a713
JS
525
526 wxNode *current = text_list->First();
527 while (current)
528 {
529 wxShapeTextLine *line = (wxShapeTextLine *)current->Data();
530
42cfaf8c 531 dc.DrawText(line->GetText(), WXROUND(xoffset + line->GetX()), WXROUND(yoffset + line->GetY()));
0fc1a713
JS
532 current = current->Next();
533 }
534
535 dc.DestroyClippingRegion();
536}
537
538/*
539 * Find centroid given list of points comprising polyline
540 *
541 */
542
42cfaf8c 543void oglFindPolylineCentroid(wxList *points, double *x, double *y)
0fc1a713 544{
42cfaf8c
JS
545 double xcount = 0;
546 double ycount = 0;
0fc1a713
JS
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 */
42cfaf8c
JS
568void oglCheckLineIntersection(double x1, double y1, double x2, double y2,
569 double x3, double y3, double x4, double y4,
570 double *ratio1, double *ratio2)
0fc1a713 571{
42cfaf8c
JS
572 double denominator_term = (y4 - y3)*(x2 - x1) - (y2 - y1)*(x4 - x3);
573 double numerator_term = (x3 - x1)*(y4 - y3) + (x4 - x3)*(y1 - y3);
0fc1a713 574
42cfaf8c
JS
575 double line_constant;
576 double length_ratio = 1.0;
577 double k_line = 1.0;
0fc1a713
JS
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 */
42cfaf8c
JS
608void oglFindEndForPolyline(double n, double xvec[], double yvec[],
609 double x1, double y1, double x2, double y2, double *x3, double *y3)
0fc1a713
JS
610{
611 int i;
42cfaf8c
JS
612 double lastx = xvec[0];
613 double lasty = yvec[0];
0fc1a713 614
42cfaf8c
JS
615 double min_ratio = 1.0;
616 double line_ratio;
617 double other_ratio;
0fc1a713
JS
618
619 for (i = 1; i < n; i++)
620 {
42cfaf8c 621 oglCheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[i], yvec[i],
0fc1a713
JS
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
42cfaf8c 630 // Do last (implicit) line if last and first doubles are not identical
0fc1a713
JS
631 if (!(xvec[0] == lastx && yvec[0] == lasty))
632 {
42cfaf8c 633 oglCheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[0], yvec[0],
0fc1a713
JS
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
42cfaf8c
JS
650void 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
0fc1a713 654{
42cfaf8c
JS
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);
0fc1a713
JS
670}
671
672/*
673 * Find where the line hits the circle.
674 *
675 */
676
42cfaf8c
JS
677void 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)
0fc1a713 681{
42cfaf8c 682 double H = (double)sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
0fc1a713
JS
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
42cfaf8c
JS
702void 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)
0fc1a713 707{
42cfaf8c 708 double l = (double)sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
0fc1a713
JS
709
710 if (l < 0.01)
42cfaf8c 711 l = (double) 0.01;
0fc1a713 712
42cfaf8c
JS
713 double i_bar = (x2 - x1)/l;
714 double j_bar = (y2 - y1)/l;
0fc1a713 715
42cfaf8c
JS
716 double x3 = (- length*i_bar) + x2;
717 double y3 = (- length*j_bar) + y2;
0fc1a713
JS
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
42cfaf8c
JS
739void oglDrawArcToEllipse(double x1, double y1, double width1, double height1, double x2, double y2, double x3, double y3,
740 double *x4, double *y4)
0fc1a713 741{
42cfaf8c
JS
742 double a1 = (double)(width1/2.0);
743 double b1 = (double)(height1/2.0);
0fc1a713
JS
744
745 // These are required to give top left x and y coordinates for DrawEllipse
42cfaf8c
JS
746// double top_left_x1 = (double)(x1 - a1);
747// double top_left_y1 = (double)(y1 - b1);
0fc1a713
JS
748/*
749 // Check for vertical line
750 if (fabs(x2 - x3) < 0.05)
751 {
752 *x4 = x3;
753 if (y2 < y3)
42cfaf8c 754 *y4 = (double)(y1 - b1);
0fc1a713 755 else
42cfaf8c 756 *y4 = (double)(y1 + b1);
0fc1a713
JS
757 return;
758 }
759*/
760 // Check that x2 != x3
761 if (fabs(x2 - x3) < 0.05)
762 {
763 *x4 = x2;
764 if (y3 > y2)
42cfaf8c 765 *y4 = (double)(y1 - sqrt((b1*b1 - (((x2-x1)*(x2-x1))*(b1*b1)/(a1*a1)))));
0fc1a713 766 else
42cfaf8c 767 *y4 = (double)(y1 + sqrt((b1*b1 - (((x2-x1)*(x2-x1))*(b1*b1)/(a1*a1)))));
0fc1a713
JS
768 return;
769 }
770
771 // Calculate the x and y coordinates of the point where arc intersects ellipse
772
42cfaf8c
JS
773 double A, B, C, D, E, F, G, H, K;
774 double ellipse1_x, ellipse1_y;
0fc1a713 775
42cfaf8c
JS
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));
0fc1a713
JS
785
786 if (K >= 0)
787 // In this case the line intersects the ellipse, so calculate intersection
788 {
789 if(x2 >= x1)
790 {
42cfaf8c
JS
791 ellipse1_x = (double)(((F * -1) + sqrt(K)) / (2 * E));
792 ellipse1_y = (double)((H * (ellipse1_x - x2)) + y2);
0fc1a713
JS
793 }
794 else
795 {
42cfaf8c
JS
796 ellipse1_x = (double)(((F * -1) - sqrt(K)) / (2 * E));
797 ellipse1_y = (double)((H * (ellipse1_x - x2)) + y2);
0fc1a713
JS
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
42cfaf8c
JS
813 double circle_x = ellipse1_x - 2.0;
814 double circle_y = ellipse1_y - 2.0;
0fc1a713
JS
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
820void 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
42cfaf8c
JS
835bool 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
34138703
JS
841/*
842 * Hex<->Dec conversion
843 */
844
845// Array used in DecToHex conversion routine.
846static 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
850unsigned 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
868void 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
878wxColour 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
894wxString 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
0fc1a713 908