void Track::Draw( ocpnDC& dc, ViewPort &VP, const LLBBox &box ) { std::list< std::list<wxPoint> > pointlists; GetPointLists(pointlists, VP, box); if(!pointlists.size()) return; unsigned short int FromSegNo = 1; // Establish basic colour wxColour basic_colour; if( IsRunning() ) basic_colour = GetGlobalColor( _T ( "URED" ) ); else basic_colour = GetDimColor(g_colourTrackLineColour); wxPenStyle style = wxPENSTYLE_SOLID; int width = g_pRouteMan->GetTrackPen()->GetWidth(); wxColour col; if( m_style != wxPENSTYLE_INVALID ) style = m_style; if( m_width != WIDTH_UNDEFINED ) width = m_width; if( m_Colour == wxEmptyString ) { col = basic_colour; } else { for( unsigned int i = 0; i < sizeof( ::GpxxColorNames ) / sizeof(wxString); i++ ) { if( m_Colour == ::GpxxColorNames[i] ) { col = ::GpxxColors[i]; break; } } } double radius = 0.; if( g_bHighliteTracks ) { double radius_meters = 20; //Current_Ch->GetNativeScale() * .0015; // 1.5 mm at original scale radius = radius_meters * VP.view_scale_ppm; if(radius < 1.0) radius = 0; } if( dc.GetDC() || radius ) { dc.SetPen( *wxThePenList->FindOrCreatePen( col, width, style ) ); dc.SetBrush( *wxTheBrushList->FindOrCreateBrush( col, wxBRUSHSTYLE_SOLID ) ); for(std::list< std::list<wxPoint> >::iterator lines = pointlists.begin(); lines != pointlists.end(); lines++) { // convert from linked list to array wxPoint *points = new wxPoint[lines->size()]; int i = 0; for(std::list<wxPoint>::iterator line = lines->begin(); line != lines->end(); line++) { points[i] = *line; i++; } int hilite_width = radius; if( hilite_width ) { wxPen psave = dc.GetPen(); dc.StrokeLines( i, points ); wxColor trackLine_dim_colour = GetDimColor(g_colourTrackLineColour); wxColour hilt( trackLine_dim_colour.Red(), trackLine_dim_colour.Green(), trackLine_dim_colour.Blue(), 128 ); wxPen HiPen( hilt, hilite_width, wxPENSTYLE_SOLID ); dc.SetPen( HiPen ); dc.StrokeLines( i, points ); dc.SetPen( psave ); } else dc.StrokeLines( i, points ); delete [] points; } } #ifdef ocpnUSE_GL else { // opengl version glColor3ub(col.Red(), col.Green(), col.Blue()); glLineWidth( wxMax( g_GLMinSymbolLineWidth, width ) ); if( g_GLOptions.m_GLLineSmoothing ) glEnable( GL_LINE_SMOOTH ); glEnable( GL_BLEND ); int size = 0; // convert from linked list to array, allocate array just once for(std::list< std::list<wxPoint> >::iterator lines = pointlists.begin(); lines != pointlists.end(); lines++) size = wxMax(size, lines->size()); int *points = new int[2*size]; glVertexPointer(2, GL_INT, 0, points); glEnableClientState(GL_VERTEX_ARRAY); for(std::list< std::list<wxPoint> >::iterator lines = pointlists.begin(); lines != pointlists.end(); lines++) { // convert from linked list to array int i = 0; for(std::list<wxPoint>::iterator line = lines->begin(); line != lines->end(); line++) { points[i+0] = line->x; points[i+1] = line->y; i+=2; } glDrawArrays(GL_LINE_STRIP, 0, i >> 1); } glDisableClientState(GL_VERTEX_ARRAY); delete [] points; glDisable( GL_LINE_SMOOTH ); glDisable( GL_BLEND ); } #endif if(m_HighlightedTrackPoint >= 0) TrackPoints[m_HighlightedTrackPoint]->Draw(dc); }
void RoutePoint::DrawGL( ViewPort &vp, ChartCanvas *canvas, bool use_cached_screen_coords ) { // if( !m_bIsVisible ) // return; // if( !m_bIsActive) // An active route point must always be visible // if( !IsScaVisible( canvas) ) // return; ; if ( !IsVisibleSelectable(canvas) ) return; // Optimization, especially apparent on tracks in normal cases if( m_IconName == _T("empty") && !m_bShowName && !m_bPtIsSelected ) return; if(m_wpBBox.GetValid() && vp.view_scale_ppm == m_wpBBox_view_scale_ppm && vp.rotation == m_wpBBox_rotation) { /* see if this waypoint can intersect with bounding box */ LLBBox vpBBox = vp.GetBBox(); if( vpBBox.IntersectOut( m_wpBBox ) ){ // Are Range Rings enabled? if(m_bShowWaypointRangeRings && (m_iWaypointRangeRingsNumber > 0)){ double factor = 1.00; if( m_iWaypointRangeRingsStepUnits == 1 ) // convert kilometers to NMi factor = 1 / 1.852; double radius = factor * m_iWaypointRangeRingsNumber * m_fWaypointRangeRingsStep / 60.; LLBBox radar_box = m_wpBBox; radar_box.EnLarge(radius * 2 ); if( vpBBox.IntersectOut( radar_box ) ){ return; } } else return; } } wxPoint r; wxRect hilitebox; unsigned char transparency = 150; if(use_cached_screen_coords && m_pos_on_screen) r.x = m_screen_pos.m_x, r.y = m_screen_pos.m_y; else canvas->GetCanvasPointPix( m_lat, m_lon, &r ); if(r.x == INVALID_COORD) return; // Substitute icon? wxBitmap *pbm; if( ( m_bIsActive ) && ( m_IconName != _T("mob") ) ) pbm = pWayPointMan->GetIconBitmap( _T ( "activepoint" ) ); else pbm = m_pbmIcon; // If icon is corrupt, there is really nothing else to do... if(!pbm->IsOk()) return; int sx2 = pbm->GetWidth() / 2; int sy2 = pbm->GetHeight() / 2; // Calculate the mark drawing extents wxRect r1( r.x - sx2, r.y - sy2, sx2 * 2, sy2 * 2 ); // the bitmap extents wxRect r3 = r1; if( m_bShowName ) { if( !m_pMarkFont ) { m_pMarkFont = FontMgr::Get().GetFont( _( "Marks" ) ); m_FontColor = FontMgr::Get().GetFontColor( _( "Marks" ) ); CalculateNameExtents(); } if( m_pMarkFont ) { wxRect r2( r.x + m_NameLocationOffsetX, r.y + m_NameLocationOffsetY, m_NameExtents.x, m_NameExtents.y ); r3.Union( r2 ); } } hilitebox = r3; hilitebox.x -= r.x; hilitebox.y -= r.y; if(!m_bPreScaled){ hilitebox.x *= g_ChartScaleFactorExp; hilitebox.y *= g_ChartScaleFactorExp; hilitebox.width *= g_ChartScaleFactorExp; hilitebox.height *= g_ChartScaleFactorExp; } float radius; if( g_btouch ){ hilitebox.Inflate( 20 ); radius = 20.0f; } else{ hilitebox.Inflate( 4 ); radius = 4.0f; } /* update bounding box */ if(!m_wpBBox.GetValid() || vp.view_scale_ppm != m_wpBBox_view_scale_ppm || vp.rotation != m_wpBBox_rotation) { double lat1, lon1, lat2, lon2; canvas->GetCanvasPixPoint(r.x+hilitebox.x, r.y+hilitebox.y+hilitebox.height, lat1, lon1); canvas->GetCanvasPixPoint(r.x+hilitebox.x+hilitebox.width, r.y+hilitebox.y, lat2, lon2); if(lon1 > lon2) m_wpBBox.Set(lat1, lon1, lat2, lon2+360); else m_wpBBox.Set(lat1, lon1, lat2, lon2); m_wpBBox_view_scale_ppm = vp.view_scale_ppm; m_wpBBox_rotation = vp.rotation; } // if(region.Contains(r3) == wxOutRegion) // return; ocpnDC dc; // Highlite any selected point if( m_bPtIsSelected ) { wxColour hi_colour; if( m_bBlink ){ wxPen *pen = g_pRouteMan->GetActiveRoutePointPen(); hi_colour = pen->GetColour(); } else{ hi_colour = GetGlobalColor( _T ( "YELO1" ) ); } AlphaBlending( dc, r.x + hilitebox.x, r.y + hilitebox.y, hilitebox.width, hilitebox.height, radius, hi_colour, transparency ); } bool bDrawHL = false; if( m_bBlink && ( gFrame->nBlinkerTick & 1 ) ) bDrawHL = true; if( ( !bDrawHL ) && ( NULL != m_pbmIcon ) ) { int glw, glh; unsigned int IconTexture = pWayPointMan->GetIconTexture( pbm, glw, glh ); glBindTexture(GL_TEXTURE_2D, IconTexture); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glColor3f(1, 1, 1); int x = r1.x, y = r1.y, w = r1.width, h = r1.height; float scale = 1.0; if(!m_bPreScaled){ scale = g_ChartScaleFactorExp; } float ws = r1.width * scale; float hs = r1.height * scale; float xs = r.x - ws/2.; float ys = r.y - hs/2.; float u = (float)w/glw, v = (float)h/glh; glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(xs, ys); glTexCoord2f(u, 0); glVertex2f(xs+ws, ys); glTexCoord2f(u, v); glVertex2f(xs+ws, ys+hs); glTexCoord2f(0, v); glVertex2f(xs, ys+hs); glEnd(); // glBegin(GL_QUADS); // glTexCoord2f(0, 0); glVertex2f(x, y); // glTexCoord2f(u, 0); glVertex2f(x+w, y); // glTexCoord2f(u, v); glVertex2f(x+w, y+h); // glTexCoord2f(0, v); glVertex2f(x, y+h); // glEnd(); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); } if( m_bShowName && m_pMarkFont ) { int w = m_NameExtents.x, h = m_NameExtents.y; if(!m_iTextTexture && w && h) { wxBitmap tbm(w, h); /* render text on dc */ wxMemoryDC dc; dc.SelectObject( tbm ); dc.SetBackground( wxBrush( *wxBLACK ) ); dc.Clear(); dc.SetFont( *m_pMarkFont ); dc.SetTextForeground( *wxWHITE ); dc.DrawText( m_MarkName, 0, 0); dc.SelectObject( wxNullBitmap ); /* make alpha texture for text */ wxImage image = tbm.ConvertToImage(); unsigned char *d = image.GetData(); unsigned char *e = new unsigned char[w * h]; if(d && e){ for( int p = 0; p < w*h; p++) e[p] = d[3*p + 0]; } /* create texture for rendered text */ glGenTextures(1, &m_iTextTexture); glBindTexture(GL_TEXTURE_2D, m_iTextTexture); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); m_iTextTextureWidth = NextPow2(w); m_iTextTextureHeight = NextPow2(h); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_iTextTextureWidth, m_iTextTextureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_ALPHA, GL_UNSIGNED_BYTE, e); delete [] e; } if(m_iTextTexture) { /* draw texture with text */ glBindTexture(GL_TEXTURE_2D, m_iTextTexture); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glColor3ub(m_FontColor.Red(), m_FontColor.Green(), m_FontColor.Blue()); int x = r.x + m_NameLocationOffsetX, y = r.y + m_NameLocationOffsetY; float u = (float)w/m_iTextTextureWidth, v = (float)h/m_iTextTextureHeight; glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(x, y); glTexCoord2f(u, 0); glVertex2f(x+w, y); glTexCoord2f(u, v); glVertex2f(x+w, y+h); glTexCoord2f(0, v); glVertex2f(x, y+h); glEnd(); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); } } // Draw waypoint radar rings if activated if( m_iWaypointRangeRingsNumber && m_bShowWaypointRangeRings ) { double factor = 1.00; if( m_iWaypointRangeRingsStepUnits == 1 ) // nautical miles factor = 1 / 1.852; factor *= m_fWaypointRangeRingsStep; double tlat, tlon; wxPoint r1; ll_gc_ll( m_lat, m_lon, 0, factor, &tlat, &tlon ); canvas->GetCanvasPointPix( tlat, tlon, &r1 ); double lpp = sqrt( pow( (double) (r.x - r1.x), 2) + pow( (double) (r.y - r1.y), 2 ) ); int pix_radius = (int) lpp; extern wxColor GetDimColor(wxColor c); wxColor ring_dim_color = GetDimColor(m_wxcWaypointRangeRingsColour); double platform_pen_width = wxRound(wxMax(1.0, g_Platform->GetDisplayDPmm() / 2)); // 0.5 mm nominal, but not less than 1 pixel wxPen ppPen1( ring_dim_color, platform_pen_width ); wxBrush saveBrush = dc.GetBrush(); wxPen savePen = dc.GetPen(); dc.SetPen( ppPen1 ); dc.SetBrush( wxBrush( ring_dim_color, wxBRUSHSTYLE_TRANSPARENT ) ); for( int i = 1; i <= m_iWaypointRangeRingsNumber; i++ ) dc.StrokeCircle( r.x, r.y, i * pix_radius ); dc.SetPen( savePen ); dc.SetBrush( saveBrush ); } // Render Drag handle if enabled if(m_bDrawDragHandle){ // A line, southeast, scaled to the size of the icon double platform_pen_width = wxRound(wxMax(1.0, g_Platform->GetDisplayDPmm() / 2)); // 0.5 mm nominal, but not less than 1 pixel wxColor dh_color = wxColor(0,0,0); wxPen ppPen1( dh_color, 3 * platform_pen_width ); dc.SetPen( ppPen1 ); dc.DrawLine(r.x + hilitebox.width/4, r.y + hilitebox.height/4, r.x + m_drag_line_length_man, r.y + m_drag_line_length_man); dh_color = GetGlobalColor( _T ( "YELO1" ) ); wxPen ppPen2( dh_color, platform_pen_width ); dc.SetPen( ppPen2 ); dc.DrawLine(r.x + hilitebox.width/4, r.y + hilitebox.height/4, r.x + m_drag_line_length_man, r.y + m_drag_line_length_man); // The drag handle glBindTexture(GL_TEXTURE_2D, m_dragIconTexture); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glColor3f(1, 1, 1); int x = r.x + m_drag_icon_offset, y = r.y + m_drag_icon_offset, w = m_dragIcon.GetWidth(), h = m_dragIcon.GetHeight(); float scale = 1.0; float ws = w * scale; float hs = h * scale; float xs = x - ws/2.; float ys = y - hs/2.; float u = (float)w/m_dragIconTextureWidth, v = (float)h/m_dragIconTextureWidth; glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(xs, ys); glTexCoord2f(u, 0); glVertex2f(xs+ws, ys); glTexCoord2f(u, v); glVertex2f(xs+ws, ys+hs); glTexCoord2f(0, v); glVertex2f(xs, ys+hs); glEnd(); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); } if( m_bBlink ) g_blink_rect = CurrentRect_in_DC; // also save for global blinker // This will be useful for fast icon redraws CurrentRect_in_DC.x = r.x + hilitebox.x; CurrentRect_in_DC.y = r.y + hilitebox.y; CurrentRect_in_DC.width = hilitebox.width; CurrentRect_in_DC.height = hilitebox.height; if( m_bBlink ) g_blink_rect = CurrentRect_in_DC; // also save for global blinker }