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