diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2020-08-08 11:53:00 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2020-08-08 11:53:00 +0200 |
commit | b623f5953691b2a0614e6f1f4def86bdbb9a4113 (patch) | |
tree | 18102bd36f7e22eb2ba2b9f880e4cb29346f4cb8 /app/bin/track.c | |
parent | 359b557176b9bb2ff1aed2082641eed39c358d0d (diff) |
New upstream version 5.2.0Beta2.1upstream/5.2.0Beta2.1upstream
Diffstat (limited to 'app/bin/track.c')
-rw-r--r-- | app/bin/track.c | 900 |
1 files changed, 667 insertions, 233 deletions
diff --git a/app/bin/track.c b/app/bin/track.c index 0660d7d..c9ec7db 100644 --- a/app/bin/track.c +++ b/app/bin/track.c @@ -43,6 +43,8 @@ #include "paths.h" #include "track.h" #include "utility.h" +#include "misc.h" +#include "ctrain.h" #ifndef TRACKDEP #ifndef FASTTRACK @@ -59,6 +61,8 @@ #endif #endif +EXPORT char tempSpecial[4096]; + static int log_track = 0; static int log_endPt = 0; static int log_readTracks = 0; @@ -110,6 +114,8 @@ EXPORT BOOL_T onTrackInSplit = FALSE; static BOOL_T inDrawTracks; +static wBool_t bWriteEndPtDirectIndex = FALSE; + #ifndef TRACKDEP /***************************************************************************** @@ -117,10 +123,17 @@ static BOOL_T inDrawTracks; * * */ +EXPORT void ActivateTrack( track_cp trk) { + int inx = GetTrkType(trk); + if (trackCmds( inx )->activate != NULL) + trackCmds( inx )->activate (trk); + +} EXPORT void DescribeTrack( track_cp trk, char * str, CSIZE_T len ) { + trackCmds( GetTrkType(trk) )->describe ( trk, str, len ); /*epCnt = GetTrkEndPtCnt(trk); if (debugTrack >= 2) @@ -131,7 +144,7 @@ EXPORT void DescribeTrack( track_cp trk, char * str, CSIZE_T len ) EXPORT DIST_T GetTrkDistance( track_cp trk, coOrd * pos ) { - return trackCmds( GetTrkType(trk) )->distance( trk, pos ); + return fabs(trackCmds( GetTrkType(trk) )->distance( trk, pos )); } /** @@ -176,13 +189,14 @@ EXPORT track_p OnTrack2( coOrd * fp, BOOL_T complain, BOOL_T track, BOOL_T ignor } p = *fp; distance = trackCmds( GetTrkType(trk) )->distance( trk, &p ); - if (distance < closestDistance) { + if (fabs(distance) <= fabs(closestDistance)) { //Make the last (highest) preferred closestDistance = distance; closestTrack = trk; closestPos = p; } } - if (closestTrack && (closestDistance <= mainD.scale*0.25 || closestDistance <= trackGauge*2.0) ) { + if (closestTrack && closestDistance <0 ) closestDistance = 0.0; //Turntable was closest - inside well + if (closestTrack && ((closestDistance <= mainD.scale*0.25) || (closestDistance <= trackGauge*2.0) )) { *fp = closestPos; return closestTrack; } @@ -214,9 +228,21 @@ EXPORT BOOL_T CheckTrackLayer( track_p trk ) if (GetLayerFrozen( GetTrkLayer( trk ) ) ) { ErrorMessage( MSG_CANT_MODIFY_FROZEN_TRK ); return FALSE; - } else { + } else if (GetLayerModule( GetTrkLayer( trk ) ) ) { + ErrorMessage( MSG_CANT_MODIFY_MODULE_TRK ); + return FALSE; + } else + return TRUE; +} + +EXPORT BOOL_T CheckTrackLayerSilent( track_p trk ) +{ + if (GetLayerFrozen( GetTrkLayer( trk ) ) ) { + return FALSE; + } else if (GetLayerModule( GetTrkLayer( trk ) ) ) { + return FALSE; + } else return TRUE; - } } /****************************************************************************** @@ -249,7 +275,6 @@ EXPORT void EnumerateTracks( void ) trackCmds(inx)->enumerate( NULL ); EnumerateEnd(); - Reset(); } /***************************************************************************** @@ -327,7 +352,9 @@ EXPORT TRKTYP_T GetTrkType( track_p trk ) EXPORT SCALEINX_T GetTrkScale( track_p trk ) { - return (SCALEINX_T)trk->scale; + if ( trk ) + return (SCALEINX_T)trk->scale; + return 0; } EXPORT void SetTrkScale( track_p trk, SCALEINX_T si ) @@ -369,6 +396,7 @@ EXPORT struct extraData * GetTrkExtraData( track_cp trk ) EXPORT void SetTrkEndPoint( track_p trk, EPINX_T ep, coOrd pos, ANGLE_T angle ) { + ASSERT( ep < trk->endCnt ); if (trk->endPt[ep].track != NULL) { AbortProg( "setTrkEndPoint: endPt is connected" ); } @@ -378,29 +406,43 @@ EXPORT void SetTrkEndPoint( track_p trk, EPINX_T ep, coOrd pos, ANGLE_T angle ) EXPORT coOrd GetTrkEndPos( track_p trk, EPINX_T e ) { + ASSERT( e < trk->endCnt ); return trk->endPt[e].pos; } EXPORT ANGLE_T GetTrkEndAngle( track_p trk, EPINX_T e ) { + ASSERT( e < trk->endCnt ); return trk->endPt[e].angle; } EXPORT track_p GetTrkEndTrk( track_p trk, EPINX_T e ) { + ASSERT( e < trk->endCnt ); return trk->endPt[e].track; } EXPORT long GetTrkEndOption( track_p trk, EPINX_T e ) { + ASSERT( e < trk->endCnt ); return trk->endPt[e].option; } EXPORT long SetTrkEndOption( track_p trk, EPINX_T e, long option ) { + ASSERT( e < trk->endCnt ); return trk->endPt[e].option = option; } +EXPORT DIST_T GetTrkGauge( + track_cp trk ) +{ + if (trk) + return GetScaleTrackGauge( GetTrkScale( trk ) ); + else + return trackGauge; +} + EXPORT int GetTrkWidth( track_p trk ) { return (int)trk->width; @@ -441,6 +483,7 @@ EXPORT void SetTrkEndElev( track_p trk, EPINX_T ep, int option, DIST_T height, c track_p trk1; EPINX_T ep1; trk->endPt[ep].elev.option = option; + trk->endPt[ep].elev.cacheSet = FALSE; if (EndPtIsDefinedElev(trk,ep)) { trk->endPt[ep].elev.u.height = height; } else if (EndPtIsStationElev(trk,ep)) { @@ -487,6 +530,23 @@ EXPORT DIST_T GetTrkEndElevHeight( track_p trk, EPINX_T e ) return trk->endPt[e].elev.u.height; } +EXPORT BOOL_T GetTrkEndElevCachedHeight (track_p trk, EPINX_T e, DIST_T * height, DIST_T * length) +{ + if (trk->endPt[e].elev.cacheSet) { + *height = trk->endPt[e].elev.cachedElev; + *length = trk->endPt[e].elev.cachedLength; + return TRUE; + } + return FALSE; +} + +EXPORT void SetTrkEndElevCachedHeight ( track_p trk, EPINX_T e, DIST_T height, DIST_T length) +{ + trk->endPt[e].elev.cachedElev = height; + trk->endPt[e].elev.cachedLength = length; + trk->endPt[e].elev.cacheSet = TRUE; +} + EXPORT char * GetTrkEndElevStation( track_p trk, EPINX_T e ) { @@ -531,13 +591,21 @@ void SetTrkLayer( track_p trk, int layer ) EXPORT int ClrAllTrkBits( int bits ) { + return ClrAllTrkBitsRedraw( bits, FALSE ); +} + + +EXPORT int ClrAllTrkBitsRedraw( int bits, wBool_t bRedraw ) +{ track_p trk; - int cnt; - cnt = 0; + int cnt = 0; TRK_ITERATE( trk ) { - if (trk->bits&bits) + if (trk->bits&bits) { cnt++; - trk->bits &= ~bits; + trk->bits &= ~bits; + if ( bRedraw ) + DrawNewTrack( trk ); + } } return cnt; } @@ -549,6 +617,9 @@ EXPORT void SetTrkElev( track_p trk, int mode, DIST_T elev ) SetTrkBits( trk, TB_ELEVPATH ); trk->elev = elev; trk->elevMode = mode; + for (int i=0;i<trk->endCnt;i++) { + trk->endPt[i].elev.cacheSet = FALSE; + } } @@ -606,7 +677,9 @@ EXPORT BOOL_T WriteEndPt( FILE * f, track_cp trk, EPINX_T ep ) long option; assert ( endPt != NULL ); - if (endPt->track == NULL || + if (bWriteEndPtDirectIndex && endPt->index > 0) { + rc &= fprintf( f, "\tT4 %d ", endPt->index )>0; + } else if (endPt->track == NULL || ( exportingTracks && !GetTrkSelected(endPt->track) ) ) { rc &= fprintf( f, "\tE4 " )>0; } else { @@ -651,7 +724,7 @@ EXPORT EPINX_T PickEndPoint( coOrd p, track_cp trk ) if (trk->endCnt <= 0) return -1; if ( onTrackInSplit && trk->endCnt > 2 ) { - if (GetTrkType(trk) != T_TURNOUT) + if (GetTrkType(trk) == T_TURNOUT) return TurnoutPickEndPt( p, trk ); } d = FindDistance( p, trk->endPt[0].pos ); @@ -875,12 +948,14 @@ EXPORT BOOL_T MakeParallelTrack( track_p trk, coOrd pos, DIST_T dist, + DIST_T factor, track_p * newTrkR, coOrd * p0R, - coOrd * p1R ) + coOrd * p1R, + BOOL_T track) { if ( trackCmds(trk->type)->makeParallel ) - return trackCmds(trk->type)->makeParallel( trk, pos, dist, newTrkR, p0R, p1R ); + return trackCmds(trk->type)->makeParallel( trk, pos, dist, factor, newTrkR, p0R, p1R, track); return FALSE; } @@ -1011,7 +1086,7 @@ EXPORT void ClearTracks( void ) to_first = NULL; to_last = &to_first; max_index = 0; - changed = 0; + changed = checkPtMark = 0; trackCount = 0; ClearCars(); InfoCount( trackCount ); @@ -1033,11 +1108,14 @@ EXPORT void ResolveIndex( void ) track_p trk; EPINX_T ep; TRK_ITERATE(trk) { + LOG (log_track, 1, ( "ResNextTrack( T%d, t%d, E%d, X%ld)\n", trk->index, trk->type, trk->endCnt, trk->extraSize )); for (ep=0; ep<trk->endCnt; ep++) if (trk->endPt[ep].index >= 0) { trk->endPt[ep].track = FindTrack( trk->endPt[ep].index ); if (trk->endPt[ep].track == NULL) { - NoticeMessage( MSG_RESOLV_INDEX_BAD_TRK, _("Continue"), NULL, trk->index, ep, trk->endPt[ep].index ); + int rc = NoticeMessage( MSG_RESOLV_INDEX_BAD_TRK, _("Continue"), _("Quit"), trk->index, ep, trk->endPt[ep].index ); + if ( rc != 1 ) + return; } } ResolveBlockTrack (trk); @@ -1063,29 +1141,21 @@ LOG( log_track, 4, ( "DeleteTrack(T%d)\n", GetTrkIndex(trk) ) ) } } } - UndrawNewTrack( trk ); for (i=0;i<trk->endCnt;i++) { if ((trk2=trk->endPt[i].track) != NULL) { ep2 = GetEndPtConnectedToMe( trk2, trk ); - /*UndrawNewTrack( trk2 );*/ - DrawEndPt( &mainD, trk2, ep2, wDrawColorWhite ); DisconnectTracks( trk2, ep2, trk, i ); - /*DrawNewTrack( trk2 );*/ - if (!QueryTrack(trk2,Q_DONT_DRAW_ENDPOINT)) - DrawEndPt( &mainD, trk2, ep2, wDrawColorBlack ); if ( QueryTrack(trk,Q_CANNOT_BE_ON_END) ) UndoJoint( trk2, ep2, trk, i ); - ClrTrkElev( trk2 ); } } - CheckDeleteSwitchmotor( trk ); - CheckDeleteBlock( trk ); + CheckDeleteSwitchmotor( trk ); + CheckDeleteBlock( trk ); + CheckCarTraverse( trk ); DecrementLayerObjects(trk->layer); trackCount--; AuditTracks( "deleteTrack T%d", trk->index); UndoDelete(trk); /**< Attention: trk is invalidated during that call */ - MainRedraw(); - MapRedraw(); InfoCount( trackCount ); return TRUE; } @@ -1130,6 +1200,98 @@ BOOL_T TrackIterate( track_p * trk ) *trk = trk1; return trk1 != NULL; } + + +wBool_t IsPosClose( coOrd pos1, coOrd pos2 ) { + DIST_T d = FindDistance( pos1, pos2 ); + return d < 0.1; +} + + +wBool_t IsAngleClose( ANGLE_T angle1, ANGLE_T angle2 ) +{ + ANGLE_T angle = NormalizeAngle( angle1 - angle2 ); + if (angle > 180) + angle = 360-angle; + return angle < 0.01; +} + + +wBool_t IsDistClose( DIST_T dist1, DIST_T dist2 ) +{ + DIST_T dist = fabs( dist1 - dist2 ); + return dist < 0.01; +} + +wBool_t IsWidthClose( DIST_T dist1, DIST_T dist2 ) +{ + // width is computed by pixels/dpi + // problem is when widths are computed on platforms with differing dpi + DIST_T dist = fabs( dist1 - dist2 ); + if ( dist < 0.01 ) + return TRUE; +#ifdef WINDOWS + dist1 *= 96.0/72.0; +#else + dist1 *= 72.0/96.0; +#endif + dist = fabs( dist1 - dist2 ); + if ( dist < 0.01 ) + return TRUE; + return FALSE; +} + +wBool_t IsColorClose( wDrawColor color1, wDrawColor color2 ) +{ + long rgb1 = wDrawGetRGB( color1 ); + long rgb2 = wDrawGetRGB( color2 ); + int r1 = (rgb1 >> 16) & 0xff; + int g1 = (rgb1 >> 8) & 0xff; + int b1 = rgb1 & 0xff; + int r2 = (rgb2 >> 16) & 0xff; + int g2 = (rgb2 >> 8) & 0xff; + int b2 = rgb2 & 0xff; + long diff = abs(r1-r2) + abs(g1-g2) + abs(b1-b2); + return (diff < 7); +} + +wBool_t CompareTrack( track_cp trk1, track_cp trk2 ) +{ + wBool_t rc = FALSE; + if ( trk1 == NULL ) { + sprintf( message, "Compare: T%d not found\n", trk2->index ); + return FALSE; + } + sprintf( message, "Compare T:%d - ", GetTrkIndex(trk1) ); + char * cp = message+strlen(message); + REGRESS_CHECK_INT( "Type", trk1, trk2, type ) + REGRESS_CHECK_INT( "Index", trk1, trk2, index ) + REGRESS_CHECK_INT( "Layer", trk1, trk2, layer ) + REGRESS_CHECK_INT( "Scale", trk1, trk2, scale ) + REGRESS_CHECK_INT( "EndPtCnt", trk1, trk2, endCnt ) + char * cq = cp-2; + for ( int inx=0; inx<GetTrkEndPtCnt( trk1 ); inx++ ) { + cp = cq; + sprintf( cp, "EP:%d - ", inx ); + cp += strlen(cp); + REGRESS_CHECK_POS( "Pos", trk1, trk2, endPt[inx].pos ) + REGRESS_CHECK_ANGLE( "Angle", trk1, trk2, endPt[inx].angle ) + int inx1 = trk1->endPt[inx].index; + track_cp trk1x = GetTrkEndTrk( trk1, inx ); + if ( trk1x ) + inx1 = GetTrkIndex( trk1x ); + int inx2 = trk2->endPt[inx].index; + if ( inx1 != inx2 ) { + sprintf( cp, "Index: Actual` %d, Expected %d\n", inx1, inx2 ); + return FALSE; + } + REGRESS_CHECK_INT( "Option", trk1, trk2, endPt[inx].option ) + } + if ( trackCmds( GetTrkType( trk1 ) )->compare == NULL ) + return TRUE; + return trackCmds( GetTrkType( trk1 ) )->compare( trk1, trk2 ); +} + /***************************************************************************** * @@ -1221,9 +1383,9 @@ EXPORT void InitCmdAboveBelow( void ) { wIcon_p bm_p; bm_p = wIconCreatePixMap( above_xpm ); - AddToolbarButton( "cmdAbove", bm_p, IC_SELECTED, (addButtonCallBack_t)SelectAbove, NULL ); + AddToolbarButton( "cmdAbove", bm_p, IC_SELECTED|IC_POPUP, (addButtonCallBack_t)SelectAbove, NULL ); bm_p = wIconCreatePixMap( below_xpm ); - AddToolbarButton( "cmdBelow", bm_p, IC_SELECTED, (addButtonCallBack_t)SelectBelow, NULL ); + AddToolbarButton( "cmdBelow", bm_p, IC_SELECTED|IC_POPUP, (addButtonCallBack_t)SelectBelow, NULL ); } /***************************************************************************** @@ -1244,6 +1406,15 @@ EXPORT BOOL_T ReadTrack( char * line ) { TRKINX_T inx, lo, hi; int cmp; + if (strncmp( paramLine, "TABLEEDGE ", 10 ) == 0) { + ReadTableEdge( paramLine+10 ); + return TRUE; + } + if (strncmp( paramLine, "TEXT ", 5 ) == 0) { + ReadText( paramLine+5 ); + return TRUE; + } + if (bsearchRead) { if (sortedCmds == NULL) { sortedCmds = (trackCmd_t**)MyMalloc( (trackCmds_da.cnt-1) * sizeof *(trackCmd_t*)0 ); @@ -1258,8 +1429,7 @@ if (bsearchRead) { inx = (lo+hi)/2; cmp = strncmp( line, sortedCmds[inx]->name, strlen(sortedCmds[inx]->name) ); if (cmp == 0) { - sortedCmds[inx]->read(line); - return TRUE; + return sortedCmds[inx]->read(line); } else if (cmp < 0) { hi = inx-1; } else { @@ -1269,28 +1439,33 @@ if (bsearchRead) { } else { for (inx=1; inx<trackCmds_da.cnt; inx++) { if (strncmp( line, trackCmds(inx)->name, strlen(trackCmds(inx)->name) ) == 0 ) { - trackCmds(inx)->read( line ); - return TRUE; + trackCmds(inx)->read( line ); + // Return TRUE means we found the object type and processed it + // Any errors will be handled by the callee's: + // Either skip the definition (ReadSegs) or skip the remainder of the file (InputError) + return TRUE; } } } - if (strncmp( paramLine, "TABLEEDGE ", 10 ) == 0) - return ReadTableEdge( paramLine+10 ); - if (strncmp( paramLine, "TEXT ", 5 ) == 0) - return ReadText( paramLine+5 ); + // Object type not found return FALSE; } -EXPORT BOOL_T WriteTracks( FILE * f ) +EXPORT BOOL_T WriteTracks( FILE * f, wBool_t bFull ) { track_p trk; BOOL_T rc = TRUE; - RenumberTracks(); + if ( bFull ) + RenumberTracks(); + if ( !bFull ) + bWriteEndPtDirectIndex = TRUE; TRK_ITERATE( trk ) { rc &= trackCmds(GetTrkType(trk))->write( trk, f ); } - rc &= WriteCars( f ); + bWriteEndPtDirectIndex = FALSE; + if ( bFull ) + rc &= WriteCars( f ); return rc; } @@ -1302,7 +1477,9 @@ EXPORT void ImportStart( void ) } -EXPORT void ImportEnd( void ) + + +EXPORT void ImportEnd( coOrd offset, wBool_t import, wBool_t inPlace ) { track_p to_firstOld; wIndex_t trackCountOld; @@ -1310,51 +1487,98 @@ EXPORT void ImportEnd( void ) coOrd pos; wPos_t x, y; wPos_t ww, hh; + wBool_t offscreen = FALSE; + + double xmin = 0.0; + double xmax = 0.0; + double ymin = 0.0; double ymax = 0.0; // get the current mouse position GetMousePosition( &x, &y ); mainD.Pix2CoOrd( &mainD, x, y, &pos ); + // get the size of the drawing area wDrawGetSize( mainD.d, &ww, &hh ); - // in case the pointer is close to the edge or above the drawing area - // recalculate the destination position so the pasted part remains visible - if( abs( y - hh ) < CLOSETOTHEEDGE ) { - for ( trk=*importTrack; trk; trk=trk->next ) { - if (!IsTrackDeleted(trk) && trk->hi.y > ymax ) { - ymax = trk->hi.y; - } + coOrd middle_screen; + wPos_t mx,my; + + mx = ww/2; + my = hh/2; + + mainD.Pix2CoOrd( &mainD, mx, my, &middle_screen ); + + + for ( trk=*importTrack; trk; trk=trk->next ) { + if (!IsTrackDeleted(trk)) { + if (trk->hi.y > ymax ) ymax = trk->hi.y; + if (trk->lo.y < ymin ) ymin = trk->lo.y; + if (trk->hi.x > xmax ) xmax = trk->hi.x; + if (trk->lo.x < xmin ) xmin = trk->lo.x; } - pos.y -= ymax; } - + + coOrd size = {xmax-xmin,ymax-ymin}; + + + + if (import) { + offset = zero; + } else if (!inPlace) { + //If cursor is off drawing area - cursor is in middle screen + if ((x<LBORDER) || (x>(ww-RBORDER)) || (y<BBORDER) || (y>(hh-TBORDER))) { + pos.x = middle_screen.x; + pos.y = middle_screen.y; + } + offset.x += pos.x; + offset.y += pos.y; + } + + coOrd middle_object; + + middle_object.x = offset.x + (size.x/2); + middle_object.y = offset.y + (size.y/2); + + wPos_t ox,oy; + mainD.CoOrd2Pix( &mainD, middle_object, &ox, &oy ); + + if ((ox<0) || (ox>ww) || (oy<0) || (oy>hh) ) offscreen = TRUE; + to_firstOld = to_first; to_first = *importTrack; trackCountOld = trackCount; ResolveIndex(); to_first = to_firstOld; RenumberTracks(); - DrawMapBoundingBox( FALSE ); // move the imported track into place for ( trk=*importTrack; trk; trk=trk->next ) if (!IsTrackDeleted(trk)) { - MoveTrack( trk, pos );// mainD.orig ); + coOrd move; + move.x = offset.x; + move.y = offset.y; + MoveTrack( trk, move );// mainD.orig ); trk->bits |= TB_SELECTED; DrawTrack( trk, &mainD, wDrawColorBlack ); } - DrawMapBoundingBox( TRUE ); importTrack = NULL; trackCount = trackCountOld; InfoCount( trackCount ); + // Pan screen if needed to center of new + if (offscreen) { + panCenter = middle_object; + PanHere((void*)0); + } } - -EXPORT BOOL_T ExportTracks( FILE * f ) +/******* + * Move Selected Tracks to origin zero and write out + *******/ +EXPORT BOOL_T ExportTracks( FILE * f, coOrd * offset) { track_p trk; - coOrd xlat, orig; + coOrd xlat,orig; exportingTracks = TRUE; orig = mapD.size; @@ -1368,8 +1592,9 @@ EXPORT BOOL_T ExportTracks( FILE * f ) trk->index = ++max_index; } } - orig.x -= trackGauge; - orig.y -= trackGauge; + + *offset = orig; + xlat.x = - orig.x; xlat.y = - orig.y; TRK_ITERATE( trk ) { @@ -1527,13 +1752,13 @@ nextEndPt:; if (auditStop) if (NoticeMessage( MSG_AUDIT_WRITE_FILE, _("Yes"), _("No"))) { fprintf( auditFile, "# before undo\n" ); - WriteTracks(auditFile); + WriteTracks(auditFile, TRUE); Rdump( auditFile ); if (strcmp("undoUndo",event)==0) { fprintf( auditFile, "# failure in undo\n" ); } else if (UndoUndo()) { fprintf( auditFile, "# after undo\n" ); - WriteTracks(auditFile); + WriteTracks(auditFile, TRUE); Rdump( auditFile ); } else { fprintf( auditFile, "# undo stack is empty\n" ); @@ -1584,21 +1809,33 @@ EXPORT void ComputeBoundingBox( track_p trk ) EXPORT DIST_T EndPtDescriptionDistance( coOrd pos, track_p trk, - EPINX_T ep ) + EPINX_T ep, + coOrd *dpos, + BOOL_T show_hidden, + BOOL_T * hidden) { elev_t *e; coOrd pos1; track_p trk1; + *dpos = pos; + if (hidden) *hidden = FALSE; e = &trk->endPt[ep].elev; - if ((e->option&ELEV_MASK)==ELEV_NONE || - (e->option&ELEV_VISIBLE)==0 ) + if ((e->option&ELEV_MASK)==ELEV_NONE) + return 100000; + if (((e->option&ELEV_VISIBLE)==0) && !show_hidden) return 100000; if ((trk1=GetTrkEndTrk(trk,ep)) && GetTrkIndex(trk1)<GetTrkIndex(trk)) return 100000; + if ((e->option&ELEV_VISIBLE)==0) { //Hidden - disregard offset + if (hidden) *hidden = TRUE; + return FindDistance( GetTrkEndPos(trk,ep), pos ); + } /*REORIGIN( pos1, e->doff, GetTrkEndPos(trk,ep), GetTrkEndAngle(trk,ep) );*/ pos1 = GetTrkEndPos(trk,ep); pos1.x += e->doff.x; pos1.y += e->doff.y; + *dpos = pos1; + if (hidden) *hidden = !(e->option&ELEV_VISIBLE); return FindDistance( pos1, pos ); } @@ -1610,22 +1847,21 @@ EXPORT STATUS_T EndPtDescriptionMove( coOrd pos ) { static coOrd p0, p1; + static BOOL_T editState = FALSE; elev_t *e, *e1; - wDrawColor color; track_p trk1; e = &trk->endPt[ep].elev; switch (action) { case C_DOWN: p0 = GetTrkEndPos(trk,ep); - /*REORIGIN( p0, e->doff, GetTrkEndPos(trk,ep), GetTrkEndAngle(trk,ep) );*/ - + p1 = pos; + e->option |= ELEV_VISIBLE; //Make sure we make visible + DrawEndElev( &mainD, trk, ep, wDrawColorWhite ); + /*no break*/ case C_MOVE: case C_UP: - if (action != C_DOWN) - DrawLine( &tempD, p0, p1, 0, wDrawColorBlack ); - color = GetTrkColor( trk, &mainD ); - DrawEndElev( &tempD, trk, ep, color ); + editState = TRUE; p1 = pos; e->doff.x = (pos.x-p0.x); e->doff.y = (pos.y-p0.y); @@ -1633,15 +1869,18 @@ EXPORT STATUS_T EndPtDescriptionMove( e1 = &trk1->endPt[GetEndPtConnectedToMe(trk1,trk)].elev; e1->doff = e->doff; } - DrawEndElev( &tempD, trk, ep, color ); - if (action != C_UP) - DrawLine( &tempD, p0, p1, 0, wDrawColorBlack ); - MainRedraw(); - MapRedraw(); + if ( action == C_UP ) { + editState = FALSE; + wDrawColor color = GetTrkColor( trk, &mainD ); + DrawEndElev( &mainD, trk, ep, color ); + } return action==C_UP?C_TERMINATE:C_CONTINUE; case C_REDRAW: - DrawLine( &tempD, p0, p1, 0, wDrawColorBlack ); + DrawEndElev( &tempD, trk, ep, wDrawColorBlue ); + if ( editState ) { + DrawLine( &tempD, p0, p1, 0, wDrawColorBlue ); + } break; } return C_CONTINUE; @@ -1692,12 +1931,12 @@ EXPORT void LoosenTracks( void ) } } if (count) - MainRedraw(); + MainRedraw(); // LoosenTracks else InfoMessage(_("No tracks loosened")); } -EXPORT void ConnectTracks( track_p trk0, EPINX_T inx0, track_p trk1, EPINX_T inx1 ) +EXPORT int ConnectTracks( track_p trk0, EPINX_T inx0, track_p trk1, EPINX_T inx1 ) { DIST_T d; ANGLE_T a; @@ -1705,31 +1944,23 @@ EXPORT void ConnectTracks( track_p trk0, EPINX_T inx0, track_p trk1, EPINX_T inx if ( !IsTrack(trk0) ) { NoticeMessage( _("Connecting a non-track(%d) to (%d)"), _("Continue"), NULL, GetTrkIndex(trk0), GetTrkIndex(trk1) ); - return; + return -1; } if ( !IsTrack(trk1) ) { NoticeMessage( _("Connecting a non-track(%d) to (%d)"), _("Continue"), NULL, GetTrkIndex(trk1), GetTrkIndex(trk0) ); - return; + return -1; } pos0 = trk0->endPt[inx0].pos; pos1 = trk1->endPt[inx1].pos; LOG( log_track, 3, ( "ConnectTracks( T%d[%d] @ [%0.3f, %0.3f] = T%d[%d] @ [%0.3f %0.3f]\n", trk0->index, inx0, pos0.x, pos0.y, trk1->index, inx1, pos1.x, pos1.y ) ) d = FindDistance( pos0, pos1 ); - a = NormalizeAngle( trk0->endPt[inx0].angle - - trk1->endPt[inx1].angle + 180.0 ); - if (d > connectDistance || (a > connectAngle && a < 360.0 - connectAngle) || (log_endPt>0 && logTable(log_endPt).level>=1)) { -#ifndef WINDOWS - LogPrintf( "connectTracks: T%d[%d] T%d[%d] d=%0.3f a=%0.3f\n %d ", - trk0->index, inx0, trk1->index, inx1, d, a, trk0->index ); - /*PrintEndPt( logFile, trk0, 0 ); - PrintEndPt( logFile, trk0, 1 );???*/ - LogPrintf( "\n %d ", trk1->index ); - /*PrintEndPt( logFile, trk1, 0 ); - PrintEndPt( logFile, trk1, 1 );???*/ - LogPrintf("\n"); -#endif - if (d > connectDistance || (a > connectAngle && a < 360.0 - connectAngle)) - NoticeMessage( MSG_CONNECT_TRK, _("Continue"), NULL, trk0->index, inx0, trk1->index, inx1, d, a ); + a = fabs(DifferenceBetweenAngles( trk0->endPt[inx0].angle, + trk1->endPt[inx1].angle + 180.0 )); + if (d > connectDistance || (a > connectAngle ) ) { + LOG( log_endPt, 1, ( "connectTracks: T%d[%d] T%d[%d] d=%0.3f a=%0.3f\n", + trk0->index, inx0, trk1->index, inx1, d, a ) ); + NoticeMessage( MSG_CONNECT_TRK, _("Continue"), NULL, trk0->index, inx0, trk1->index, inx1, d, a ); + return -1; /* Stop connecting out of alignment tracks! */ } UndoModify( trk0 ); UndoModify( trk1 ); @@ -1738,6 +1969,7 @@ LOG( log_track, 3, ( "ConnectTracks( T%d[%d] @ [%0.3f, %0.3f] = T%d[%d] @ [%0.3f trk0->endPt[inx0].track = trk1; trk1->endPt[inx1].track = trk0; AuditTracks( "connectTracks T%d[%d], T%d[%d]", trk0->index, inx0, trk1->index, inx1 ); + return 0; } @@ -1834,7 +2066,6 @@ LOG( log_track, 2, ( "SplitTrack( T%d[%d], (%0.3f %0.3f)\n", trk->index, ep, pos } else { LOG( log_track, 2, ( " at endPt (no connection)\n") ) } - *leftover = trk2; DrawNewTrack( trk ); @@ -1855,7 +2086,6 @@ LOG( log_track, 2, ( "SplitTrack( T%d[%d], (%0.3f %0.3f)\n", trk->index, ep, pos LOG( log_track, 2, ( " at endPt (no connection)\n") ) } DrawNewTrack( trk ); - } else { /* TODO circle's don't have ep's */ trk2 = GetTrkEndTrk( trk, ep ); @@ -1878,13 +2108,13 @@ LOG( log_track, 2, ( "SplitTrack( T%d[%d], (%0.3f %0.3f)\n", trk->index, ep, pos trkl = *leftover; ep0 = epl; if ( !disconnect ) - ConnectTracks( trk, ep, trkl, ep0 ); - ep0 = 1-ep0; + ConnectTracks( trk, ep, trkl, epl ); + ep0 = 1-epl; while ( 1 ) { CopyAttributes( trk, trkl ); ClrTrkElev( trkl ); trk0 = GetTrkEndTrk(trkl,ep0); - if ( trk0 == NULL ) + if ( trk0 == NULL || trk0->type == T_TURNOUT ) break; ep0 = 1-GetEndPtConnectedToMe(trk0,trkl); trkl = trk0; @@ -1901,7 +2131,7 @@ LOG( log_track, 2, ( "SplitTrack( T%d[%d], (%0.3f %0.3f)\n", trk->index, ep, pos while ( 1 ) { DrawNewTrack( trkl ); trk0 = GetTrkEndTrk(trkl,ep0); - if ( trk0 == NULL || trk0 == trk2 ) + if ( trk0 == NULL || trk0 == trk2 || trk0->type == T_TURNOUT) break; ep0 = 1-GetEndPtConnectedToMe(trk0,trkl); trkl = trk0; @@ -1970,14 +2200,14 @@ EXPORT BOOL_T RemoveTrack( track_p * trk, EPINX_T * ep, DIST_T *dist ) } dist1 = *dist; *dist = 0.0; - return TrimTrack( *trk, *ep, dist1 ); + return TrimTrack( *trk, *ep, dist1, zero, 0.0, 0.0, zero ); } -EXPORT BOOL_T TrimTrack( track_p trk, EPINX_T ep, DIST_T dist ) +EXPORT BOOL_T TrimTrack( track_p trk, EPINX_T ep, DIST_T dist, coOrd pos, ANGLE_T angle, DIST_T radius, coOrd center ) { if (trackCmds(trk->type)->trim) - return trackCmds(trk->type)->trim( trk, ep, dist ); + return trackCmds(trk->type)->trim( trk, ep, dist, pos, angle, radius, center ); else return FALSE; } @@ -1992,6 +2222,130 @@ EXPORT BOOL_T MergeTracks( track_p trk0, EPINX_T ep0, track_p trk1, EPINX_T ep1 return FALSE; } +EXPORT STATUS_T ExtendTrackFromOrig( track_p trk, wAction_t action, coOrd pos ) +{ + static EPINX_T ep; + static coOrd end_pos; + static BOOL_T valid; + DIST_T d; + track_p trk1; + trackParams_t params; + static wBool_t curved; + static ANGLE_T end_angle; + + switch ( action ) { + case C_DOWN: + ep = PickUnconnectedEndPoint( pos, trk ); + if ( ep == -1 ) + return C_ERROR; + pos = GetTrkEndPos(trk,ep); + if (!GetTrackParams(PARAMS_CORNU,trk,pos,¶ms)) return C_ERROR; + end_pos = pos; + if (params.type == curveTypeCurve) { + curved = TRUE; + tempSegs(0).type = SEG_CRVTRK; + tempSegs(0).width = 0; + tempSegs(0).u.c.radius = params.arcR; + tempSegs(0).u.c.center = params.arcP; + tempSegs(0).u.c.a0 = FindAngle(params.arcP,GetTrkEndPos(trk,ep)); + tempSegs(0).u.c.a1 = 0; + } else { + curved = FALSE; + tempSegs(0).type = SEG_STRTRK; + tempSegs(0).width = 0; + tempSegs(0).u.l.pos[0] = tempSegs(0).u.l.pos[1] = GetTrkEndPos( trk, ep ); + } + valid = FALSE; + InfoMessage( _("Drag to change track length") ); + return C_CONTINUE; + /*no break*/ + case C_MOVE: + if (curved) { + //Normalize pos + PointOnCircle( &pos, tempSegs(0).u.c.center, tempSegs(0).u.c.radius, FindAngle(tempSegs(0).u.c.center,pos) ); + ANGLE_T a = FindAngle(tempSegs(0).u.c.center,pos)-FindAngle(tempSegs(0).u.c.center,end_pos); + d = fabs(a)*2*M_PI/360*tempSegs(0).u.c.radius; + if ( d <= minLength ) { + if (action == C_MOVE) + ErrorMessage( MSG_TRK_TOO_SHORT, _("Connecting "), PutDim(fabs(minLength-d)) ); + valid = FALSE; + return C_CONTINUE; + } + //Restrict to outside track + ANGLE_T diff = NormalizeAngle(GetTrkEndAngle(trk, ep)-FindAngle(end_pos,pos)); + if (diff>90.0 && diff<270.0) { + valid = FALSE; + tempSegs(0).u.c.a1 = 0; + tempSegs(0).u.c.a0 = end_angle; + InfoMessage( _("Inside turnout track")); + return C_CONTINUE; + } + end_angle = GetTrkEndAngle( trk, ep ); + a = FindAngle(tempSegs(0).u.c.center, pos ); + PointOnCircle( &pos, tempSegs(0).u.c.center, tempSegs(0).u.c.radius, a ); + ANGLE_T a2 = FindAngle(tempSegs(0).u.c.center,end_pos); + if ((end_angle > 180 && (a2>90 && a2 <270)) || + (end_angle < 180 && (a2<90 || a2 >270))) { + tempSegs(0).u.c.a0 = a2; + tempSegs(0).u.c.a1 = NormalizeAngle(a-a2); + } else { + tempSegs(0).u.c.a0 = a; + tempSegs(0).u.c.a1 = NormalizeAngle(a2-a); + } + tempSegs_da.cnt = 1; + valid = TRUE; + if (action == C_MOVE) + InfoMessage( _("Curve: Length=%s Radius=%0.3f Arc=%0.3f"), + FormatDistance( d ), FormatDistance(tempSegs(0).u.c.radius), PutAngle( fabs(a) ) ); + return C_CONTINUE; + } else { + d = FindDistance( end_pos, pos ); + valid = TRUE; + if ( d <= minLength ) { + if (action == C_MOVE) + ErrorMessage( MSG_TRK_TOO_SHORT, _("Connecting "), PutDim(fabs(minLength-d)) ); + valid = FALSE; + return C_CONTINUE; + } + ANGLE_T diff = NormalizeAngle(GetTrkEndAngle( trk, ep )-FindAngle(end_pos, pos)); + if (diff>=90.0 && diff<=270.0) { + valid = FALSE; + tempSegs(0).u.c.a1 = 0; + tempSegs(0).u.c.a0 = end_angle; + InfoMessage( _("Inside turnout track")); + return C_CONTINUE; + } + Translate( &tempSegs(0).u.l.pos[1], tempSegs(0).u.l.pos[0], GetTrkEndAngle( trk, ep ), d ); + tempSegs_da.cnt = 1; + if (action == C_MOVE) + InfoMessage( _("Straight: Length=%s Angle=%0.3f"), + FormatDistance( d ), PutAngle( GetTrkEndAngle( trk, ep ) ) ); + } + return C_CONTINUE; + + case C_UP: + if (!valid) + return C_TERMINATE; + UndrawNewTrack( trk ); + EPINX_T jp; + if (curved) { + trk1 = NewCurvedTrack(tempSegs(0).u.c.center, tempSegs(0).u.c.radius, tempSegs(0).u.c.a0, tempSegs(0).u.c.a1, 0); + jp = PickUnconnectedEndPoint(end_pos,trk1); + } else { + trk1 = NewStraightTrack( tempSegs(0).u.l.pos[0], tempSegs(0).u.l.pos[1] ); + jp = 0; + } + CopyAttributes( trk, trk1 ); + ConnectTracks( trk, ep, trk1, jp ); + DrawNewTrack( trk ); + DrawNewTrack( trk1 ); + return C_TERMINATE; + + default: + ; + } + return C_ERROR; +} EXPORT STATUS_T ExtendStraightFromOrig( track_p trk, wAction_t action, coOrd pos ) { @@ -2106,6 +2460,9 @@ EXPORT char * GetTrkTypeName( track_p trk ) return trackCmds(trk->type)->name; } +/* + * Note Misnomer - this function also gets the normal length - enumerate deals with flextrack length + */ EXPORT DIST_T GetFlexLength( track_p trk0, EPINX_T ep, coOrd * pos ) { @@ -2153,9 +2510,33 @@ EXPORT DIST_T GetTrkLength( track_p trk, EPINX_T ep0, EPINX_T ep1 ) } else { pos0 = GetTrkEndPos(trk,ep0); if (ep1==-1) { + // Usual case for asking about distance to center of turnout for grades + if (trk->type==T_TURNOUT) { + trackParams_t trackParamsData; + trackParamsData.ep = ep0; + if (trackCmds(trk->type)->getTrackParams != NULL) { + //Find distance to centroid of end points * 2 or actual length if epCnt < 3 + trackCmds(trk->type)->getTrackParams(PARAMS_TURNOUT,trk,pos0,&trackParamsData); + return trackParamsData.len/2.0; + } + } pos1.x = (trk->hi.x+trk->lo.x)/2.0; pos1.y = (trk->hi.y+trk->lo.y)/2.0; } else { + if (trk->type==T_TURNOUT) { + pos1 = GetTrkEndPos(trk,ep1); + trackParams_t trackParamsData; + trackParamsData.ep = ep0; + if (trackCmds(trk->type)->getTrackParams != NULL) { + //Find distance via centroid of end points or actual length if epCnt < 3 + trackCmds(trk->type)->getTrackParams(PARAMS_TURNOUT,trk,pos0,&trackParamsData); + d = trackParamsData.len/2.0; + trackParamsData.ep = ep1; + trackCmds(trk->type)->getTrackParams(PARAMS_TURNOUT,trk,pos1,&trackParamsData); + d += trackParamsData.len/2.0; + return d; + } + } pos1 = GetTrkEndPos(trk,ep1); } pos1.x -= pos0.x; @@ -2169,6 +2550,8 @@ EXPORT DIST_T GetTrkLength( track_p trk, EPINX_T ep0, EPINX_T ep1 ) #define DRAW_TUNNEL_DASH (1) #define DRAW_TUNNEL_SOLID (2) EXPORT long drawTunnel = DRAW_TUNNEL_DASH; +EXPORT long colorTrack; +EXPORT long colorDraw; /****************************************************************************** * @@ -2179,6 +2562,24 @@ EXPORT long drawTunnel = DRAW_TUNNEL_DASH; EXPORT long tieDrawMode = TIEDRAWMODE_SOLID; EXPORT wDrawColor tieColor; +static wBool_t DoDrawTies( drawCmd_p d, track_cp trk ) +{ + DIST_T scale2rail = (d->options&DC_PRINT)?(twoRailScale*2+1):twoRailScale; + if ( !trk ) + return FALSE; + if (GetTrkNoTies(trk)) + return FALSE; //No Ties for this Track + if ( tieDrawMode == TIEDRAWMODE_NONE ) + return FALSE; + if ( d == &mapD ) + return FALSE; + if ( d->scale >= scale2rail ) + return FALSE; + if ( !(GetTrkVisible(trk) || drawTunnel==DRAW_TUNNEL_SOLID) ) + return FALSE; + return TRUE; +} + EXPORT void DrawTie( drawCmd_p d, coOrd pos, @@ -2188,7 +2589,9 @@ EXPORT void DrawTie( wDrawColor color, BOOL_T solid ) { - coOrd p[4], lo, hi; + coOrd lo, hi; + coOrd p[4]; + int t[4]; length /= 2; width /= 2; @@ -2198,6 +2601,7 @@ EXPORT void DrawTie( hi.x += length; hi.y += length; angle += 90; + Translate( &p[0], pos, angle, length ); Translate( &p[1], p[0], angle+90, width ); Translate( &p[0], p[0], angle-90, width ); @@ -2205,6 +2609,10 @@ EXPORT void DrawTie( Translate( &p[3], p[2], angle-90, width ); Translate( &p[2], p[2], angle+90, width ); + for (int i=0;i<4;i++) { + t[i] = 0; + } + if ( d == &mainD ) { lo.x -= RBORDER/mainD.dpi*mainD.scale; lo.y -= TBORDER/mainD.dpi*mainD.scale; @@ -2214,19 +2622,16 @@ EXPORT void DrawTie( return; } if ( solid ) { - DrawFillPoly( d, 4, p, color ); + DrawPoly( d, 4, p, t, color, 0, 1, 0 ); } else { - DrawLine( d, p[0], p[1], 0, color ); - DrawLine( d, p[1], p[2], 0, color ); - DrawLine( d, p[2], p[3], 0, color ); - DrawLine( d, p[3], p[0], 0, color ); + DrawPoly( d, 4, p, t, color, 0, 0, 0); } } -EXPORT void DrawCurvedTies( +static void DrawCurvedTies( drawCmd_p d, - track_p trk, + SCALEINX_T scaleInx, coOrd p, DIST_T r, ANGLE_T a0, @@ -2239,27 +2644,27 @@ EXPORT void DrawCurvedTies( coOrd pos; int cnt; - if ( (d->funcs->options&wDrawOptTemp) != 0 ) + if ( (d->options&DC_SIMPLE) != 0 ) return; - if ( trk == NULL ) - return; - - td = GetScaleTieData(GetTrkScale(trk)); - if ( (!GetTrkVisible(trk)) && drawTunnel!=DRAW_TUNNEL_SOLID ) + if ( scaleInx < 0 ) return; + td = GetScaleTieData( scaleInx ); + if (color == wDrawColorBlack) color = tieColor; len = 2*M_PI*r*a1/360.0; - cnt = (int)(len/td->spacing); - if ( len-td->spacing*cnt-td->width > (td->spacing-td->width)/2 ) + cnt = (int)floor(len/td->spacing+0.5); + if ( len-td->spacing*cnt-(td->width/2) > (td->spacing-td->width)/2 ) { cnt++; + } if ( cnt != 0 ) { - dang = a1/cnt; + dang = (360.0*(len)/cnt)/(2*M_PI*r); for ( ang=a0+dang/2; cnt; cnt--,ang+=dang ) { PointOnCircle( &pos, p, r, ang ); DrawTie( d, pos, ang+90, td->length, td->width, color, tieDrawMode==TIEDRAWMODE_SOLID ); } + } } @@ -2273,11 +2678,11 @@ EXPORT void DrawCurvedTrack( coOrd p0, coOrd p1, track_p trk, - DIST_T trackGauge, wDrawColor color, long options ) { DIST_T scale2rail; + DIST_T trackGauge = GetTrkGauge(trk); wDrawWidth width=0; trkSeg_p segPtr; @@ -2295,9 +2700,10 @@ EXPORT void DrawCurvedTrack( } scale2rail = (d->options&DC_PRINT)?(twoRailScale*2+1):twoRailScale; - if (options&DTS_THICK2) - width = 2; - if (options&DTS_THICK3) + width = trk ? GetTrkWidth( trk ): 0; + if ( d->options&DC_THICK ) + width = 3; + if ( color == wDrawColorPreviewSelected || color == wDrawColorPreviewUnselected ) width = 3; #ifdef WINDOWS width *= (wDrawWidth)(d->dpi/mainD.dpi); @@ -2308,21 +2714,15 @@ EXPORT void DrawCurvedTrack( LOG( log_track, 4, ( "DST( (%0.3f %0.3f) R%0.3f A%0.3f..%0.3f)\n", p.x, p.y, r, a0, a1 ) ) - if ( (options&DTS_TIES) != 0 && trk && - tieDrawMode!=TIEDRAWMODE_NONE && - d!=&mapD && - (d->options&DC_TIES)!=0 && - d->scale<scale2rail/2 ) - DrawCurvedTies( d, trk, p, r, a0, a1, color ); + if ( DoDrawTies( d, trk ) ) + DrawCurvedTies( d, GetTrkScale(trk), p, r, a0, a1, color ); if (color == wDrawColorBlack) color = normalColor; if ( d->scale >= scale2rail ) { DrawArc( d, p, r, a0, a1, ((d->scale<32) && centerDrawMode && !(options&DTS_NOCENTER)) ? 1 : 0, width, color ); - } else if (d->options & DC_QUICK) { - DrawArc( d, p, r, a0, a1, ((d->scale<32) && centerDrawMode && !(options&DTS_NOCENTER)) ? 1 : 0, 0, color ); } else { if ( (d->scale <= 1 && (d->options&DC_SIMPLE)==0) || (d->options&DC_CENTERLINE)!=0 - || (d->scale <= scale2rail/2 && d->options&DC_PRINT && printCenterLines)) { // if printing two rails respect print CenterLine option + || (d->scale <= scale2rail/2 && ((d->options&DC_PRINT) && printCenterLines))) { // if printing two rails respect print CenterLine option long options = d->options; d->options |= DC_DASH; DrawArc( d, p, r, a0, a1, 0, 0, color ); @@ -2340,12 +2740,44 @@ LOG( log_track, 4, ( "DST( (%0.3f %0.3f) R%0.3f A%0.3f..%0.3f)\n", } } } + if (trk && GetTrkBridge( trk ) ) { + + ANGLE_T a2,a3; + coOrd pp0,pp1,pp2,pp3; + + a2 = a0+R2D(trackGauge*1.0/r); + a3 = a1-R2D(trackGauge*2.0/r); + + wDrawWidth width2 = (wDrawWidth)round((2.0 * d->dpi)/75.0); + + DrawArc( d, p, r+(trackGauge*1.5), a2, a3, 0, width2, color ); + + PointOnCircle(&pp0,p,r+(trackGauge*1.5),a2); + PointOnCircle(&pp1,p,r+(trackGauge*1.5),a3+a2); + + Translate( &pp2,pp0, a2-90+45, trackGauge); + DrawLine( d, pp0, pp2, width2, color ); + Translate( &pp3,pp1, a2+a3+90-45, trackGauge); + DrawLine( d, pp1, pp3, width2, color ); + + DrawArc( d, p, r-(trackGauge*1.5), a2, a3, 0, width2, color ); + + PointOnCircle(&pp0,p,r-(trackGauge*1.5),a2); + PointOnCircle(&pp1,p,r-(trackGauge*1.5),a3+a2); + + Translate( &pp2,pp0, a2-90-45, trackGauge); + DrawLine( d, pp0, pp2, width2, color ); + Translate( &pp3,pp1, a2+a3+90+45, trackGauge); + DrawLine( d, pp1, pp3, width2, color ); + + } + } -EXPORT void DrawStraightTies( +static void DrawStraightTies( drawCmd_p d, - track_p trk, + SCALEINX_T scaleInx, coOrd p0, coOrd p1, wDrawColor color ) @@ -2357,25 +2789,24 @@ EXPORT void DrawStraightTies( int cnt; ANGLE_T angle; - if ( (d->funcs->options&wDrawOptTemp) != 0 ) - return; - if ( trk == NULL ) + if ( (d->options&DC_SIMPLE) != 0 ) return; - td = GetScaleTieData(GetTrkScale(trk)); - if ( (!GetTrkVisible(trk)) && drawTunnel!=DRAW_TUNNEL_SOLID ) - return; if ( color == wDrawColorBlack ) color = tieColor; - td = GetScaleTieData( GetTrkScale(trk) ); + if ( scaleInx < 0 ) + return; + td = GetScaleTieData( scaleInx ); len = FindDistance( p0, p1 ); len -= tieOff0+tieOff1; angle = FindAngle( p0, p1 ); - cnt = (int)(len/td->spacing); - if ( len-td->spacing*cnt-td->width > (td->spacing-td->width)/2 ) + cnt = (int)floor(len/td->spacing+0.5); + if ( len-td->spacing*cnt-td->width > (td->spacing-td->width)/2 ) { cnt++; + } if ( cnt != 0 ) { - dlen = len/cnt; + dlen = FindDistance( p0, p1 )/cnt; + double endsize = FindDistance( p0, p1 )-cnt*dlen-td->width; for ( len=dlen/2; cnt; cnt--,len+=dlen ) { Translate( &pos, p0, angle, len ); DrawTie( d, pos, angle, td->length, td->width, color, tieDrawMode==TIEDRAWMODE_SOLID ); @@ -2389,13 +2820,13 @@ EXPORT void DrawStraightTrack( coOrd p0, coOrd p1, ANGLE_T angle, - track_p trk, - DIST_T trackGauge, + track_cp trk, wDrawColor color, long options ) { coOrd pp0, pp1; DIST_T scale2rail; + DIST_T trackGauge = GetTrkGauge(trk); wDrawWidth width=0; trkSeg_p segPtr; @@ -2414,9 +2845,10 @@ EXPORT void DrawStraightTrack( scale2rail = (d->options&DC_PRINT)?(twoRailScale*2+1):twoRailScale; - if (options&DTS_THICK2) - width = 2; - if (options&DTS_THICK3) + width = trk ? GetTrkWidth( trk ): 0; + if ( d->options&DC_THICK ) + width = 3; + if ( color == wDrawColorPreviewSelected || color == wDrawColorPreviewUnselected ) width = 3; #ifdef WINDOWS width *= (wDrawWidth)(d->dpi/mainD.dpi); @@ -2426,21 +2858,15 @@ EXPORT void DrawStraightTrack( #endif LOG( log_track, 4, ( "DST( (%0.3f %0.3f) .. (%0.3f..%0.3f)\n", p0.x, p0.y, p1.x, p1.y ) ) - if ( (options&DTS_TIES) != 0 && trk && - tieDrawMode!=TIEDRAWMODE_NONE && - d!=&mapD && - (d->options&DC_TIES)!=0 && - d->scale<scale2rail/2 ) - DrawStraightTies( d, trk, p0, p1, color ); + if ( DoDrawTies( d, trk ) ) + DrawStraightTies( d, GetTrkScale(trk), p0, p1, color ); if (color == wDrawColorBlack) color = normalColor; if ( d->scale >= scale2rail ) { DrawLine( d, p0, p1, width, color ); - } else if (d->options&DC_QUICK) { - DrawLine( d, p0, p1, 0, color ); } else { if ( (d->scale <= 1 && (d->options&DC_SIMPLE)==0) || (d->options&DC_CENTERLINE)!=0 - || (d->scale <= scale2rail/2 && d->options&DC_PRINT && printCenterLines)) { // if printing two rails respect print CenterLine option + || (d->scale <= scale2rail/2 && ((d->options&DC_PRINT) && printCenterLines))) { // if printing two rails respect print CenterLine option long options = d->options; d->options |= DC_DASH; DrawLine( d, p0, p1, 0, color ); @@ -2466,37 +2892,68 @@ LOG( log_track, 4, ( "DST( (%0.3f %0.3f) .. (%0.3f..%0.3f)\n", } } } + if (trk && GetTrkBridge( trk ) ) { + + coOrd pp2,pp3; + wDrawWidth width2 = (wDrawWidth)round((2.0 * d->dpi)/75.0); + + Translate( &pp0, p0, angle+90, trackGauge*1.5 ); + Translate( &pp1, p1, angle+90, trackGauge*1.5 ); + Translate( &pp0, pp0, angle+180, trackGauge*1.5 ); + Translate( &pp1, pp1, angle, trackGauge*1.5 ); + DrawLine( d, pp0, pp1, width2, color ); + Translate( &pp2,pp0, angle+90-45, trackGauge); + DrawLine( d, pp0, pp2, width2, color ); + Translate( &pp3,pp1, angle+90+45, trackGauge); + DrawLine( d, pp1, pp3, width2, color ); + + Translate( &pp0, p0, angle-90, trackGauge*1.5 ); + Translate( &pp1, p1, angle-90, trackGauge*1.5 ); + Translate( &pp0, pp0, angle+180, trackGauge*1.5 ); + Translate( &pp1, pp1, angle, trackGauge*1.5 ); + DrawLine( d, pp0, pp1, width2, color ); + Translate( &pp2,pp0, angle-90+45, trackGauge); + DrawLine( d, pp0, pp2, width2, color ); + Translate( &pp3,pp1, angle-90-45, trackGauge); + DrawLine( d, pp1, pp3, width2, color ); + + } } EXPORT wDrawColor GetTrkColor( track_p trk, drawCmd_p d ) { - DIST_T len, elev0, elev1; + DIST_T len, len1, elev0, elev1; ANGLE_T grade = 0.0; if ( IsTrack( trk ) && GetTrkEndPtCnt(trk) == 2 ) { - len = GetTrkLength( trk, 0, 1 ); - if (len>0.1) { - ComputeElev( trk, 0, FALSE, &elev0, NULL ); - ComputeElev( trk, 1, FALSE, &elev1, NULL ); - grade = fabs( (elev1-elev0)/len )*100.0; + if (GetTrkEndElevCachedHeight(trk,0,&elev0,&len) && GetTrkEndElevCachedHeight(trk,1,&elev1,&len1)) { + grade = fabs( (elev1-elev0)/(len+len1))*100.0; + } else { + len = GetTrkLength( trk, 0, 1 ); + if (len>0.1) { + ComputeElev( trk, 0, FALSE, &elev0, NULL, FALSE ); + ComputeElev( trk, 1, FALSE, &elev1, NULL, FALSE ); + grade = fabs( (elev1-elev0)/len )*100.0; + } } } - if ( (d->options&(DC_GROUP)) == 0 ) { - if ( grade > GetLayoutMaxTrackGrade()) - return exceptionColor; - if ( QueryTrack( trk, Q_EXCEPTION ) ) - return exceptionColor; - } - if ( (d->options&(DC_PRINT|DC_GROUP)) == 0 ) { + if ( (d->options&(DC_SIMPLE|DC_SEGTRACK)) != 0 ) + return wDrawColorBlack; + if ( grade > GetLayoutMaxTrackGrade()) + return exceptionColor; + if ( QueryTrack( trk, Q_EXCEPTION ) ) + return exceptionColor; + if ( (d->options&(DC_PRINT)) == 0 ) { if (GetTrkBits(trk)&TB_PROFILEPATH) return profilePathColor; if ((d->options&DC_PRINT)==0 && GetTrkSelected(trk)) return selectedColor; } - if ( (d->options&(DC_GROUP)) == 0 ) { - if ( (IsTrack(trk)?(colorLayers&1):(colorLayers&2)) ) - return GetLayerColor((unsigned int)curTrackLayer); + if ( (IsTrack(trk)?(colorTrack):(colorDraw)) ) { + unsigned int iLayer = GetTrkLayer( trk ); + if (GetLayerUseColor( iLayer ) ) + return GetLayerColor( iLayer ); } return wDrawColorBlack; } @@ -2504,9 +2961,11 @@ EXPORT wDrawColor GetTrkColor( track_p trk, drawCmd_p d ) EXPORT void DrawTrack( track_cp trk, drawCmd_p d, wDrawColor color ) { - DIST_T scale2rail; TRKTYP_T trkTyp; + // Hack for WINDOWS + if ( trk->bits & TB_UNDRAWN ) + return; trkTyp = GetTrkType(trk); curTrackLayer = GetTrkLayer(trk); if (d != &mapD ) { @@ -2519,48 +2978,43 @@ EXPORT void DrawTrack( track_cp trk, drawCmd_p d, wDrawColor color ) if (color == wDrawColorBlack) { color = GetTrkColor( trk, d ); } + if (color == wDrawColorPreviewSelected || color == wDrawColorPreviewUnselected ) { + d->options |= DC_THICK; + } } + if (d == &mapD && !GetLayerOnMap(curTrackLayer)) return; - if ( (IsTrack(trk)?(colorLayers&1):(colorLayers&2)) && + if ( (IsTrack(trk)?(colorTrack):(colorDraw)) && d != &mapD && color == wDrawColorBlack ) - color = GetLayerColor((unsigned int)curTrackLayer); - scale2rail = (d->options&DC_PRINT)?(twoRailScale*2+1):twoRailScale; - if ( (!inDrawTracks) && - tieDrawMode!=TIEDRAWMODE_NONE && - d != &mapD && - d->scale<scale2rail/2 && - QueryTrack(trk, Q_ISTRACK) && - (GetTrkVisible(trk) || drawTunnel==DRAW_TUNNEL_SOLID) ) { - d->options |= DC_TIES; - } + if (GetLayerUseColor((unsigned int)curTrackLayer)) + color = GetLayerColor((unsigned int)curTrackLayer); trackCmds(trkTyp)->draw( trk, d, color ); - if ( (!inDrawTracks) ) { - d->options &= ~DC_TIES; - } d->options &= ~DC_DASH; + d->options &= ~DC_THICK; + DrawTrackElev( trk, d, color!=wDrawColorWhite ); } static void DrawATrack( track_cp trk, wDrawColor color ) { - DrawMapBoundingBox( FALSE ); DrawTrack( trk, &mapD, color ); DrawTrack( trk, &mainD, color ); - DrawMapBoundingBox( TRUE ); } EXPORT void DrawNewTrack( track_cp t ) { + t->bits &= ~TB_UNDRAWN; DrawATrack( t, wDrawColorBlack ); } EXPORT void UndrawNewTrack( track_cp t ) { DrawATrack( t, wDrawColorWhite ); + t->bits |= TB_UNDRAWN; } EXPORT int doDrawPositionIndicator = 1; @@ -2610,7 +3064,7 @@ static void DrawUnconnectedEndPt( drawCmd_p d, coOrd p, ANGLE_T a, DIST_T trackG Translate( &p, p, a+90.0, 0.2 ); Translate( &p0, p, a, trackGauge ); Translate( &p1, p, a-180.0, trackGauge ); - DrawLine( d, p0, p1, (drawUnconnectedEndPt>0)?4:0, (drawUnconnectedEndPt>1)?exceptionColor:color ); + DrawLine( d, p0, p1, (drawUnconnectedEndPt>0)?4:0, (color==wDrawColorWhite)?color:(drawUnconnectedEndPt>1)?exceptionColor:color ); } } @@ -2643,7 +3097,7 @@ EXPORT void DrawEndElev( drawCmd_p d, track_p trk, EPINX_T ep, wDrawColor color case ELEV_GRADE: if ( color == wDrawColorWhite ) { elev0 = grade = elev->u.height; - } else if ( !ComputeElev( trk, ep, FALSE, &elev0, &grade ) ) { + } else if ( !ComputeElev( trk, ep, FALSE, &elev0, &grade, FALSE ) ) { elev0 = grade = 0; gradeOk = FALSE; } @@ -2651,7 +3105,7 @@ EXPORT void DrawEndElev( drawCmd_p d, track_p trk, EPINX_T ep, wDrawColor color elevStr = FormatDistance(elev0); elev->u.height = elev0; } else if (gradeOk) { - sprintf( message, "%0.1f%%", fabs(grade*100.0) ); + sprintf( message, "%0.1f%%", round(fabs(grade*100.0)*10)/10 ); elevStr = message; a = GetTrkEndAngle( trk, ep ); style = BOX_ARROW; @@ -2704,16 +3158,16 @@ EXPORT void DrawEndPt( wDrawWidth width; wDrawWidth width2; - // line width for the tunnel portal, make sure it is rounded correctly - width2 = (wDrawWidth)round((2.0 * d->dpi)/75.0); - if (d->funcs->options&wDrawOptTemp) + if ( (d->options & (DC_SIMPLE|DC_SEGTRACK)) != 0) return; if ( trk && QueryTrack( trk, Q_NODRAWENDPT ) ) return; - if (trk == NULL || ep < 0) return; + // line width for the tunnel portal, make sure it is rounded correctly + width2 = (wDrawWidth)round((2.0 * d->dpi)/75.0); + if (color == wDrawColorBlack) color = normalColor; @@ -2734,17 +3188,20 @@ EXPORT void DrawEndPt( return; sepBoundary = FALSE; - if ((d->options&DC_PRINT)==0 && importTrack == NULL && GetTrkSelected(trk) && (!GetTrkSelected(trk1))) { + if ( inDrawTracks && (d->options&DC_PRINT)==0 && importTrack == NULL && GetTrkSelected(trk) && (!GetTrkSelected(trk1))) { DIST_T len; len = trackGauge*2.0; if (len < 0.10*d->scale) len = 0.10*d->scale; + long oldOptions = d->options; + d->options &= ~DC_NOTSOLIDLINE; Translate( &p0, p, a+45, len ); Translate( &p1, p, a+225, len ); - DrawLine( &tempD, p0, p1, 0, selectedColor ); + DrawLine( d, p0, p1, 2, selectedColor ); Translate( &p0, p, a-45, len ); Translate( &p1, p, a-225, len ); - DrawLine( &tempD, p0, p1, 0, selectedColor ); + DrawLine( d, p0, p1, 2, selectedColor ); + d->options = oldOptions; sepBoundary = TRUE; } else if ((d->options&DC_PRINT)==0 && importTrack == NULL && (!GetTrkSelected(trk)) && GetTrkSelected(trk1)) { sepBoundary = TRUE; @@ -2831,7 +3288,6 @@ EXPORT void DrawTracks( drawCmd_p d, DIST_T scale, coOrd orig, coOrd size ) inDrawTracks = TRUE; InfoCount( 0 ); - d->options |= DC_TIES; TRK_ITERATE( trk ) { if ( (d->options&DC_PRINT) != 0 && wPrintQuit() ) { @@ -2854,7 +3310,6 @@ EXPORT void DrawTracks( drawCmd_p d, DIST_T scale, coOrd orig, coOrd size ) if (count%10 == 0) InfoCount( count ); } - d->options &= ~DC_TIES; if (d == &mainD) { for (inx=1; inx<trackCmds_da.cnt; inx++) @@ -2868,14 +3323,6 @@ EXPORT void DrawTracks( drawCmd_p d, DIST_T scale, coOrd orig, coOrd size ) } -EXPORT void RedrawLayer( unsigned int l, BOOL_T draw ) -{ - MainRedraw(); - MapRedraw(); - -} - - EXPORT void DrawSelectedTracks( drawCmd_p d ) { track_cp trk; @@ -2899,8 +3346,6 @@ EXPORT void DrawSelectedTracks( drawCmd_p d ) EXPORT void HilightElevations( BOOL_T hilight ) { - static long lastRedraw = -1; - static BOOL_T lastHilight = FALSE; track_p trk, trk1; EPINX_T ep; int mode; @@ -2908,12 +3353,6 @@ EXPORT void HilightElevations( BOOL_T hilight ) coOrd pos; DIST_T radius; - if (currRedraw > lastRedraw) { - lastRedraw = currRedraw; - lastHilight = FALSE; - } - if (lastHilight == hilight) - return; radius = 0.05*mainD.scale; if ( radius < trackGauge/2.0 ) radius = trackGauge/2.0; @@ -2937,25 +3376,20 @@ EXPORT void HilightElevations( BOOL_T hilight ) } } } - lastHilight = hilight; } EXPORT void HilightSelectedEndPt( BOOL_T show, track_p trk, EPINX_T ep ) { - static BOOL_T lastShow = FALSE; - static long lastRedraw = -1; coOrd pos; - if (trk == NULL) - return; - if (currRedraw > lastRedraw) { - lastRedraw = currRedraw; - lastShow = FALSE; - } - if (lastShow != show) { + if (!trk || (ep==-1)) return; + pos = GetTrkEndPos( trk, ep ); + if ( show == TRUE ) { pos = GetTrkEndPos( trk, ep ); DrawFillCircle( &tempD, pos, 0.10*mainD.scale, selectedColor ); - lastShow = show; + } else { + pos = GetTrkEndPos( trk, ep ); + DrawFillCircle( &tempD, pos, 0.10*mainD.scale, wDrawColorWhite ); } } |