OpenCPN Partial API docs
Loading...
Searching...
No Matches
dial.cpp
1/******************************************************************************
2 * $Id: dial.cpp, v1.0 2010/08/05 SethDart Exp $
3 *
4 * Project: OpenCPN
5 * Purpose: Dashboard Plugin
6 * Author: Jean-Eudes Onfray
7 * (Inspired by original work from Andreas Heiming)
8 *
9 ***************************************************************************
10 * Copyright (C) 2010 by David S. Register *
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 * This program is distributed in the hope that it will be useful, *
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20 * GNU General Public License for more details. *
21 * *
22 * You should have received a copy of the GNU General Public License *
23 * along with this program; if not, write to the *
24 * Free Software Foundation, Inc., *
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
26 ***************************************************************************
27 */
28
29#include <wx/wxprec.h>
30
31#ifndef WX_PRECOMP
32#include <wx/wx.h>
33#endif // precompiled headers
34
35#include "dial.h"
36
37#ifdef __BORLANDC__
38#pragma hdrstop
39#endif
40
41#include <cmath>
42#include "wx/tokenzr.h"
43
44#ifdef __OCPN__ANDROID__
45#include "qdebug.h"
46#endif
47
48double rad2deg(double angle) { return angle * 180.0 / M_PI; }
49double deg2rad(double angle) { return angle / 180.0 * M_PI; }
50
51DashboardInstrument_Dial::DashboardInstrument_Dial(
52 wxWindow* parent, wxWindowID id, wxString title,
53 InstrumentProperties* Properties, DASH_CAP cap_flag, int s_angle,
54 int r_angle, int s_value, int e_value)
55 : DashboardInstrument(parent, id, title, cap_flag, Properties) {
56 m_AngleStart = s_angle;
57 m_AngleRange = r_angle;
58 m_MainValueMin = s_value;
59 m_MainValueMax = e_value;
60 m_MainValueCap = cap_flag;
61
62 m_MainValue = s_value;
63 m_ExtraValue = 0;
64 m_MainValueFormat = "%d";
65 m_MainValueUnit = "";
66 m_MainValueOption = DIAL_POSITION_NONE;
67 m_ExtraValueFormat = "%d";
68 m_ExtraValueUnit = "";
69 m_ExtraValueOption = DIAL_POSITION_NONE;
70 m_MarkerOption = DIAL_MARKER_SIMPLE;
71 m_MarkerStep = 1;
72 m_LabelStep = 1;
73 m_MarkerOffset = 1;
74 m_LabelOption = DIAL_LABEL_HORIZONTAL;
75}
76
77wxSize DashboardInstrument_Dial::GetSize(int orient, wxSize hint) {
78 InitTitleSize();
79 InitTitleAndDataPosition(DefaultWidth);
80 int w;
81 if (orient == wxHORIZONTAL) {
82 w = wxMax(hint.y, GetFullHeight(DefaultWidth));
83 return wxSize(w - m_TitleHeight, w);
84 } else {
85 w = wxMax(hint.x, DefaultWidth);
86 return wxSize(w, GetFullHeight(w));
87 }
88}
89
90void DashboardInstrument_Dial::SetData(DASH_CAP st, double data,
91 wxString unit) {
92 if (st == m_MainValueCap) {
93 m_MainValue = data;
94 m_MainValueUnit = unit;
95 } else if (st == m_ExtraValueCap) {
96 m_ExtraValue = data;
97 m_ExtraValueUnit = unit;
98 }
99 Refresh();
100}
101
102void DashboardInstrument_Dial::Draw(wxGCDC* bdc) {
103 if (m_Properties) {
104 wxBrush b1(
105 GetColourSchemeBackgroundColour(m_Properties->m_DataBackgroundColour));
106 bdc->SetBackground(b1);
107 } else {
108 wxColour c1;
109 GetGlobalColor("DASHB", &c1);
110 wxBrush b1(c1);
111 bdc->SetBackground(b1);
112 }
113 bdc->Clear();
114
115 wxSize size = GetClientSize();
116 m_cx = size.x / 2;
117 int availableHeight = GetDataBottom(size.y) - m_DataTop;
118 InitTitleAndDataPosition(availableHeight);
119 availableHeight -= 6;
120 int width, height;
121 wxFont f;
122 if (m_Properties)
123 f = m_Properties->m_LabelFont.GetChosenFont();
124 else
125 f = g_pFontLabel->GetChosenFont();
126 bdc->GetTextExtent("000", &width, &height, 0, 0, &f);
127 m_cy = m_DataTop + 2;
128 m_cy += availableHeight / 2;
129 m_radius = availableHeight / 2;
130
131 DrawFrame(bdc);
132 DrawLabels(bdc);
133 DrawMarkers(bdc);
134 DrawBackground(bdc);
135 DrawData(bdc, m_MainValue, m_MainValueUnit, m_MainValueFormat,
136 m_MainValueOption);
137 DrawData(bdc, m_ExtraValue, m_ExtraValueUnit, m_ExtraValueFormat,
138 m_ExtraValueOption);
139 DrawForeground(bdc);
140}
141
142void DashboardInstrument_Dial::DrawFrame(wxGCDC* dc) {
143 wxSize size = GetClientSize();
144 wxColour cl;
145 if (m_Properties) {
146 cl = GetColourSchemeBackgroundColour(m_Properties->m_TitleBackgroundColour);
147 } else {
148 GetGlobalColor("DASHL", &cl);
149 }
150 dc->SetTextForeground(cl);
151 dc->SetBrush(*wxTRANSPARENT_BRUSH);
152
153 int penwidth = 1 + size.x / 100;
154 wxPen pen(cl, penwidth, wxPENSTYLE_SOLID);
155
156 if (m_MarkerOption == DIAL_MARKER_REDGREENBAR) {
157 pen.SetWidth(penwidth * 2);
158 GetGlobalColor("DASHR", &cl);
159 pen.SetColour(cl);
160 dc->SetPen(pen);
161 double angle1 = deg2rad(270); // 305-ANGLE_OFFSET
162 double angle2 = deg2rad(90); // 55-ANGLE_OFFSET
163 int radi = m_radius - 1 - penwidth;
164 wxCoord x1 = m_cx + ((radi)*cos(angle1));
165 wxCoord y1 = m_cy + ((radi)*sin(angle1));
166 wxCoord x2 = m_cx + ((radi)*cos(angle2));
167 wxCoord y2 = m_cy + ((radi)*sin(angle2));
168 dc->DrawArc(x1, y1, x2, y2, m_cx, m_cy);
169
170 GetGlobalColor("DASHG", &cl);
171 pen.SetColour(cl);
172 dc->SetPen(pen);
173 angle1 = deg2rad(89); // 305-ANGLE_OFFSET
174 angle2 = deg2rad(271); // 55-ANGLE_OFFSET
175 x1 = m_cx + ((radi)*cos(angle1));
176 y1 = m_cy + ((radi)*sin(angle1));
177 x2 = m_cx + ((radi)*cos(angle2));
178 y2 = m_cy + ((radi)*sin(angle2));
179 dc->DrawArc(x1, y1, x2, y2, m_cx, m_cy);
180
181 // Some platforms have trouble with transparent pen.
182 // so we simply draw arcs for the outer ring.
183 GetGlobalColor("DASHF", &cl);
184 pen.SetWidth(penwidth);
185 pen.SetColour(cl);
186 dc->SetPen(pen);
187 angle1 = deg2rad(0);
188 angle2 = deg2rad(180);
189 radi = m_radius - 1;
190
191 x1 = m_cx + ((radi)*cos(angle1));
192 y1 = m_cy + ((radi)*sin(angle1));
193 x2 = m_cx + ((radi)*cos(angle2));
194 y2 = m_cy + ((radi)*sin(angle2));
195 dc->DrawArc(x1, y1, x2, y2, m_cx, m_cy);
196 dc->DrawArc(x2, y2, x1, y1, m_cx, m_cy);
197
198 } else {
199 GetGlobalColor("DASHF", &cl);
200 pen.SetColour(cl);
201 dc->SetPen(pen);
202 dc->DrawCircle(m_cx, m_cy, m_radius);
203 }
204}
205
206void DashboardInstrument_Dial::DrawMarkers(wxGCDC* dc) {
207 if (m_MarkerOption == DIAL_MARKER_NONE) return;
208
209 wxColour cl;
210 GetGlobalColor("DASHF", &cl);
211 int penwidth = GetClientSize().x / 100;
212 wxPen pen(cl, penwidth, wxPENSTYLE_SOLID);
213 dc->SetPen(pen);
214
215 int diff_angle = m_AngleStart + m_AngleRange - ANGLE_OFFSET;
216 // angle between markers
217 double abm = m_AngleRange * m_MarkerStep / (m_MainValueMax - m_MainValueMin);
218 // don't draw last value, it's already done as first
219 if (m_AngleRange == 360) diff_angle -= abm;
220
221 int offset = 0;
222 for (double angle = m_AngleStart - ANGLE_OFFSET; angle <= diff_angle;
223 angle += abm) {
224 if (m_MarkerOption == DIAL_MARKER_REDGREEN) {
225 int a = int(angle + ANGLE_OFFSET) % 360;
226 if (a > 180)
227 GetGlobalColor("DASHR", &cl);
228 else if ((a > 0) && (a < 180))
229 GetGlobalColor("DASHG", &cl);
230 else
231 GetGlobalColor("DASHF", &cl);
232
233 pen.SetColour(cl);
234 dc->SetPen(pen);
235 }
236
237 double size = 0.92;
238 if (offset % m_MarkerOffset) {
239 size = 0.96;
240 }
241 offset++;
242
243 dc->DrawLine(m_cx + ((m_radius - 1) * size * cos(deg2rad(angle))),
244 m_cy + ((m_radius - 1) * size * sin(deg2rad(angle))),
245 m_cx + ((m_radius - 1) * cos(deg2rad(angle))),
246 m_cy + ((m_radius - 1) * sin(deg2rad(angle))));
247 }
248 // We must reset pen color so following drawings are fine
249 if (m_MarkerOption == DIAL_MARKER_REDGREEN) {
250 GetGlobalColor("DASHF", &cl);
251 pen.SetStyle(wxPENSTYLE_SOLID);
252 pen.SetColour(cl);
253 dc->SetPen(pen);
254 }
255}
256
257void DashboardInstrument_Dial::DrawLabels(wxGCDC* dc) {
258 if (m_LabelOption == DIAL_LABEL_NONE) return;
259
260 wxPoint TextPoint;
261 wxPen pen;
262 wxColor cl;
263 GetGlobalColor("DASHF", &cl);
264
265 if (m_Properties) {
266 dc->SetFont(m_Properties->m_SmallFont.GetChosenFont());
267 dc->SetTextForeground(
268 GetColourSchemeFont(m_Properties->m_SmallFont.GetColour()));
269 } else {
270 dc->SetFont(g_pFontSmall->GetChosenFont());
271 dc->SetTextForeground(GetColourSchemeFont(g_pFontSmall->GetColour()));
272 }
273 int diff_angle = m_AngleStart + m_AngleRange - ANGLE_OFFSET;
274 // angle between markers
275 double abm = m_AngleRange * m_LabelStep / (m_MainValueMax - m_MainValueMin);
276 // don't draw last value, it's already done as first
277 if (m_AngleRange == 360) diff_angle -= abm;
278
279 int offset = 0;
280 int value = m_MainValueMin;
281 int width, height;
282 wxFont f;
283 for (double angle = m_AngleStart - ANGLE_OFFSET; angle <= diff_angle;
284 angle += abm) {
285 wxString label = (m_LabelArray.GetCount() ? m_LabelArray.Item(offset)
286 : wxString::Format("%d", value));
287 if (m_Properties)
288 f = m_Properties->m_SmallFont.GetChosenFont();
289 else
290 f = g_pFontSmall->GetChosenFont();
291 dc->GetTextExtent(label, &width, &height, 0, 0, &f);
292 double halfW = width / 2;
293 if (m_LabelOption == DIAL_LABEL_HORIZONTAL) {
294 double halfH = height / 2;
295 // double delta = sqrt(width*width+height*height);
296 double delta = sqrt(halfW * halfW + halfH * halfH);
297 TextPoint.x =
298 m_cx + ((m_radius * 0.90) - delta) * cos(deg2rad(angle)) - halfW;
299 TextPoint.y =
300 m_cy + ((m_radius * 0.90) - delta) * sin(deg2rad(angle)) - halfH;
301 dc->DrawText(label, TextPoint);
302
303 } else if (m_LabelOption == DIAL_LABEL_ROTATED) {
304 // The coordinates of dc->DrawRotatedText refer to the top-left corner
305 // of the rectangle bounding the string. So we must calculate the
306 // right coordinates depending of the angle.
307 // Move left from the Marker so that the position is in the Middle of Text
308 long double tmpangle = angle - rad2deg(asin(halfW / (0.90 * m_radius)));
309 TextPoint.x = m_cx + m_radius * 0.90 * cos(deg2rad(tmpangle));
310 TextPoint.y = m_cy + m_radius * 0.90 * sin(deg2rad(tmpangle));
311 dc->DrawRotatedText(label, TextPoint, -90 - angle);
312 }
313 offset++;
314 value += m_LabelStep;
315 }
316}
317
318void DashboardInstrument_Dial::DrawBackground(wxGCDC* dc) {
319 // Nothing to do here right now, will be overwritten
320 // by child classes if required
321}
322
323void DashboardInstrument_Dial::DrawData(wxGCDC* dc, double value, wxString unit,
324 wxString format,
325 DialPositionOption position) {
326 if (position == DIAL_POSITION_NONE) return;
327
328 if (m_Properties) {
329 dc->SetFont(m_Properties->m_LabelFont.GetChosenFont());
330 dc->SetTextForeground(
331 GetColourSchemeFont(m_Properties->m_LabelFont.GetColour()));
332 } else {
333 dc->SetFont(g_pFontLabel->GetChosenFont());
334 dc->SetTextForeground(GetColourSchemeFont(g_pFontLabel->GetColour()));
335 }
336 wxColour cl;
337 // GetGlobalColor(_T("DASHF"), &cl);
338 wxSize size = GetClientSize();
339
340 wxString text;
341 if (!std::isnan(value)) {
342 if (unit == "\u00B0")
343 text = wxString::Format(format, value) + DEGREE_SIGN;
344 else if (unit == "\u00B0L") // No special display for now, might be
345 // XX�< (as in text-only instrument)
346 text = wxString::Format(format, value) + DEGREE_SIGN;
347 else if (unit == "\u00B0R") // No special display for now, might be >XX�
348 text = wxString::Format(format, value) + DEGREE_SIGN;
349 else if (unit == "\u00B0T")
350 text = wxString::Format(format, value) + DEGREE_SIGN + "T";
351 else if (unit == "\u00B0M")
352 text = wxString::Format(format, value) + DEGREE_SIGN + "M";
353 else if (unit == "N") // Knots
354 text = wxString::Format(format, value) + " Kts";
355 else
356 text = wxString::Format(format, value) + " " + unit;
357 } else
358 text = "---";
359
360 int width, height;
361 wxFont f;
362 if (m_Properties)
363 f = m_Properties->m_LabelFont.GetChosenFont();
364 else
365 f = g_pFontLabel->GetChosenFont();
366 dc->GetMultiLineTextExtent(text, &width, &height, NULL, &f);
367
368 wxRect TextPoint;
369 TextPoint.width = width;
370 TextPoint.height = height;
371 switch (position) {
372 case DIAL_POSITION_NONE:
373 // This case was already handled before, it's here just
374 // to avoid compiler warning.
375 return;
376 case DIAL_POSITION_INSIDE: {
377 TextPoint.x = m_cx - (width / 2) - 1;
378 TextPoint.y = ((size.y - m_InstrumentSpacing) * .75) - height;
379 if ((g_TitleAlignment & wxALIGN_BOTTOM) != 0)
380 TextPoint.y -= m_TitleHeight;
381 if (m_Properties)
382 cl = GetColourSchemeBackgroundColour(
383 m_Properties->m_TitleBackgroundColour);
384 else
385 GetGlobalColor("DASHL", &cl);
386 int penwidth = size.x / 100;
387 wxPen* pen =
388 wxThePenList->FindOrCreatePen(cl, penwidth, wxPENSTYLE_SOLID);
389 dc->SetPen(*pen);
390 if (m_Properties)
391 cl = GetColourSchemeBackgroundColour(
392 m_Properties->m_DataBackgroundColour);
393 else
394 GetGlobalColor("DASHB", &cl);
395 dc->SetBrush(cl);
396 // There might be a background drawn below
397 // so we must clear it first.
398 dc->DrawRoundedRectangle(TextPoint.x - 2, TextPoint.y - 2, width + 4,
399 height + 4, 3);
400 break;
401 }
402 case DIAL_POSITION_TOPLEFT:
403 TextPoint.x = 0;
404 TextPoint.y = m_DataTop;
405 break;
406 case DIAL_POSITION_TOPRIGHT:
407 TextPoint.x = size.x - width - 1;
408 TextPoint.y = m_DataTop;
409 break;
410 case DIAL_POSITION_BOTTOMLEFT:
411 TextPoint.x = 0;
412 TextPoint.y = GetDataBottom(size.y) - height;
413 break;
414 case DIAL_POSITION_BOTTOMRIGHT:
415 TextPoint.x = size.x - width - 1;
416 TextPoint.y = GetDataBottom(size.y) - height;
417 break;
418 case DIAL_POSITION_BOTTOMMIDDLE:
419 if (!std::isnan(value)) {
420 TextPoint.x = m_cx - (width / 2) - 1;
421 TextPoint.y = GetDataBottom(size.y) - height;
422 // There might be a background drawn below
423 // so we must clear it first.
424 dc->DrawRoundedRectangle(TextPoint.x - 2, TextPoint.y - 2, width + 4,
425 height + 4, 3);
426 }
427 break;
428 }
429
430 // wxColour c2;
431 // GetGlobalColor(_T("DASHB"), &c2);
432 wxColour c3;
433 GetGlobalColor("DASHF", &c3);
434
435 wxStringTokenizer tkz(text, "\n");
436 wxString token;
437
438 token = tkz.GetNextToken();
439 while (token.Length()) {
440 if (m_Properties)
441 f = m_Properties->m_LabelFont.GetChosenFont();
442 else
443 f = g_pFontLabel->GetChosenFont();
444 dc->GetTextExtent(token, &width, &height, NULL, NULL, &f);
445 dc->DrawText(token, TextPoint.x, TextPoint.y);
446 TextPoint.y += height;
447 token = tkz.GetNextToken();
448 }
449}
450
451void DashboardInstrument_Dial::DrawForeground(wxGCDC* dc) {
452 // The default foreground is the arrow used in most dials
453 wxColour cl;
454 GetGlobalColor("DASH2", &cl);
455 wxPen pen1;
456 pen1.SetStyle(wxPENSTYLE_SOLID);
457 pen1.SetColour(cl);
458 pen1.SetWidth(2);
459 dc->SetPen(pen1);
460 GetGlobalColor("DASH1", &cl);
461 wxBrush brush1;
462 brush1.SetStyle(wxBRUSHSTYLE_SOLID);
463 brush1.SetColour(cl);
464 dc->SetBrush(brush1);
465 dc->DrawCircle(m_cx, m_cy, m_radius / 8);
466
467 dc->SetPen(*wxTRANSPARENT_PEN);
468 if (m_Properties)
469 cl = GetColourSchemeFont(m_Properties->m_Arrow_First_Colour);
470 else
471 GetGlobalColor("DASHN", &cl);
472 wxBrush brush;
473 brush.SetStyle(wxBRUSHSTYLE_SOLID);
474 brush.SetColour(cl);
475 dc->SetBrush(brush);
476
477 /* this is fix for a +/-180� round instrument, when m_MainValue is supplied as
478 * <0..180><L | R> for example TWA & AWA */
479 double data;
480 if (m_MainValueUnit == "\u00B0L")
481 data = 360 - m_MainValue;
482 else
483 data = m_MainValue;
484
485 // The arrow should stay inside fixed limits
486 double val;
487 if (data < m_MainValueMin)
488 val = m_MainValueMin;
489 else if (data > m_MainValueMax)
490 val = m_MainValueMax;
491 else
492 val = data;
493
494 double value = deg2rad((val - m_MainValueMin) * m_AngleRange /
495 (m_MainValueMax - m_MainValueMin)) +
496 deg2rad(m_AngleStart - ANGLE_OFFSET);
497
498 wxPoint points[4];
499 points[0].x = m_cx + (m_radius * 0.95 * cos(value - .010));
500 points[0].y = m_cy + (m_radius * 0.95 * sin(value - .010));
501 points[1].x = m_cx + (m_radius * 0.95 * cos(value + .015));
502 points[1].y = m_cy + (m_radius * 0.95 * sin(value + .015));
503 points[2].x = m_cx + (m_radius * 0.22 * cos(value + 2.8));
504 points[2].y = m_cy + (m_radius * 0.22 * sin(value + 2.8));
505 points[3].x = m_cx + (m_radius * 0.22 * cos(value - 2.8));
506 points[3].y = m_cy + (m_radius * 0.22 * sin(value - 2.8));
507 dc->DrawPolygon(4, points, 0, 0);
508}
509
510/* Shared functions */
511void DrawCompassRose(wxGCDC* dc, int cx, int cy, int radius, int startangle,
512 bool showlabels, InstrumentProperties* Properties) {
513 wxPoint pt, points[3];
514 wxString Value;
515 int width, height;
516 wxString CompassArray[] = {_("N"), _("NE"), _("E"), _("SE"), _("S"),
517 _("SW"), _("W"), _("NW"), _("N")};
518 if (Properties)
519 dc->SetFont((Properties->m_SmallFont.GetChosenFont()));
520 else
521 dc->SetFont((g_pFontSmall->GetChosenFont()));
522
523 wxColour cl;
524 wxPen* pen;
525 GetGlobalColor("DASH2", &cl);
526 pen = wxThePenList->FindOrCreatePen(cl, 1, wxPENSTYLE_SOLID);
527 wxBrush* b2 = wxTheBrushList->FindOrCreateBrush(cl);
528
529 GetGlobalColor("DASH1", &cl);
530 wxBrush* b1 = wxTheBrushList->FindOrCreateBrush(cl);
531
532 dc->SetPen(*pen);
533 dc->SetTextForeground(cl);
534 dc->SetBrush(*b2);
535
536 int offset = 0;
537 wxFont f;
538 for (double tmpangle = startangle - ANGLE_OFFSET;
539 tmpangle < startangle + 360 - ANGLE_OFFSET; tmpangle += 90) {
540 if (showlabels) {
541 Value = CompassArray[offset];
542 if (Properties) {
543 f = Properties->m_SmallFont.GetChosenFont();
544 dc->GetTextExtent(Value, &width, &height, 0, 0, &f);
545 } else {
546 f = g_pFontSmall->GetChosenFont();
547 dc->GetTextExtent(Value, &width, &height, 0, 0, &f);
548 }
549 double x = width / 2;
550 long double anglefortext = tmpangle - rad2deg(asin((x / radius)));
551 pt.x = cx + radius * cos(deg2rad(anglefortext));
552 pt.y = cy + radius * sin(deg2rad(anglefortext));
553 dc->DrawRotatedText(Value, pt.x, pt.y, -90 - tmpangle);
554 Value = CompassArray[offset + 1];
555 if (Properties) {
556 f = Properties->m_SmallFont.GetChosenFont();
557 dc->GetTextExtent(Value, &width, &height, 0, 0, &f);
558 } else {
559 f = g_pFontSmall->GetChosenFont();
560 dc->GetTextExtent(Value, &width, &height, 0, 0, &f);
561 }
562 x = width / 2;
563 anglefortext = tmpangle - rad2deg(asin((x / radius))) + 45;
564 pt.x = cx + radius * cos(deg2rad(anglefortext));
565 pt.y = cy + radius * sin(deg2rad(anglefortext));
566 dc->DrawRotatedText(Value, pt.x, pt.y, -135 - tmpangle);
567 }
568 points[0].x = cx;
569 points[0].y = cy;
570 points[1].x = cx + radius * 0.15 * cos(deg2rad(tmpangle));
571 points[1].y = cy + radius * 0.15 * sin(deg2rad(tmpangle));
572 points[2].x = cx + radius * 0.6 * cos(deg2rad(tmpangle + 45));
573 points[2].y = cy + radius * 0.6 * sin(deg2rad(tmpangle + 45));
574 dc->DrawPolygon(3, points, 0, 0);
575 points[1].x = cx + radius * 0.15 * cos(deg2rad(tmpangle + 90));
576 points[1].y = cy + radius * 0.15 * sin(deg2rad(tmpangle + 90));
577 dc->SetBrush(*b1);
578 dc->DrawPolygon(3, points, 0, 0);
579 points[2].x = cx + radius * 0.8 * cos(deg2rad(tmpangle));
580 points[2].y = cy + radius * 0.8 * sin(deg2rad(tmpangle));
581 points[1].x = cx + radius * 0.15 * cos(deg2rad(tmpangle + 45));
582 points[1].y = cy + radius * 0.15 * sin(deg2rad(tmpangle + 45));
583 dc->DrawPolygon(3, points, 0, 0);
584 points[2].x = cx + radius * 0.8 * cos(deg2rad(tmpangle + 90));
585 points[2].y = cy + radius * 0.8 * sin(deg2rad(tmpangle + 90));
586 dc->SetBrush(*b2);
587 dc->DrawPolygon(3, points, 0, 0);
588 offset += 2;
589 }
590}
591
592void DrawBoat(wxGCDC* dc, int cx, int cy, int radius) {
593 // Now draw the boat
594 wxColour cl;
595 GetGlobalColor("DASH2", &cl);
596 wxPen* pen = wxThePenList->FindOrCreatePen(cl, 1, wxPENSTYLE_SOLID);
597 dc->SetPen(*pen);
598 GetGlobalColor("DASH1", &cl);
599 dc->SetBrush(cl);
600 wxPoint points[7];
601
602 /*
603 * 0
604 * /\
605 * / \
606 * / \
607 * 6 / \ 1
608 * | |
609 * | X |
610 * 5 | | 2
611 * \ /
612 * \__ _/
613 * 4 3
614 */
615 points[0].x = cx;
616 points[0].y = cy - radius * .60; // a little bit longer than compass rose
617 points[1].x = cx + radius * .15;
618 points[1].y = cy - radius * .08;
619 points[2].x = cx + radius * .15;
620 points[2].y = cy + radius * .12;
621 points[3].x = cx + radius * .10;
622 points[3].y = cy + radius * .40;
623 points[4].x = cx - radius * .10;
624 points[4].y = cy + radius * .40;
625 points[5].x = cx - radius * .15;
626 points[5].y = cy + radius * .12;
627 points[6].x = cx - radius * .15;
628 points[6].y = cy - radius * .08;
629
630 dc->DrawPolygon(7, points, 0, 0);
631}