void Route::DrawGLLines( ViewPort &vp, ocpnDC *dc ) { #ifdef ocpnUSE_GL float pix_full_circle = WGS84_semimajor_axis_meters * mercator_k0 * 2 * PI * vp.view_scale_ppm; bool r1valid = false; wxPoint2DDouble r1; wxPoint2DDouble lastpoint; wxRoutePointListNode *node = pRoutePointList->GetFirst(); RoutePoint *prp2 = node->GetData(); cc1->GetDoubleCanvasPointPix( prp2->m_lat, prp2->m_lon, &lastpoint); if(m_nPoints == 1 && dc) { // single point.. make sure it shows up for highlighting cc1->GetDoubleCanvasPointPix( prp2->m_lat, prp2->m_lon, &r1); dc->DrawLine(r1.m_x, r1.m_y, r1.m_x+2, r1.m_y+2); return; } // Handle offscreen points LLBBox bbox = vp.GetBBox(); // dc is passed for thicker highlighted lines (performance not very important) if( !dc ) glBegin(GL_LINES); unsigned short int FromSegNo = prp2->m_GPXTrkSegNo; for(node = node->GetNext(); node; node = node->GetNext()) { RoutePoint *prp1 = prp2; prp2 = node->GetData(); unsigned short int ToSegNo = prp2->m_GPXTrkSegNo; // Provisional, to properly set status of last point in route prp2->m_pos_on_screen = false; if (FromSegNo != ToSegNo) { FromSegNo = ToSegNo; r1valid = false; } else { wxPoint2DDouble r2; cc1->GetDoubleCanvasPointPix( prp2->m_lat, prp2->m_lon, &r2); if(wxIsNaN(r2.m_x)) { r1valid = false; continue; } lastpoint = r2; // For active track segment to ownship // don't need to perform calculations or render segment // if both points are past any edge of the vp // TODO: use these optimizations for dc mode bool lat1l = prp1->m_lat < bbox.GetMinY(), lat2l = prp2->m_lat < bbox.GetMinY(); bool lat1r = prp1->m_lat > bbox.GetMaxY(), lat2r = prp2->m_lat > bbox.GetMaxY(); if( (lat1l && lat2l) || (lat1r && lat2r) ) { r1valid = false; prp1->m_pos_on_screen = false; continue; } bool lon1l, lon1r, lon2l, lon2r; TestLongitude(prp1->m_lon, bbox.GetMinX(), bbox.GetMaxX(), lon1l, lon1r); TestLongitude(prp2->m_lon, bbox.GetMinX(), bbox.GetMaxX(), lon2l, lon2r); if( (lon1l && lon2l) || (lon1r && lon2r) ) { r1valid = false; prp1->m_pos_on_screen = false; continue; } if(!r1valid) { cc1->GetDoubleCanvasPointPix( prp1->m_lat, prp1->m_lon, &r1); if(wxIsNaN(r1.m_x)) continue; } // we must decide which way to go in longitude // for projections which wrap, in this case, we will render two lines // (one may often be off screen which would be nice to fix but complicate things here // anyway, in some cases both points are on screen, but the route wraps to either side // so two lines are needed to draw this properly double adder = 0; if( (vp.m_projection_type == PROJECTION_MERCATOR || vp.m_projection_type == PROJECTION_EQUIRECTANGULAR) ) { float olon = vp.clon > 0 ? vp.clon - 180 : vp.clon + 180; if(prp1->m_lon < prp2->m_lon) { if(prp2->m_lon - prp1->m_lon < 180) { if(olon > prp1->m_lon && olon < prp2->m_lon) adder = pix_full_circle; } else if(olon < prp1->m_lon || olon > prp2->m_lon) adder = -pix_full_circle; } else if(prp1->m_lon - prp2->m_lon < 180) { if(olon < prp1->m_lon && olon > prp2->m_lon) adder = -pix_full_circle; } else if(olon > prp1->m_lon || olon < prp2->m_lon) adder = pix_full_circle; } if( dc ) if(adder) { float adderc = cos(vp.rotation)*adder, adders = sin(vp.rotation)*adder; dc->DrawLine(r1.m_x, r1.m_y, r2.m_x + adderc, r2.m_y + adders); dc->DrawLine(r1.m_x - adderc, r1.m_y - adders, r2.m_x, r2.m_y); } else dc->DrawLine(r1.m_x, r1.m_y, r2.m_x, r2.m_y); else { glVertex2f(r1.m_x, r1.m_y); if(adder) { float adderc = cos(vp.rotation)*adder, adders = sin(vp.rotation)*adder; glVertex2f(r2.m_x+adderc, r2.m_y+adders); glVertex2f(r1.m_x-adderc, r1.m_y-adders); } glVertex2f(r2.m_x, r2.m_y); // cache screen position for arrows and points if(!r1valid) { prp1->m_pos_on_screen = !lat1l && !lat1r && !lon1l && !lon1r; prp1->m_screen_pos = r1; } prp2->m_pos_on_screen = !lat2l && !lat2r && !lon2l && !lon2r; prp2->m_screen_pos = r2; } r1 = r2; r1valid = true; } } // Draw tentative segment from last point to Ownship, if running. if( IsTrack() ) { /* Active tracks */ if( dynamic_cast<Track *>(this)->IsRunning() ){ wxPoint2DDouble rs; cc1->GetDoubleCanvasPointPix( gLat, gLon, &rs); if( dc ) dc->DrawLine(lastpoint.m_x, lastpoint.m_y, rs.m_x, rs.m_y); else { glVertex2f(lastpoint.m_x, lastpoint.m_y); glVertex2f(rs.m_x, rs.m_y); } } } if( !dc ) glEnd(); #endif }
void Route::DrawGLLines( ViewPort &VP, ocpnDC *dc ) { #ifdef ocpnUSE_GL float pix_full_circle = WGS84_semimajor_axis_meters * mercator_k0 * 2 * PI * VP.view_scale_ppm; bool r1valid = false; wxPoint2DDouble r1; wxPoint2DDouble lastpoint; wxRoutePointListNode *node = pRoutePointList->GetFirst(); RoutePoint *prp2 = node->GetData(); cc1->GetDoubleCanvasPointPix( prp2->m_lat, prp2->m_lon, &lastpoint); if(m_nPoints == 1 && dc) { // single point.. make sure it shows up for highlighting cc1->GetDoubleCanvasPointPix( prp2->m_lat, prp2->m_lon, &r1); dc->DrawLine(r1.m_x, r1.m_y, r1.m_x+2, r1.m_y+2); return; } // dc is passed for thicker highlighted lines (performance not very important) if( !dc ) glBegin(GL_LINES); unsigned short int FromSegNo = prp2->m_GPXTrkSegNo; for(node = node->GetNext(); node; node = node->GetNext()) { RoutePoint *prp1 = prp2; prp2 = node->GetData(); unsigned short int ToSegNo = prp2->m_GPXTrkSegNo; // Provisional, to properly set status of last point in route prp2->m_pos_on_screen = false; if (FromSegNo != ToSegNo) { FromSegNo = ToSegNo; r1valid = false; } else { wxPoint2DDouble r2; cc1->GetDoubleCanvasPointPix( prp2->m_lat, prp2->m_lon, &r2); lastpoint = r2; // For active track segment to ownship // Handle offscreen points LLBBox bbox = VP.GetBBox(); // don't need to perform calculations or render segment // if both points are past any edge of the vp // TODO: use these optimizations for dc mode bool lat1l = prp1->m_lat < bbox.GetMinY(), lat2l = prp2->m_lat < bbox.GetMinY(); bool lat1r = prp1->m_lat > bbox.GetMaxY(), lat2r = prp2->m_lat > bbox.GetMaxY(); if( (lat1l && lat2l) || (lat1r && lat2r) ) { r1valid = false; prp1->m_pos_on_screen = false; continue; } bool lon1l, lon1r, lon2l, lon2r; TestLongitude(prp1->m_lon, bbox.GetMinX(), bbox.GetMaxX(), lon1l, lon1r); TestLongitude(prp2->m_lon, bbox.GetMinX(), bbox.GetMaxX(), lon2l, lon2r); if( (lon1l && lon2l) || (lon1r && lon2r) ) { r1valid = false; prp1->m_pos_on_screen = false; continue; } if(!r1valid) cc1->GetDoubleCanvasPointPix( prp1->m_lat, prp1->m_lon, &r1); // In the cases where one point is on, and one off // we must decide which way to go in longitude double adder1 = 0, adder2 = 0; if(!(lon1l || lon1r) && (lon2l || lon2r) ) { // first point is on screen, second not if( r2.m_x < r1.m_x ) adder2 = pix_full_circle; else adder2 = -pix_full_circle; if( fabs(r1.m_x - r2.m_x) < fabs(r1.m_x - ( r2.m_x + adder2 )) ) adder2 = 0; } else if(lon1l || lon1r) { // first point is off screen if( r1.m_x < r2.m_x ) adder1 = pix_full_circle; else adder1 = -pix_full_circle; if( fabs(r1.m_x - r2.m_x) < fabs(r2.m_x - (r1.m_x + adder1)) ) adder1 = 0; } if( dc ) dc->DrawLine(r1.m_x + adder1, r1.m_y, r2.m_x + adder2, r2.m_y); else { glVertex2f(r1.m_x + adder1, r1.m_y); glVertex2f(r2.m_x + adder2, r2.m_y); // cache screen position for arrows and points if(!r1valid) { prp1->m_pos_on_screen = !lat1l && !lat1r && !lon1l && !lon1r; prp1->m_screen_pos = r1; } prp2->m_pos_on_screen = !lat2l && !lat2r && !lon2l && !lon2r; prp2->m_screen_pos = r2; } r1 = r2; r1valid = true; } } // Draw tentative segment from last point to Ownship, if running. if( IsTrack() ) { /* Active tracks */ if( dynamic_cast<Track *>(this)->IsRunning() ){ wxPoint2DDouble rs; cc1->GetDoubleCanvasPointPix( gLat, gLon, &rs); if( dc ) dc->DrawLine(lastpoint.m_x, lastpoint.m_y, rs.m_x, rs.m_y); else { glVertex2f(lastpoint.m_x, lastpoint.m_y); glVertex2f(rs.m_x, rs.m_y); } } } if( !dc ) glEnd(); #endif }