void Track::GetPointLists(std::list< std::list<wxPoint> > &pointlists, ViewPort &VP, const LLBBox &box ) { if( !IsVisible() || GetnPoints() == 0 ) return; Finalize(); // OCPNStopWatch sw; Segments(pointlists, box, VP.view_scale_ppm); #if 0 if(GetnPoints() > 40000) { double t = sw.GetTime(); double c = 0; for(std::list< std::list<wxPoint> >::iterator lines = pointlists.begin(); lines != pointlists.end(); lines++) { if(lines->size() > 1) c += lines->size(); continue; } printf("assemble time %f %f segments %f seg/ms\n", sw.GetTime(), c, c/t); } #endif // Add last segment, dynamically, maybe..... // we should not add this segment if it is not on the screen... if( IsRunning() ) { std::list<wxPoint> new_list; pointlists.push_back(new_list); AddPointToList(pointlists, TrackPoints.size()-1); wxPoint r; cc1->GetCanvasPointPix( gLat, gLon, &r ); pointlists.back().push_back(r); } }
void Route::DeletePoint( RoutePoint *rp, bool bRenamePoints ) { // n.b. must delete Selectables and update config before deleting the point if( rp->m_bIsInLayer ) return; pSelect->DeleteAllSelectableRoutePoints( this ); pSelect->DeleteAllSelectableRouteSegments( this ); pConfig->DeleteWayPoint( rp ); pRoutePointList->DeleteObject( rp ); if( ( rp->m_GUID.Len() ) && ( wxNOT_FOUND != RoutePointGUIDList.Index( rp->m_GUID ) ) ) RoutePointGUIDList.Remove( rp->m_GUID ); delete rp; if( bRenamePoints ) RenameRoutePoints(); if( GetnPoints() > 1 ) { pSelect->AddAllSelectableRouteSegments( this ); pSelect->AddAllSelectableRoutePoints( this ); pConfig->UpdateRoute( this ); RebuildGUIDList(); // ensure the GUID list is intact and good FinalizeForRendering(); UpdateSegmentDistances(); } }
RoutePoint *Route::InsertPointAfter( RoutePoint *pRP, double rlat, double rlon, bool bRenamePoints ) { int nRP = pRoutePointList->IndexOf( pRP ); if( nRP >= GetnPoints() - 1 ) return NULL; nRP++; RoutePoint *newpoint = new RoutePoint( rlat, rlon, wxString( _T ( "diamond" ) ), GetNewMarkSequenced(), GPX_EMPTY_STRING ); newpoint->m_bIsInRoute = true; newpoint->m_bDynamicName = true; newpoint->SetNameShown( false ); pRoutePointList->Insert( nRP, newpoint ); RoutePointGUIDList.Insert( pRP->m_GUID, nRP ); if( bRenamePoints ) RenameRoutePoints(); FinalizeForRendering(); UpdateSegmentDistances(); return ( newpoint ); }
void Route::AddPoint( RoutePoint *pNewPoint, bool b_rename_in_sequence, bool b_deferBoxCalc ) { if( pNewPoint->m_bIsolatedMark ) { pNewPoint->m_bKeepXRoute = true; } pNewPoint->m_bIsolatedMark = false; // definitely no longer isolated pNewPoint->m_bIsInRoute = true; RoutePoint *prev = GetLastPoint(); pRoutePointList->Append( pNewPoint ); if( !b_deferBoxCalc ) FinalizeForRendering(); if( prev ) UpdateSegmentDistance( prev, pNewPoint ); if( b_rename_in_sequence && pNewPoint->GetName().IsEmpty() && !pNewPoint->m_bKeepXRoute ) { wxString name; name.Printf( _T ( "%03d" ), GetnPoints() ); pNewPoint->SetName( name ); pNewPoint->m_bDynamicName = true; } return; }
void Track::Clone( Track *psourcetrack, int start_nPoint, int end_nPoint, const wxString & suffix) { if( psourcetrack->m_bIsInLayer ) return; m_TrackNameString = psourcetrack->m_TrackNameString + suffix; m_TrackStartString = psourcetrack->m_TrackStartString; m_TrackEndString = psourcetrack->m_TrackEndString; bool b_splitting = GetnPoints() == 0; int startTrkSegNo; if( b_splitting ) startTrkSegNo = psourcetrack->GetPoint( start_nPoint )->m_GPXTrkSegNo; else startTrkSegNo = GetLastPoint()->m_GPXTrkSegNo; int i; for( i = start_nPoint; i <= end_nPoint; i++ ) { TrackPoint *psourcepoint = psourcetrack->GetPoint( i ); if(psourcepoint){ TrackPoint *ptargetpoint = new TrackPoint( psourcepoint); AddPoint( ptargetpoint ); } } }
void Route::CloneTrack( Route *psourceroute, int start_nPoint, int end_nPoint, const wxString & suffix) { if( psourceroute->m_bIsInLayer ) return; m_bIsTrack = psourceroute->m_bIsTrack; m_RouteNameString = psourceroute->m_RouteNameString + suffix; m_RouteStartString = psourceroute->m_RouteStartString; m_RouteEndString = psourceroute->m_RouteEndString; bool b_splitting = GetnPoints() == 0; int startTrkSegNo; if( b_splitting ) startTrkSegNo = psourceroute->GetPoint( start_nPoint )->m_GPXTrkSegNo; else startTrkSegNo = this->GetLastPoint()->m_GPXTrkSegNo; int i; for( i = start_nPoint; i <= end_nPoint; i++ ) { RoutePoint *psourcepoint = psourceroute->GetPoint( i ); RoutePoint *ptargetpoint = new RoutePoint( psourcepoint->m_lat, psourcepoint->m_lon, psourcepoint->GetIconName(), psourcepoint->GetName(), GPX_EMPTY_STRING, false ); AddPoint( ptargetpoint, false ); // This is a hack, need to undo the action of Route::AddPoint ptargetpoint->m_bIsInRoute = false; ptargetpoint->m_bIsInTrack = true; CloneAddedTrackPoint( m_pLastAddedPoint, psourcepoint ); int segment_shift = psourcepoint->m_GPXTrkSegNo; if( start_nPoint == 2 ) segment_shift = psourcepoint->m_GPXTrkSegNo - 1; // continue first segment if tracks share the first point if( b_splitting ) m_pLastAddedPoint->m_GPXTrkSegNo = ( psourcepoint->m_GPXTrkSegNo - startTrkSegNo ) + 1; else m_pLastAddedPoint->m_GPXTrkSegNo = startTrkSegNo + segment_shift; } FinalizeForRendering(); }
Track *ActiveTrack::DoExtendDaily() { Track *pExtendTrack = NULL; TrackPoint *pExtendPoint = NULL; TrackPoint *pLastPoint = GetPoint( 0 ); wxTrackListNode *track_node = pTrackList->GetFirst(); while( track_node ) { Track *ptrack = track_node->GetData(); if( !ptrack->m_bIsInLayer && ptrack->m_GUID != m_GUID ) { TrackPoint *track_node = ptrack->GetLastPoint(); if( track_node->GetCreateTime() <= pLastPoint->GetCreateTime() ) { if( !pExtendPoint || track_node->GetCreateTime() > pExtendPoint->GetCreateTime() ) { pExtendPoint = track_node; pExtendTrack = ptrack; } } } track_node = track_node->GetNext(); // next track } if( pExtendTrack && pExtendTrack->GetPoint( 0 )->GetCreateTime().FromTimezone( wxDateTime::GMT0 ).IsSameDate(pLastPoint->GetCreateTime().FromTimezone( wxDateTime::GMT0 ) ) ) { int begin = 1; if( pLastPoint->GetCreateTime() == pExtendPoint->GetCreateTime() ) begin = 2; pSelect->DeleteAllSelectableTrackSegments( pExtendTrack ); wxString suffix = _T(""); if( GetName().IsNull() ) { suffix = pExtendTrack->GetName(); if( suffix.IsNull() ) suffix = wxDateTime::Today().FormatISODate(); } pExtendTrack->Clone( this, begin, GetnPoints(), suffix ); pSelect->AddAllSelectableTrackSegments( pExtendTrack ); pSelect->DeleteAllSelectableTrackSegments( this ); return pExtendTrack; } else { if( GetName().IsNull() ) SetName(wxDateTime::Today().FormatISODate()); return NULL; } }
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(GetnPoints() == 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); for(node = node->GetNext(); node; node = node->GetNext()) { RoutePoint *prp1 = prp2; prp2 = node->GetData(); // Provisional, to properly set status of last point in route prp2->m_pos_on_screen = false; { 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.GetMinLat(), lat2l = prp2->m_lat < bbox.GetMinLat(); bool lat1r = prp1->m_lat > bbox.GetMaxLat(), lat2r = prp2->m_lat > bbox.GetMaxLat(); if( (lat1l && lat2l) || (lat1r && lat2r) ) { r1valid = false; prp1->m_pos_on_screen = false; continue; } bool lon1l, lon1r, lon2l, lon2r; TestLongitude(prp1->m_lon, bbox.GetMinLon(), bbox.GetMaxLon(), lon1l, lon1r); TestLongitude(prp2->m_lon, bbox.GetMinLon(), bbox.GetMaxLon(), 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; } } if( !dc ) glEnd(); #endif }
void Route::DrawPointWhich( ocpnDC& dc, int iPoint, wxPoint *rpn ) { if( iPoint <= GetnPoints() ) GetPoint( iPoint )->Draw( dc, rpn ); }
void ActiveTrack::AddPointNow( bool do_add_point ) { wxDateTime now = wxDateTime::Now(); if( m_prev_dist < 0.0005 ) // avoid zero length segs if( !do_add_point ) return; if( m_prev_time.IsValid() ) if( m_prev_time == now ) // avoid zero time segs if( !do_add_point ) return; vector2D gpsPoint( gLon, gLat ); // The dynamic interval algorithm will gather all track points in a queue, // and analyze the cross track errors for each point before actually adding // a point to the track. switch( trackPointState ) { case firstPoint: { TrackPoint *pTrackPoint = AddNewPoint( gpsPoint, now.ToUTC() ); m_lastStoredTP = pTrackPoint; trackPointState = secondPoint; do_add_point = false; break; } case secondPoint: { vector2D pPoint( gLon, gLat ); skipPoints.push_back( pPoint ); skipTimes.push_back( now.ToUTC() ); trackPointState = potentialPoint; break; } case potentialPoint: { if( gpsPoint == skipPoints[skipPoints.size()-1] ) break; unsigned int xteMaxIndex = 0; double xteMax = 0; // Scan points skipped so far and see if anyone has XTE over the threshold. for( unsigned int i=0; i<skipPoints.size(); i++ ) { double xte = GetXTE( m_lastStoredTP->m_lat, m_lastStoredTP->m_lon, gLat, gLon, skipPoints[i].lat, skipPoints[i].lon ); if( xte > xteMax ) { xteMax = xte; xteMaxIndex = i; } } if( xteMax > m_allowedMaxXTE ) { TrackPoint *pTrackPoint = AddNewPoint( skipPoints[xteMaxIndex], skipTimes[xteMaxIndex] ); pSelect->AddSelectableTrackSegment( m_lastStoredTP->m_lat, m_lastStoredTP->m_lon, pTrackPoint->m_lat, pTrackPoint->m_lon, m_lastStoredTP, pTrackPoint, this ); m_prevFixedTP = m_fixedTP; m_fixedTP = m_removeTP; m_removeTP = m_lastStoredTP; m_lastStoredTP = pTrackPoint; for( unsigned int i=0; i<=xteMaxIndex; i++ ) { skipPoints.pop_front(); skipTimes.pop_front(); } // Now back up and see if we just made 3 points in a straight line and the middle one // (the next to last) point can possibly be eliminated. Here we reduce the allowed // XTE as a function of leg length. (Half the XTE for very short legs). if( GetnPoints() > 2 ) { double dist = DistGreatCircle( m_fixedTP->m_lat, m_fixedTP->m_lon, m_lastStoredTP->m_lat, m_lastStoredTP->m_lon ); double xte = GetXTE( m_fixedTP, m_lastStoredTP, m_removeTP ); if( xte < m_allowedMaxXTE / wxMax(1.0, 2.0 - dist*2.0) ) { TrackPoints.pop_back(); TrackPoints.pop_back(); TrackPoints.push_back( m_lastStoredTP ); pSelect->DeletePointSelectableTrackSegments( m_removeTP ); pSelect->AddSelectableTrackSegment( m_fixedTP->m_lat, m_fixedTP->m_lon, m_lastStoredTP->m_lat, m_lastStoredTP->m_lon, m_fixedTP, m_lastStoredTP, this ); delete m_removeTP; m_removeTP = m_fixedTP; m_fixedTP = m_prevFixedTP; } } } skipPoints.push_back( gpsPoint ); skipTimes.push_back( now.ToUTC() ); break; } } // Check if this is the last point of the track. if( do_add_point ) { TrackPoint *pTrackPoint = AddNewPoint( gpsPoint, now.ToUTC() ); pSelect->AddSelectableTrackSegment( m_lastStoredTP->m_lat, m_lastStoredTP->m_lon, pTrackPoint->m_lat, pTrackPoint->m_lon, m_lastStoredTP, pTrackPoint, this ); } m_prev_time = now; }