diff options
Diffstat (limited to 'app/bin/track.c')
-rw-r--r-- | app/bin/track.c | 2546 |
1 files changed, 1253 insertions, 1293 deletions
diff --git a/app/bin/track.c b/app/bin/track.c index c9ec7db..951eec3 100644 --- a/app/bin/track.c +++ b/app/bin/track.c @@ -1,5 +1,5 @@ /** \file track.c - * Track + * Track */ /* XTrkCad - Model Railroad CAD @@ -17,16 +17,9 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <assert.h> -#include <time.h> -#include <ctype.h> -#include <stdarg.h> -#include <math.h> -#include <string.h> - #include "ccurve.h" #include "cjoin.h" #include "compound.h" @@ -36,36 +29,36 @@ #include "custom.h" #include "draw.h" #include "fileio.h" -#include "i18n.h" #include "layout.h" -#include "messages.h" #include "param.h" #include "paths.h" #include "track.h" -#include "utility.h" +#include "trackx.h" +#include "trkendpt.h" #include "misc.h" #include "ctrain.h" +#include "common-ui.h" +#include "version.h" -#ifndef TRACKDEP -#ifndef FASTTRACK -#include "trackx.h" -#endif -#endif +#include <inttypes.h> -#ifndef WINDOWS -#include <errno.h> -#else -// starting from Visual Studio 2015 round is in the runtime library, fake otherwise -#if ( _MSC_VER < 1900 ) -#define round(x) floor((x)+0.5) -#endif -#endif +#include <stdint.h> + +#define SLOG_FMT "0x%.12" PRIxPTR EXPORT char tempSpecial[4096]; +/** @logcmd @showrefby track=n track.c */ static int log_track = 0; +/** @logcmd @showrefby endPt=n track.c */ static int log_endPt = 0; +/** @logcmd @showrefby readTracks=n track.c */ static int log_readTracks = 0; +/** @logcmd @showrefby timedrawtracks=n track.c */ +static int log_timedrawtracks = 0; + +// Enable trkType checks on extraData*_t +#define CHECK_EXTRA_DATA /***************************************************************************** * @@ -77,15 +70,20 @@ static int log_readTracks = 0; #define CLOSETOTHEEDGE (10) /**< minimum distance between paste position and edge of window */ +EXPORT DIST_T trackGauge; +EXPORT DIST_T minLength = 0.1; +EXPORT DIST_T connectDistance = 0.1; +EXPORT ANGLE_T connectAngle = 1.0; +EXPORT long twoRailScale = 16; + EXPORT wIndex_t trackCount; EXPORT long drawEndPtV = 2; EXPORT long drawUnconnectedEndPt = 0; /**< How do we draw Unconnected EndPts */ -EXPORT long centerDrawMode = FALSE; /**< flag to control drawing of circle centers */ -EXPORT long printCenterLines = FALSE; /**< flag to control drawing of centerline in Print */ +EXPORT long centerDrawMode = + FALSE; /**< flag to control drawing of circle centers */ -static BOOL_T exportingTracks = FALSE; EXPORT signed char * pathPtr; EXPORT int pathCnt = 0; @@ -101,10 +99,7 @@ EXPORT unsigned int curTrackLayer; EXPORT coOrd descriptionOff; EXPORT DIST_T roadbedWidth = 0.0; -EXPORT DIST_T roadbedLineWidth = 3.0/75.0; - -//EXPORT DIST_T minTrackRadius; -//EXPORT DIST_T maxTrackGrade = 5.0; +EXPORT DIST_T roadbedLineWidth = 3.0/BASE_DPI; static int suspendElevUpdates = FALSE; @@ -114,19 +109,23 @@ EXPORT BOOL_T onTrackInSplit = FALSE; static BOOL_T inDrawTracks; -static wBool_t bWriteEndPtDirectIndex = FALSE; +EXPORT wBool_t bFreeTrack = FALSE; + +EXPORT long colorTrack = 0; +EXPORT long colorDraw = 0; -#ifndef TRACKDEP /***************************************************************************** * - * + * * */ -EXPORT void ActivateTrack( track_cp trk) { +EXPORT void ActivateTrack( track_cp trk) +{ int inx = GetTrkType(trk); - if (trackCmds( inx )->activate != NULL) + if (trackCmds( inx )->activate != NULL) { trackCmds( inx )->activate (trk); + } } @@ -150,20 +149,21 @@ EXPORT DIST_T GetTrkDistance( track_cp trk, coOrd * pos ) /** * Check whether the track passed as parameter is close to an existing piece. Track * pieces that aren't visible (in a tunnel or on an invisble layer) can be ignored, - * depending on flag. If there is a track closeby, the passed track is moved to that + * depending on flag. If there is a track closeby, the passed track is moved to that * position. This implements the snap feature. * * \param fp IN/OUT the old and the new position * \param complain IN show error message if there is no other piece of track - * \param track IN + * \param track IN * \param ignoreHidden IN decide whether hidden track is ignored or not - * \return NULL if there is no track, pointer to track otherwise + * \return NULL if there is no track, pointer to track otherwise */ -EXPORT track_p OnTrack2( coOrd * fp, BOOL_T complain, BOOL_T track, BOOL_T ignoreHidden, track_p t ) +EXPORT track_p OnTrack2( coOrd * fp, BOOL_T complain, BOOL_T track, + BOOL_T ignoreHidden, track_p t ) { track_p trk; - DIST_T distance, closestDistance = 1000000; + DIST_T distance, closestDistance = DIST_INF; track_p closestTrack = NULL; coOrd p, closestPos, q0, q1; @@ -173,30 +173,38 @@ EXPORT track_p OnTrack2( coOrd * fp, BOOL_T complain, BOOL_T track, BOOL_T ignor q0.y -= 1.0; q1.y += 1.0; TRK_ITERATE( trk ) { - if ( track && !IsTrack(trk) ) + if ( track && !IsTrack(trk) ) { continue; - if (trk == t) continue; + } + if (trk == t) { continue; } + // Bounding box check if (trk->hi.x < q0.x || - trk->lo.x > q1.x || - trk->hi.y < q0.y || - trk->lo.y > q1.y ) + trk->lo.x > q1.x || + trk->hi.y < q0.y || + trk->lo.y > q1.y ) { continue; + } if ( ignoreHidden ) { - if ( (!GetTrkVisible(trk)) && drawTunnel == DRAW_TUNNEL_NONE) + if ( (!GetTrkVisible(trk)) && drawTunnel == DRAW_TUNNEL_NONE) { continue; - if ( !GetLayerVisible( GetTrkLayer( trk ) ) ) + } + if ( !GetLayerVisible( GetTrkLayer( trk ) ) ) { continue; + } } + p = *fp; distance = trackCmds( GetTrkType(trk) )->distance( trk, &p ); - if (fabs(distance) <= fabs(closestDistance)) { //Make the last (highest) preferred + if (fabs(distance) <= fabs( + closestDistance)) { //Make the last (highest) preferred closestDistance = distance; closestTrack = trk; closestPos = p; } } - if (closestTrack && closestDistance <0 ) closestDistance = 0.0; //Turntable was closest - inside well - 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; } @@ -218,7 +226,9 @@ EXPORT track_p OnTrack( coOrd * fp, BOOL_T complain, BOOL_T track ) return OnTrack2( fp, complain, track, TRUE, NULL ); } -EXPORT track_p OnTrackIgnore (coOrd * fp, BOOL_T complain, BOOL_T track, track_p t ) { +EXPORT track_p OnTrackIgnore (coOrd * fp, BOOL_T complain, BOOL_T track, + track_p t ) +{ return OnTrack2(fp, complain, track, TRUE, t); } @@ -231,8 +241,9 @@ EXPORT BOOL_T CheckTrackLayer( track_p trk ) } else if (GetLayerModule( GetTrkLayer( trk ) ) ) { ErrorMessage( MSG_CANT_MODIFY_MODULE_TRK ); return FALSE; - } else + } else { return TRUE; + } } EXPORT BOOL_T CheckTrackLayerSilent( track_p trk ) @@ -241,8 +252,9 @@ EXPORT BOOL_T CheckTrackLayerSilent( track_p trk ) return FALSE; } else if (GetLayerModule( GetTrkLayer( trk ) ) ) { return FALSE; - } else + } else { return TRUE; + } } /****************************************************************************** @@ -252,27 +264,42 @@ EXPORT BOOL_T CheckTrackLayerSilent( track_p trk ) */ -EXPORT void EnumerateTracks( void ) +EXPORT void EnumerateTracks( void * unused ) { track_p trk; TRKINX_T inx; - enumerateMaxDescLen = strlen("Description"); + enumerateMaxDescLen = (int)strlen("Description"); + + BOOL_T content = FALSE; TRK_ITERATE( trk ) { - /* + /* * process track piece if none are selected (list all) or if it is one of the * selected pieces (list only selected ) */ - if ((!selectedTrackCount || GetTrkSelected(trk)) && trackCmds(trk->type)->enumerate != NULL) - trackCmds(trk->type)->enumerate( trk ); + if ((!selectedTrackCount || GetTrkSelected(trk)) + && trackCmds(trk->type)->enumerate != NULL) { + if (trackCmds(trk->type)->enumerate( trk )==TRUE) { content = TRUE; } + } + } + + if (content == FALSE) { + wBeep(); + if (selectedTrackCount == 0) { + InfoMessage(_("No track or structure pieces are present in layout")); + } else { + InfoMessage(_("No track or structure pieces are selected")); + } + return; } EnumerateStart(); for (inx=1; inx<trackCmds_da.cnt; inx++) - if (trackCmds(inx)->enumerate != NULL) + if (trackCmds(inx)->enumerate != NULL) { trackCmds(inx)->enumerate( NULL ); + } EnumerateEnd(); } @@ -285,32 +312,33 @@ EXPORT void EnumerateTracks( void ) static void AbortNoTrack( void ) { - AbortProg( "No Track Op called" ); + CHECKMSG( FALSE, ( "No Track Op called" ) ); } static trackCmd_t notrackCmds = { - "NOTRACK", - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack, - (void*)AbortNoTrack }; + "NOTRACK", + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack, + (void*)AbortNoTrack +}; EXPORT TRKTYP_T InitObject( trackCmd_t * cmds ) { @@ -328,6 +356,7 @@ EXPORT void InitTrkTrack( void ) log_track = LogFindIndex( "track" ); log_endPt = LogFindIndex( "endPt" ); log_readTracks = LogFindIndex( "readTracks" ); + log_timedrawtracks = LogFindIndex( "timedrawtracks" ); } /***************************************************************************** @@ -337,7 +366,6 @@ EXPORT void InitTrkTrack( void ) */ -#ifndef FASTTRACK EXPORT TRKINX_T GetTrkIndex( track_p trk ) { @@ -346,14 +374,15 @@ EXPORT TRKINX_T GetTrkIndex( track_p trk ) EXPORT TRKTYP_T GetTrkType( track_p trk ) { - ASSERT( trk->type != T_NOTRACK && !IsTrackDeleted(trk) ); + CHECK( trk->type != T_NOTRACK && !IsTrackDeleted(trk) ); return trk->type; } EXPORT SCALEINX_T GetTrkScale( track_p trk ) { - if ( trk ) + if ( trk ) { return (SCALEINX_T)trk->scale; + } return 0; } @@ -367,6 +396,14 @@ EXPORT unsigned int GetTrkLayer( track_p trk ) return trk->layer; } +EXPORT tieData_t GetTrkTieData( track_p trk ) +{ + if (!GetLayerUseDefault(GetTrkLayer(trk))) { + return GetLayerTieData(GetTrkLayer(trk)); + } + return GetScaleTieData(GetTrkScale(trk)); +} + EXPORT void SetBoundingBox( track_p trk, coOrd hi, coOrd lo ) { trk->hi.x = (float)hi.x; @@ -389,58 +426,53 @@ EXPORT EPINX_T GetTrkEndPtCnt( track_cp trk ) return trk->endCnt; } -EXPORT struct extraData * GetTrkExtraData( track_cp trk ) -{ - return trk->extraData; -} -EXPORT void SetTrkEndPoint( track_p trk, EPINX_T ep, coOrd pos, ANGLE_T angle ) +EXPORT trkEndPt_p GetTrkEndPt(track_cp trk, EPINX_T ep ) { - ASSERT( ep < trk->endCnt ); - if (trk->endPt[ep].track != NULL) { - AbortProg( "setTrkEndPoint: endPt is connected" ); - } - trk->endPt[ep].pos = pos; - trk->endPt[ep].angle = angle; + CHECK( ep < GetTrkEndPtCnt(trk) ); + return EndPtIndex( trk->endPt, ep ); } -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 ) +EXPORT struct extraDataBase_t * GetTrkExtraData( track_cp trk, + TRKTYP_T trkType ) { - ASSERT( e < trk->endCnt ); - return trk->endPt[e].angle; +//printf( "GTXD T%d TY%d\n", GetTrkIndex(trk), trkType ); + if ( IsTrackDeleted(trk) ) { + // We've been called by FreeTracks() which is called from + // - ClearTracks to remove all tracks + // - DoRegression to remove expected track + // - UndoStart / UndoDelete + // Anywhere else: needs investigation + if ( bFreeTrack == FALSE ) { + printf( "GetExtraData T%d is deleted!\n", trk->index ); + } + return trk->extraData; + } +#ifdef CHECK_EXTRA_DATA + CHECK( trk->extraData ); + CHECK( trk->type == trk->extraData->trkType ); + CHECK( trkType == T_NOTRACK || trk->type == trkType ); +#endif + return trk->extraData; } -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 ) +EXPORT void ResizeExtraData( track_p trk, CSIZE_T newSize ) { - ASSERT( e < trk->endCnt ); - return trk->endPt[e].option; + trk->extraData = MyRealloc( trk->extraData, newSize ); + trk->extraSize = newSize; } -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 ) + track_cp trk ) { - if (trk) + if (trk) { return GetScaleTrackGauge( GetTrkScale( trk ) ); - else + } else { return trackGauge; + } } EXPORT int GetTrkWidth( track_p trk ) @@ -455,7 +487,11 @@ EXPORT void SetTrkWidth( track_p trk, int width ) EXPORT int GetTrkBits( track_p trk ) { - return trk->bits; + if (trk) { + return trk->bits; + } else { + return 0; + } } EXPORT int SetTrkBits( track_p trk, int bits ) @@ -476,101 +512,25 @@ EXPORT BOOL_T IsTrackDeleted( track_p trk ) { return trk->deleted; } -#endif - -EXPORT void SetTrkEndElev( track_p trk, EPINX_T ep, int option, DIST_T height, char * station ) -{ - 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)) { - if (station == NULL) - station = ""; - trk->endPt[ep].elev.u.name = MyStrdup(station); - } - if ( (trk1=GetTrkEndTrk(trk, ep)) != NULL ) { - ep1 = GetEndPtConnectedToMe( trk1, trk ); - if (ep1 >= 0) { - trk1->endPt[ep1].elev.option = option; - trk1->endPt[ep1].elev.u.height = height; - if (EndPtIsDefinedElev(trk1,ep1)) - trk1->endPt[ep1].elev.u.height = height; - else if (EndPtIsStationElev(trk,ep)) - trk1->endPt[ep1].elev.u.name = MyStrdup(station); - } - } -} - - -EXPORT void GetTrkEndElev( track_p trk, EPINX_T e, int *option, DIST_T *height ) -{ - *option = trk->endPt[e].elev.option; - *height = trk->endPt[e].elev.u.height; -} - - -EXPORT int GetTrkEndElevUnmaskedMode( track_p trk, EPINX_T e ) -{ - return trk->endPt[e].elev.option; -} - - -EXPORT int GetTrkEndElevMode( track_p trk, EPINX_T e ) -{ - return trk->endPt[e].elev.option&ELEV_MASK; -} - - -EXPORT DIST_T GetTrkEndElevHeight( track_p trk, EPINX_T e ) -{ - ASSERT( EndPtIsDefinedElev(trk,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 ) -{ - ASSERT( EndPtIsStationElev(trk,e) ); - if ( trk->endPt[e].elev.u.name == NULL ) - return ""; - else - return trk->endPt[e].elev.u.name; -} EXPORT void SetTrkEndPtCnt( track_p trk, EPINX_T cnt ) { EPINX_T oldCnt = trk->endCnt; trk->endCnt = cnt; - if ((trk->endPt = MyRealloc( trk->endPt, trk->endCnt * sizeof trk->endPt[0] )) == NULL) { - AbortProg("setTrkEndPtCnt: No memory" ); + trk->endPt = MyRealloc( trk->endPt, EndPtSize(trk->endCnt) ); + if (oldCnt < cnt) { + memset( GetTrkEndPt( trk, oldCnt ), 0, EndPtSize(cnt-oldCnt) ); + for ( EPINX_T ep = oldCnt; ep<cnt; ep++ ) { + // Set .index to -1 + SetEndPtTrack( GetTrkEndPt( trk, ep ), NULL ); + } } - if (oldCnt < cnt) - memset( &trk->endPt[oldCnt], 0, (cnt-oldCnt) * sizeof *trk->endPt ); } + /** - * Set the layer for a track. + * Set the layer for a track. * * \param trk IN the layer to change the layer for * \param layer IN the new layer for the track @@ -579,10 +539,11 @@ void SetTrkLayer( track_p trk, int layer ) { DecrementLayerObjects(trk->layer); - if (useCurrentLayer) + if (useCurrentLayer) { trk->layer = (unsigned int)curLayer; - else + } else { trk->layer = (unsigned int)layer; + } IncrementLayerObjects(trk->layer); } @@ -603,8 +564,9 @@ EXPORT int ClrAllTrkBitsRedraw( int bits, wBool_t bRedraw ) if (trk->bits&bits) { cnt++; trk->bits &= ~bits; - if ( bRedraw ) + if ( bRedraw ) { DrawNewTrack( trk ); + } } } return cnt; @@ -617,9 +579,7 @@ 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; - } + ClrEndPtElevCache( trk->endCnt, trk->endPt ); } @@ -647,7 +607,7 @@ EXPORT void ClearElevPath( void ) EXPORT BOOL_T GetTrkOnElevPath( track_p trk, DIST_T * elev ) { if (trk->bits&TB_ELEVPATH) { - if ( elev ) *elev = trk->elev; + if ( elev ) { *elev = trk->elev; } return TRUE; } else { return FALSE; @@ -670,67 +630,23 @@ EXPORT void CopyAttributes( track_p src, track_p dst ) */ -EXPORT BOOL_T WriteEndPt( FILE * f, track_cp trk, EPINX_T ep ) -{ - trkEndPt_p endPt = &trk->endPt[ep]; - BOOL_T rc = TRUE; - long option; - - assert ( endPt != 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 { - rc &= fprintf( f, "\tT4 %d ", endPt->track->index )>0; - } - rc &= fprintf( f, "%0.6f %0.6f %0.6f", endPt->pos.x, endPt->pos.y, endPt->angle )>0; - option = (endPt->option<<8) | (endPt->elev.option&0xFF); - if ( option != 0 ) { - rc &= fprintf( f, " %ld %0.6f %0.6f", option, endPt->elev.doff.x, endPt->elev.doff.y )>0; - switch ( endPt->elev.option&ELEV_MASK ) { - case ELEV_DEF: - rc &= fprintf( f, " %0.6f ", endPt->elev.u.height )>0; - break; - case ELEV_STATION: - rc &= fprintf( f, " \"%s\" ", PutTitle( endPt->elev.u.name ) )>0; - break; - default: - rc &= fprintf( f, " 0.0 ")>0; - } - } else { - rc &= fprintf( f, " 0 0.0 0.0 0.0 ")>0; - } - if ((endPt->elev.option&ELEV_MASK) == ELEV_DEF) - rc &= fprintf( f, "%0.6f ",endPt->elev.u.height)>0; - else - rc &= fprintf( f, "0.0 ")>0; - long elevVisible = (endPt->elev.option&ELEV_VISIBLE)?1:0; - long elevType = endPt->elev.option&ELEV_MASK; - long gapType = endPt->option; - rc &= fprintf( f, "%ld %ld %ld ", elevVisible, elevType, gapType)>0; - rc &= fprintf( f, "%0.6f ", trk->elev)>0; - rc &= fprintf( f, "\n" )>0; - return rc; -} - - EXPORT EPINX_T PickEndPoint( coOrd p, track_cp trk ) { EPINX_T inx, i; DIST_T d, dd; coOrd pos; - if (trk->endCnt <= 0) + 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 ); + d = FindDistance( p, GetEndPtPos( trk->endPt ) ); inx = 0; for ( i=1; i<trk->endCnt; i++ ) { - pos = trk->endPt[i].pos; + pos = GetEndPtPos( EndPtIndex( trk->endPt, i ) ); dd=FindDistance(p, pos); if (dd < d) { d = dd; @@ -741,39 +657,38 @@ EXPORT EPINX_T PickEndPoint( coOrd p, track_cp trk ) } +/** + * Find an endpoint of trk that is close to coOrd p. + * Returns index of endpoint or displays a message + * and returns -1 if none found. + */ EXPORT EPINX_T PickUnconnectedEndPoint( coOrd p, track_cp trk ) { - EPINX_T inx, i; - DIST_T d=0, dd; - coOrd pos; - inx = -1; + EPINX_T inx; - for ( i=0; i<trk->endCnt; i++ ) { - if (trk->endPt[i].track == NULL) { - pos = trk->endPt[i].pos; - dd=FindDistance(p, pos); - if (inx == -1 || dd <= d) { - d = dd; - inx = i; - } - } - } + inx = PickUnconnectedEndPointSilent( p, trk ); - if (inx == -1) + if (inx == -1) { ErrorMessage( MSG_NO_UNCONN_EP ); + } return inx; } +/** + * Find an endpoint of trk that is close to coOrd p. + * Returns index of endpoint or -1 if none found. + */ EXPORT EPINX_T PickUnconnectedEndPointSilent( coOrd p, track_cp trk ) { EPINX_T inx, i; - DIST_T d=10000.0, dd; + DIST_T d=DIST_INF, dd; coOrd pos; inx = -1; for ( i=0; i<trk->endCnt; i++ ) { - if (trk->endPt[i].track == NULL) { - pos = trk->endPt[i].pos; + trkEndPt_p epp = EndPtIndex( trk->endPt, i ); + if (GetEndPtTrack( epp ) == NULL) { + pos = GetEndPtPos( epp ); dd=FindDistance(p, pos); if (inx == -1 || dd <= d) { d = dd; @@ -786,55 +701,85 @@ EXPORT EPINX_T PickUnconnectedEndPointSilent( coOrd p, track_cp trk ) } +/** + * Connect all the end points to this track (trk0) that are close enough + * (distance and angle) to another track's unconnected endpoint. + */ +EXPORT void ConnectAllEndPts(track_p trk0) +{ + for (EPINX_T ep0 = 0; ep0 < GetTrkEndPtCnt(trk0); ep0++) { + // Skip if already connected + if (GetTrkEndTrk(trk0, ep0) != NULL) { continue; } + + coOrd pos0 = GetTrkEndPos(trk0, ep0); + track_p trk2 = OnTrack2(&pos0, FALSE, TRUE, TRUE, trk0); + + // Not near another track? + if (trk2 == NULL) { continue; } + EPINX_T ep2 = PickUnconnectedEndPointSilent(pos0, trk2); + + // Close enough? + coOrd pos2 = GetTrkEndPos(trk2, ep2); + DIST_T distance = FindDistance(pos0, pos2); + if (distance > connectDistance) { continue; } + + // Aligned? + ANGLE_T a = fabs(DifferenceBetweenAngles( + GetTrkEndAngle(trk0, ep0), + GetTrkEndAngle(trk2, ep2) + 180.0)); + if (a > connectAngle) { continue; } + + // Make the connection + ConnectTracks(trk0, ep0, trk2, ep2); + DrawNewTrack(trk2); + } +} EXPORT EPINX_T GetEndPtConnectedToMe( track_p trk, track_p me ) { EPINX_T ep; for (ep=0; ep<trk->endCnt; ep++) - if (trk->endPt[ep].track == me) + if (GetEndPtTrack( EndPtIndex( trk->endPt, ep ) ) == me) { return ep; + } return -1; } -EXPORT EPINX_T GetNearestEndPtConnectedToMe( track_p trk, track_p me, coOrd pos) { +EXPORT EPINX_T GetNearestEndPtConnectedToMe( track_p trk, track_p me, + coOrd pos) +{ EPINX_T ep, found = -1; - DIST_T d = 10000; + DIST_T d = DIST_INF; DIST_T dd; - for (ep=0; ep<trk->endCnt; ep++) { - if (trk->endPt[ep].track == me) { - dd = FindDistance(pos,trk->endPt[ep].pos); - if (dd<d) { - found = ep; - d = dd; - } + for (ep=0; ep<trk->endCnt; ep++) { + trkEndPt_p epp = EndPtIndex( trk->endPt, ep ); + if (GetEndPtTrack( epp ) == me) { + coOrd pos1 = GetEndPtPos( epp ); + dd = FindDistance(pos, pos1 ); + if (dd<d) { + found = ep; + d = dd; } } - return found; + } + return found; } EXPORT void SetEndPts( track_p trk, EPINX_T cnt ) { - EPINX_T inx; - -LOG1( log_readTracks, ( "SetEndPts( T%d, %d )\n", trk->index, cnt ) ) - if (cnt > 0 && tempEndPts_da.cnt != cnt) { - InputError( "Incorrect number of End Points for track, read %d, expected %d.\n", FALSE, tempEndPts_da.cnt, cnt ); + LOG1( log_readTracks, ( "SetEndPts( T%d, %d )\n", trk->index, cnt ) ) + if (cnt > 0 && TempEndPtsCount() != cnt) { + InputError( "Incorrect number of End Points for track, read %d, expected %d.\n", + FALSE, TempEndPtsCount(), cnt ); return; } - if (tempEndPts_da.cnt) { - trk->endPt = (trkEndPt_p)MyMalloc( tempEndPts_da.cnt * sizeof *trk->endPt ); - } else { + trk->endCnt = TempEndPtsCount(); + if ( trk->endCnt <= 0 ) { trk->endPt = NULL; + } else { + trk->endPt = (trkEndPt_p)memdup( TempEndPt(0), EndPtSize( trk->endCnt ) ); } - for ( inx=0; inx<tempEndPts_da.cnt; inx++ ) { - trk->endPt[inx].index = tempEndPts(inx).index; - trk->endPt[inx].pos = tempEndPts(inx).pos; - trk->endPt[inx].angle = tempEndPts(inx).angle; - trk->endPt[inx].elev = tempEndPts(inx).elev; - trk->endPt[inx].option = tempEndPts(inx).option; - } - trk->endCnt = tempEndPts_da.cnt; } @@ -842,8 +787,11 @@ EXPORT void MoveTrack( track_p trk, coOrd orig ) { EPINX_T ep; for (ep=0; ep<trk->endCnt; ep++) { - trk->endPt[ep].pos.x += orig.x; - trk->endPt[ep].pos.y += orig.y; + trkEndPt_p epp = EndPtIndex( trk->endPt, ep ); + coOrd pos = GetEndPtPos( epp ); + pos.x += orig.x; + pos.y += orig.y; + SetEndPt( epp, pos, GetEndPtAngle( epp ) ); } trackCmds( trk->type )->move( trk, orig ); } @@ -852,11 +800,14 @@ EXPORT void MoveTrack( track_p trk, coOrd orig ) EXPORT void RotateTrack( track_p trk, coOrd orig, ANGLE_T angle ) { EPINX_T ep; - if ( trackCmds( trk->type )->rotate == NULL ) - return; + if ( trackCmds( trk->type )->rotate == NULL ) { + return; + } for (ep=0; ep<trk->endCnt; ep++) { - Rotate( &trk->endPt[ep].pos, orig, angle ); - trk->endPt[ep].angle = NormalizeAngle( trk->endPt[ep].angle + angle ); + trkEndPt_p epp = EndPtIndex( trk->endPt, ep ); + coOrd pos = GetEndPtPos( epp ); + Rotate( &pos, orig, angle ); + SetEndPt( epp, pos, NormalizeAngle( GetEndPtAngle(epp) + angle ) ); } trackCmds( trk->type )->rotate( trk, orig, angle ); } @@ -865,11 +816,15 @@ EXPORT void RotateTrack( track_p trk, coOrd orig, ANGLE_T angle ) EXPORT void RescaleTrack( track_p trk, FLOAT_T ratio, coOrd shift ) { EPINX_T ep; - if ( trackCmds( trk->type )->rescale == NULL ) + if ( trackCmds( trk->type )->rescale == NULL ) { return; + } for (ep=0; ep<trk->endCnt; ep++) { - trk->endPt[ep].pos.x *= ratio; - trk->endPt[ep].pos.y *= ratio; + trkEndPt_p epp = EndPtIndex( trk->endPt, ep ); + coOrd pos = GetEndPtPos( epp ); + pos.x *= ratio; + pos.y *= ratio; + SetEndPt( epp, pos, GetEndPtAngle(epp) ); } trackCmds( trk->type )->rescale( trk, ratio ); MoveTrack( trk, shift ); @@ -877,9 +832,9 @@ EXPORT void RescaleTrack( track_p trk, FLOAT_T ratio, coOrd shift ) EXPORT void FlipPoint( - coOrd * pos, - coOrd orig, - ANGLE_T angle ) + coOrd * pos, + coOrd orig, + ANGLE_T angle ) { Rotate( pos, orig, -angle ); pos->x = 2*orig.x - pos->x; @@ -888,33 +843,35 @@ EXPORT void FlipPoint( EXPORT void FlipTrack( - track_p trk, - coOrd orig, - ANGLE_T angle ) + track_p trk, + coOrd orig, + ANGLE_T angle ) { EPINX_T ep; - trkEndPt_t endPt; for ( ep=0; ep<trk->endCnt; ep++ ) { - FlipPoint( &trk->endPt[ep].pos, orig, angle ); - trk->endPt[ep].angle = NormalizeAngle( 2*angle - trk->endPt[ep].angle ); - } - if ( trackCmds(trk->type)->flip ) + trkEndPt_p epp = EndPtIndex( trk->endPt, ep ); + coOrd pos1 = GetEndPtPos( epp ); + FlipPoint( &pos1, orig, angle ); + ANGLE_T angle1 = GetEndPtAngle( epp ); + angle1 = NormalizeAngle( 2*angle - angle1 ); + SetEndPt( epp, pos1, angle1 ); + } + if ( trackCmds(trk->type)->flip ) { trackCmds(trk->type)->flip( trk, orig, angle ); + } if ( QueryTrack( trk, Q_FLIP_ENDPTS ) ) { - endPt = trk->endPt[0]; - trk->endPt[0] = trk->endPt[1]; - trk->endPt[1] = endPt; + SwapEndPts( trk->endPt, 0, 1 ); } } -EXPORT EPINX_T GetNextTrk( - track_p trk1, - EPINX_T ep1, - track_p *Rtrk, - EPINX_T *Rep, - int mode ) +EXPORT EPINX_T GetNextTrk( + track_p trk1, + EPINX_T ep1, + track_p *Rtrk, + EPINX_T *Rep, + int mode ) { EPINX_T ep, epCnt = GetTrkEndPtCnt(trk1), epRet=-1; track_p trk; @@ -922,21 +879,25 @@ EXPORT EPINX_T GetNextTrk( *Rtrk = NULL; *Rep = 0; for (ep=0; ep<epCnt; ep++) { - if (ep==ep1) + if (ep==ep1) { continue; + } trk = GetTrkEndTrk( trk1, ep ); if (trk==NULL) { #ifdef LATER - if (isElev) + if (isElev) { epRet = ep; + } #endif continue; } if ( (mode&GNTignoreIgnore) && - ((trk1->endPt[ep].elev.option&ELEV_MASK)==ELEV_IGNORE)) + ((GetTrkEndElevMode(trk1,ep) == ELEV_IGNORE)) ) { continue; - if (*Rtrk != NULL) + } + if (*Rtrk != NULL) { return -1; + } *Rtrk = trk; *Rep = GetEndPtConnectedToMe( trk, trk1 ); epRet = ep; @@ -945,46 +906,51 @@ EXPORT EPINX_T GetNextTrk( } EXPORT BOOL_T MakeParallelTrack( - track_p trk, - coOrd pos, - DIST_T dist, - DIST_T factor, - track_p * newTrkR, - coOrd * p0R, - coOrd * p1R, - BOOL_T track) -{ - if ( trackCmds(trk->type)->makeParallel ) - return trackCmds(trk->type)->makeParallel( trk, pos, dist, factor, newTrkR, p0R, p1R, track); + track_p trk, + coOrd pos, + DIST_T dist, + DIST_T factor, + track_p * newTrkR, + coOrd * p0R, + coOrd * p1R, + BOOL_T track) +{ + if ( trackCmds(trk->type)->makeParallel ) { + return trackCmds(trk->type)->makeParallel( trk, pos, dist, factor, newTrkR, p0R, + p1R, track); + } return FALSE; } EXPORT BOOL_T RebuildTrackSegs( - track_p trk) + track_p trk) { - if (trackCmds(trk->type)->rebuildSegs) + if (trackCmds(trk->type)->rebuildSegs) { return trackCmds(trk->type)->rebuildSegs(trk); + } return FALSE; } EXPORT BOOL_T ReplayTrackData( - track_p trk, - void * data, - long length) + track_p trk, + void * data, + long length) { - if (trackCmds(trk->type)->replayData) - return trackCmds(trk->type)->replayData(trk,data,length); - return FALSE; + if (trackCmds(trk->type)->replayData) { + return trackCmds(trk->type)->replayData(trk,data,length); + } + return FALSE; } EXPORT BOOL_T StoreTrackData( - track_p trk, - void ** data, - long * length) + track_p trk, + void ** data, + long * length) { - if (trackCmds(trk->type)->storeData) + if (trackCmds(trk->type)->storeData) { return trackCmds(trk->type)->storeData(trk,data,length); - return FALSE; + } + return FALSE; } @@ -996,19 +962,29 @@ EXPORT BOOL_T StoreTrackData( */ - EXPORT track_p to_first = NULL; - EXPORT TRKINX_T max_index = 0; EXPORT track_p * to_last = &to_first; +EXPORT track_p GetFirstTrack() +{ + return to_first; +} + +EXPORT track_p GetNextTrack( track_p trk ) +{ + return trk->next; +} + + + static struct { - track_p first; - track_p *last; - wIndex_t count; - wIndex_t changed; - TRKINX_T max_index; - } savedTrackState; + track_p first; + track_p *last; + wIndex_t count; + wIndex_t changed; + TRKINX_T max_index; +} savedTrackState; EXPORT void RenumberTracks( void ) @@ -1021,10 +997,10 @@ EXPORT void RenumberTracks( void ) } -EXPORT track_p NewTrack( TRKINX_T index, TRKTYP_T type, EPINX_T endCnt, CSIZE_T extraSize ) +EXPORT track_p NewTrack( TRKINX_T index, TRKTYP_T type, EPINX_T endCnt, + CSIZE_T extraSize ) { track_p trk; - EPINX_T ep; trk = (track_p ) MyMalloc( sizeof *trk ); *to_last = trk; to_last = &trk->next; @@ -1034,26 +1010,31 @@ EXPORT track_p NewTrack( TRKINX_T index, TRKTYP_T type, EPINX_T endCnt, CSIZE_T } else if (max_index < index) { max_index = index; } -LOG( log_track, 1, ( "NewTrack( T%d, t%d, E%d, X%ld)\n", index, type, endCnt, extraSize ) ) + LOG( log_track, 1, ( "NewTrack( T%d, t%d, E%d, X%ld)\n", index, type, endCnt, + extraSize ) ) trk->index = index; trk->type = type; trk->layer = curLayer; - trk->scale = (char)GetLayoutCurScale(); + trk->scale = (char)GetLayerScale(curLayer); // (char)GetLayoutCurScale(); trk->bits = TB_VISIBLE; trk->elevMode = ELEV_ALONE; trk->elev = 0; - trk->endCnt = endCnt; trk->hi.x = trk->hi.y = trk->lo.x = trk->lo.y = (float)0.0; + trk->endCnt = endCnt; if (endCnt) { - trk->endPt = (trkEndPt_p)MyMalloc( endCnt * sizeof *trk->endPt ); - for ( ep = 0; ep < endCnt; ep++ ) - trk->endPt[ep].index = -1; - } else + trk->endPt = (trkEndPt_p)MyMalloc( EndPtSize(endCnt) ); + for ( EPINX_T ep = 0; ep<endCnt; ep++ ) { + SetEndPtTrack( GetTrkEndPt( trk, ep ), NULL ); + } + } else { trk->endPt = NULL; + } if (extraSize) { - trk->extraData = MyMalloc( extraSize ); - } else + trk->extraData = (struct extraDataBase_t*)MyMalloc( extraSize ); + trk->extraData->trkType = type; + } else { trk->extraData = NULL; + } trk->extraSize = extraSize; UndoNew( trk ); trackCount++; @@ -1065,12 +1046,16 @@ LOG( log_track, 1, ( "NewTrack( T%d, t%d, E%d, X%ld)\n", index, type, endCnt, ex EXPORT void FreeTrack( track_p trk ) { - trackCmds(trk->type)->delete( trk ); - if (trk->endPt) + bFreeTrack = TRUE; + trackCmds(trk->type)->deleteTrk( trk ); + if (trk->endPt) { MyFree(trk->endPt); - if (trk->extraData) + } + if (trk->extraData) { MyFree(trk->extraData); + } MyFree(trk); + bFreeTrack = FALSE; } @@ -1097,7 +1082,7 @@ EXPORT track_p FindTrack( TRKINX_T index ) { track_p trk; TRK_ITERATE(trk) { - if (trk->index == index) return trk; + if (trk->index == index) { return trk; } } return NULL; } @@ -1108,19 +1093,26 @@ 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) { - int rc = NoticeMessage( MSG_RESOLV_INDEX_BAD_TRK, _("Continue"), _("Quit"), trk->index, ep, trk->endPt[ep].index ); - if ( rc != 1 ) + 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++) { + trkEndPt_p epp = GetTrkEndPt( trk, ep ); + TRKINX_T index = GetEndPtIndex( epp ); + if (index >= 0) { + track_p track = FindTrack( index ); + if (track == NULL) { + int rc = NoticeMessage( MSG_RESOLV_INDEX_BAD_TRK, _("Continue"), _("Quit"), + trk->index, ep, index ); + if ( rc != 1 ) { return; + } } + SetEndPtTrack( epp, track ); } - ResolveBlockTrack (trk); - ResolveSwitchmotorTurnout (trk); - } + } + ResolveBlockTrack (trk); + ResolveSwitchmotorTurnout (trk); + } AuditTracks( "readTracks" ); } @@ -1129,11 +1121,13 @@ EXPORT BOOL_T DeleteTrack( track_p trk, BOOL_T all ) { EPINX_T i, ep2; track_p trk2; -LOG( log_track, 4, ( "DeleteTrack(T%d)\n", GetTrkIndex(trk) ) ) + LOG( log_track, 4, ( "DeleteTrack(T%d)\n", GetTrkIndex(trk) ) ) if (all) { if (!QueryTrack(trk,Q_CANNOT_BE_ON_END)) { - for (i=0;i<trk->endCnt;i++) { - if ((trk2=trk->endPt[i].track) != NULL) { + for (i=0; i<trk->endCnt; i++) { + trkEndPt_p epp = EndPtIndex( trk->endPt, i ); + trk2 = GetEndPtTrack(epp); + if (trk2 != NULL) { if (QueryTrack(trk2,Q_CANNOT_BE_ON_END)) { DeleteTrack( trk2, FALSE ); } @@ -1141,17 +1135,27 @@ LOG( log_track, 4, ( "DeleteTrack(T%d)\n", GetTrkIndex(trk) ) ) } } } - for (i=0;i<trk->endCnt;i++) { - if ((trk2=trk->endPt[i].track) != NULL) { + /* If Car, simulate Remove Car -> uncouple and mark deleted (no Undo) */ + if (QueryTrack(trk,Q_ISTRAIN)) { + UncoupleCars( trk, 0 ); + UncoupleCars( trk, 1 ); + trk->deleted = TRUE; + ClrTrkBits( trk, TB_SELECTED ); // Make sure we don't select a deleted car + return TRUE; + } + for (i=0; i<trk->endCnt; i++) { + trkEndPt_p epp = EndPtIndex( trk->endPt, i ); + if ((trk2=GetEndPtTrack(epp)) != NULL) { ep2 = GetEndPtConnectedToMe( trk2, trk ); DisconnectTracks( trk2, ep2, trk, i ); - if ( QueryTrack(trk,Q_CANNOT_BE_ON_END) ) + if ( QueryTrack(trk,Q_CANNOT_BE_ON_END) ) { UndoJoint( trk2, ep2, trk, i ); + } } } - CheckDeleteSwitchmotor( trk ); - CheckDeleteBlock( trk ); - CheckCarTraverse( trk ); + CheckDeleteSwitchmotor( trk ); + CheckDeleteBlock( trk ); + CheckCarTraverse( trk ); DecrementLayerObjects(trk->layer); trackCount--; AuditTracks( "deleteTrack T%d", trk->index); @@ -1191,18 +1195,27 @@ EXPORT void RestoreTrackState( void ) BOOL_T TrackIterate( track_p * trk ) { track_p trk1; - if (!*trk) + if (!*trk) { trk1 = to_first; - else + } else { trk1 = (*trk)->next; - while (trk1 && IsTrackDeleted(trk1)) + } + while (trk1 && IsTrackDeleted(trk1)) { trk1 = trk1->next; + } *trk = trk1; return trk1 != NULL; } -wBool_t IsPosClose( coOrd pos1, coOrd pos2 ) { +/***************************************************************************** +* +* REGRESSION +* +*/ + +wBool_t IsPosClose( coOrd pos1, coOrd pos2 ) +{ DIST_T d = FindDistance( pos1, pos2 ); return d < 0.1; } @@ -1211,8 +1224,9 @@ wBool_t IsPosClose( coOrd pos1, coOrd pos2 ) { wBool_t IsAngleClose( ANGLE_T angle1, ANGLE_T angle2 ) { ANGLE_T angle = NormalizeAngle( angle1 - angle2 ); - if (angle > 180) + if (angle > 180) { angle = 360-angle; + } return angle < 0.01; } @@ -1228,16 +1242,19 @@ 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 ) + if ( dist < 0.05 ) { return TRUE; -#ifdef WINDOWS - dist1 *= 96.0/72.0; -#else - dist1 *= 72.0/96.0; -#endif + } +// This was using BASE_DPI(=75.0) based on ancient monitors. +// 96 DPI is more reasonable today +// TODO: review BASE_DPI with a plan to change it to 96.0 +// printf( "WidthClose %s:%d D2:%0.3f D1:%0.3f", paramFileName, paramLineNum, dist2, dist1 ); + dist1 *= mainD.dpi/96.0; dist = fabs( dist1 - dist2 ); - if ( dist < 0.01 ) +// printf( " -> %0.3f D:%0.3f\n", dist1, dist ); + if ( dist < 0.05 ) { return TRUE; + } return FALSE; } @@ -1255,17 +1272,17 @@ wBool_t IsColorClose( wDrawColor color1, wDrawColor color2 ) return (diff < 7); } -wBool_t CompareTrack( track_cp trk1, track_cp trk2 ) +static wBool_t CompareTrack( track_cp trk1, track_cp trk2 ) { - wBool_t rc = FALSE; +// 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( "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 ) @@ -1274,25 +1291,139 @@ wBool_t CompareTrack( track_cp trk1, track_cp trk2 ) 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 ); + if ( ! CompareEndPt( cp, trk1, trk2, inx ) ) { return FALSE; } - REGRESS_CHECK_INT( "Option", trk1, trk2, endPt[inx].option ) } - if ( trackCmds( GetTrkType( trk1 ) )->compare == NULL ) + if ( trackCmds( GetTrkType( trk1 ) )->compare == NULL ) { return TRUE; + } return trackCmds( GetTrkType( trk1 ) )->compare( trk1, trk2 ); } - +EXPORT int CheckRegressionResult( long regressVersion,char * sFileName, + wBool_t bQuiet ) +{ + wBool_t bWroteActualTracks = FALSE; + int nFail = 0; + FILE * fRegression = NULL; + char * sRegressionFile = NULL; + track_p to_first_save = to_first; + track_p* to_last_save = to_last; + MakeFullpath( &sRegressionFile, workingDir, "xtrkcad.regress", NULL ); + + while ( GetNextLine() ) { + if ( paramLine[0] == '#' ) { + continue; + } + // Read Expected track + to_first = NULL; + to_last = &to_first; + paramVersion = regressVersion; + if ( !ReadTrack( paramLine ) ) { + if ( paramFile == NULL ) { + return -1; + } + break; + } + if ( to_first == NULL ) { + // Something bad happened + break; + } + track_cp tExpected = to_first; + to_first = to_first_save; + // Find corresponding Actual track + track_cp tActual = FindTrack( GetTrkIndex( tExpected ) ); + strcat( message, "Regression " ); + if ( ! CompareTrack( tActual, tExpected ) ) { + nFail++; + // Actual doesn't match Expected + lprintf( " FAIL: %s\n", message); + fRegression = fopen( sRegressionFile, "a" ); + if ( fRegression == NULL ) { + NoticeMessage( MSG_OPEN_FAIL, _("Continue"), NULL, _("Regression"), + sRegressionFile, strerror(errno) ); + break; + } + fprintf( fRegression, "REGRESSION FAIL %d\n", + PARAMVERSION ); + fprintf( fRegression, "# %s - %d\n", sFileName, paramLineNum ); + fprintf( fRegression, "# %s", message ); + if ( !bWroteActualTracks ) { + // Print Actual tracks + fprintf( fRegression, "Actual Tracks\n" ); + paramVersion = PARAMVERSION; + WriteTracks( fRegression, FALSE ); + bWroteActualTracks = TRUE; + } + // Print Expected track + to_first = tExpected; + fprintf( fRegression, "Expected Track\n" ); + WriteTracks( fRegression, FALSE ); + fclose( fRegression ); + strcat( message, "Continue test?" ); + if ( ! bQuiet ) { + int rc = wNoticeEx( NT_ERROR, message, _("Stop"), _("Continue") ); + if ( !rc ) { + while ( GetNextLine() && + strncmp( paramLine, "REGRESSION END", 14 ) != 0 ) + ; + break; + } + } + } + // Delete Expected track + to_first = tExpected; + to_last = &to_first; + FreeTrack( tExpected ); + } + to_first = to_first_save; + to_last = to_last_save; + if ( strncmp( paramLine, "REGRESSION END", 14 ) != 0 ) { + InputError( "Expected REGRESSION END", TRUE ); + } + return nFail; +} + + +/***************************************************************************** +* +* LAYER +* +*/ + +/** + * @brief Add 1 to track layer numbers that are greater than or equal to New Layer + * @param newLayer +*/ +EXPORT void TrackInsertLayer( int newLayer ) +{ + track_p trk; + + TRK_ITERATE( trk ) { + int layer = GetTrkLayer(trk); + if (layer >= newLayer) { + SetTrkLayer(trk, layer + 1); + } + } +} + +/** +* @brief Subtract 1 from track layer numbers that are greater than Removed Layer +* @param removeLayer +*/ +EXPORT void TrackDeleteLayer( int removeLayer ) +{ + track_p trk; + + TRK_ITERATE( trk ) { + int layer = GetTrkLayer(trk); + if (layer > removeLayer) { + SetTrkLayer(trk, layer - 1); + } + } +} + /***************************************************************************** * * ABOVE / BELOW @@ -1304,10 +1435,11 @@ static void ExciseSelectedTracks( track_p * pxtrk, track_p * pltrk ) track_p trk, *ptrk; for (ptrk=&to_first; *ptrk!=NULL; ) { trk = *ptrk; - if (IsTrackDeleted(trk) || !GetTrkSelected(trk)) { + if (!GetTrkSelected(trk)) { ptrk = &(*ptrk)->next; continue; } + CHECK( !IsTrackDeleted(trk) ); UndoModify( *ptrk ); UndoModify( trk ); *ptrk = trk->next; @@ -1319,7 +1451,7 @@ static void ExciseSelectedTracks( track_p * pxtrk, track_p * pltrk ) } -EXPORT void SelectAbove( void ) +EXPORT void SelectAbove( void * unused ) { track_p xtrk, ltrk; if (selectedTrackCount<=0) { @@ -1334,11 +1466,11 @@ EXPORT void SelectAbove( void ) to_last = <rk->next; } UndoEnd(); - DrawSelectedTracks( &mainD ); + DrawSelectedTracks( &mainD, false ); } -EXPORT void SelectBelow( void ) +EXPORT void SelectBelow( void * unused ) { track_p xtrk, ltrk, trk; coOrd lo, hi, lowest, highest; @@ -1355,14 +1487,18 @@ EXPORT void SelectBelow( void ) GetBoundingBox( trk, &highest, &lowest ); } else { GetBoundingBox( trk, &hi, &lo ); - if (highest.x < hi.x) + if (highest.x < hi.x) { highest.x = hi.x; - if (highest.y < hi.y) + } + if (highest.y < hi.y) { highest.y = hi.y; - if (lowest.x > lo.x) + } + if (lowest.x > lo.x) { lowest.x = lo.x; - if (lowest.y > lo.y) + } + if (lowest.y > lo.y) { lowest.y = lo.y; + } } ClrTrkBits( trk, TB_SELECTED ); } @@ -1376,16 +1512,16 @@ EXPORT void SelectBelow( void ) } -#include "bitmaps/above.xpm" -#include "bitmaps/below.xpm" +#include "bitmaps/top.xpm3" +#include "bitmaps/bottom.xpm3" EXPORT void InitCmdAboveBelow( void ) { wIcon_p bm_p; - bm_p = wIconCreatePixMap( above_xpm ); - AddToolbarButton( "cmdAbove", bm_p, IC_SELECTED|IC_POPUP, (addButtonCallBack_t)SelectAbove, NULL ); - bm_p = wIconCreatePixMap( below_xpm ); - AddToolbarButton( "cmdBelow", bm_p, IC_SELECTED|IC_POPUP, (addButtonCallBack_t)SelectBelow, NULL ); + bm_p = wIconCreatePixMap( top_xpm3[iconSize] ); + AddToolbarButton( "cmdAbove", bm_p, IC_SELECTED|IC_POPUP, SelectAbove, NULL ); + bm_p = wIconCreatePixMap( bottom_xpm3[iconSize] ); + AddToolbarButton( "cmdBelow", bm_p, IC_SELECTED|IC_POPUP, SelectBelow, NULL ); } /***************************************************************************** @@ -1415,38 +1551,40 @@ EXPORT BOOL_T ReadTrack( char * line ) return TRUE; } -if (bsearchRead) { - if (sortedCmds == NULL) { - sortedCmds = (trackCmd_t**)MyMalloc( (trackCmds_da.cnt-1) * sizeof *(trackCmd_t*)0 ); - for (inx=1; inx<trackCmds_da.cnt; inx++) - sortedCmds[inx-1] = trackCmds(inx); - qsort( sortedCmds, trackCmds_da.cnt-1, sizeof *(trackCmd_t**)0, CompareCmds ); - } - - lo = 0; - hi = trackCmds_da.cnt-2; - do { - inx = (lo+hi)/2; - cmp = strncmp( line, sortedCmds[inx]->name, strlen(sortedCmds[inx]->name) ); - if (cmp == 0) { - return sortedCmds[inx]->read(line); - } else if (cmp < 0) { - hi = inx-1; - } else { - lo = inx+1; - } - } while ( lo <= hi ); -} 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 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 (bsearchRead) { + if (sortedCmds == NULL) { + sortedCmds = (trackCmd_t**)MyMalloc( (trackCmds_da.cnt-1) * sizeof * + (trackCmd_t*)0 ); + for (inx=1; inx<trackCmds_da.cnt; inx++) { + sortedCmds[inx-1] = trackCmds(inx); + } + qsort( sortedCmds, trackCmds_da.cnt-1, sizeof *(trackCmd_t**)0, CompareCmds ); + } + + lo = 0; + hi = trackCmds_da.cnt-2; + do { + inx = (lo+hi)/2; + cmp = strncmp( line, sortedCmds[inx]->name, strlen(sortedCmds[inx]->name) ); + if (cmp == 0) { + return sortedCmds[inx]->read(line); + } else if (cmp < 0) { + hi = inx-1; + } else { + lo = inx+1; + } + } while ( lo <= hi ); + } 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 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; + } + } } -} // Object type not found return FALSE; } @@ -1456,16 +1594,19 @@ EXPORT BOOL_T WriteTracks( FILE * f, wBool_t bFull ) { track_p trk; BOOL_T rc = TRUE; - if ( bFull ) + if ( bFull ) { RenumberTracks(); - if ( !bFull ) + } + if ( !bFull ) { bWriteEndPtDirectIndex = TRUE; + } TRK_ITERATE( trk ) { rc &= trackCmds(GetTrkType(trk))->write( trk, f ); } bWriteEndPtDirectIndex = FALSE; - if ( bFull ) + if ( bFull ) { rc &= WriteCars( f ); + } return rc; } @@ -1485,8 +1626,8 @@ EXPORT void ImportEnd( coOrd offset, wBool_t import, wBool_t inPlace ) wIndex_t trackCountOld; track_p trk; coOrd pos; - wPos_t x, y; - wPos_t ww, hh; + wDrawPix_t x, y; + wWinPix_t ww, hh; wBool_t offscreen = FALSE; double xmin = 0.0; @@ -1497,27 +1638,26 @@ EXPORT void ImportEnd( coOrd offset, wBool_t import, wBool_t inPlace ) // 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 ); coOrd middle_screen; - wPos_t mx,my; + wDrawPix_t mx,my; - mx = ww/2; - my = hh/2; + mx = ww/2.0; + my = hh/2.0; 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; - } + CHECK(!IsTrackDeleted(trk)); // Export ignores deleted tracks + 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; } } coOrd size = {xmax-xmin,ymax-ymin}; @@ -1541,10 +1681,10 @@ EXPORT void ImportEnd( coOrd offset, wBool_t import, wBool_t inPlace ) middle_object.x = offset.x + (size.x/2); middle_object.y = offset.y + (size.y/2); - wPos_t ox,oy; + wDrawPix_t ox,oy; mainD.CoOrd2Pix( &mainD, middle_object, &ox, &oy ); - if ((ox<0) || (ox>ww) || (oy<0) || (oy>hh) ) offscreen = TRUE; + if ((ox<0) || (ox>ww) || (oy<0) || (oy>hh) ) { offscreen = TRUE; } to_firstOld = to_first; to_first = *importTrack; @@ -1554,7 +1694,8 @@ EXPORT void ImportEnd( coOrd offset, wBool_t import, wBool_t inPlace ) RenumberTracks(); // move the imported track into place - for ( trk=*importTrack; trk; trk=trk->next ) if (!IsTrackDeleted(trk)) { + for ( trk=*importTrack; trk; trk=trk->next ) { + CHECK( !IsTrackDeleted(trk) ); coOrd move; move.x = offset.x; move.y = offset.y; @@ -1562,33 +1703,36 @@ EXPORT void ImportEnd( coOrd offset, wBool_t import, wBool_t inPlace ) trk->bits |= TB_SELECTED; DrawTrack( trk, &mainD, wDrawColorBlack ); } - importTrack = NULL; + importTrack = NULL; trackCount = trackCountOld; InfoCount( trackCount ); // Pan screen if needed to center of new if (offscreen) { panCenter = middle_object; - PanHere((void*)0); + PanHere(I2VP(0)); } } /******* * Move Selected Tracks to origin zero and write out *******/ -EXPORT BOOL_T ExportTracks( FILE * f, coOrd * offset) +EXPORT BOOL_T ExportTracks( FILE * f, coOrd * offset ) { track_p trk; coOrd xlat,orig; - - exportingTracks = TRUE; + + bWriteEndPtExporting = TRUE; orig = mapD.size; max_index = 0; TRK_ITERATE(trk) { if ( GetTrkSelected(trk) ) { - if (trk->lo.x < orig.x) + if (QueryTrack(trk,Q_ISTRAIN)) { continue; } //Don't bother with CARs + if (trk->lo.x < orig.x) { orig.x = trk->lo.x; - if (trk->lo.y < orig.y) + } + if (trk->lo.y < orig.y) { orig.y = trk->lo.y; + } trk->index = ++max_index; } } @@ -1599,13 +1743,14 @@ EXPORT BOOL_T ExportTracks( FILE * f, coOrd * offset) xlat.y = - orig.y; TRK_ITERATE( trk ) { if ( GetTrkSelected(trk) ) { + if (QueryTrack(trk,Q_ISTRAIN)) { continue; } //Don't bother with CARs MoveTrack( trk, xlat ); trackCmds(GetTrkType(trk))->write( trk, f ); MoveTrack( trk, orig ); } } RenumberTracks(); - exportingTracks = FALSE; + bWriteEndPtExporting = FALSE; return TRUE; } @@ -1637,7 +1782,8 @@ static void AuditPrint( char * msg ) auditFile = fopen( path, "a+" ); free(path); if (auditFile == NULL) { - NoticeMessage( MSG_OPEN_FAIL, _("Continue"), NULL, _("Audit"), message, strerror(errno) ); + NoticeMessage( MSG_OPEN_FAIL, _("Continue"), NULL, _("Audit"), message, + strerror(errno) ); auditIgnore = TRUE; return; } @@ -1649,12 +1795,14 @@ static void AuditPrint( char * msg ) } fprintf(auditFile, "# " ); fprintf(auditFile, "%s", msg ); - if (auditIgnore) + if (auditIgnore) { return; + } NoticeMessage( MSG_AUDIT_PRINT_MSG, _("Ok"), NULL, msg ); if (++auditCount>10) { - if (NoticeMessage( MSG_AUDIT_PRINT_IGNORE, _("Yes"), _("No") ) ) + if (NoticeMessage( MSG_AUDIT_PRINT_IGNORE, _("Yes"), _("No") ) ) { auditIgnore = TRUE; + } auditCount = 0; } } @@ -1663,7 +1811,7 @@ static void AuditPrint( char * msg ) EXPORT void CheckTrackLength( track_cp trk ) { DIST_T dist; - + if (trackCmds(trk->type)->getLength) { dist = trackCmds(trk->type)->getLength( trk ); } else { @@ -1693,11 +1841,11 @@ EXPORT void AuditTracks( char * event, ... ) *msgp++ = '\n'; trackCount = 0; - for (i=0;i<sizeof used;i++) { + for (i=0; i<sizeof used; i++) { used[i] = 0; } if (*to_last) { - sprintf( msgp, "*to_last is not NULL (%lx)", (long)*to_last ); + sprintf( msgp, "*to_last is not NULL ("SLOG_FMT")", (uintptr_t)*to_last ); AuditPrint( msg ); } TRK_ITERATE( trk ) { @@ -1712,8 +1860,9 @@ EXPORT void AuditTracks( char * event, ... ) AuditPrint( msg ); } if ((auditCmd = trackCmds( trk->type )->audit) != NULL) { - if (!auditCmd( trk, msgp )) + if (!auditCmd( trk, msgp )) { AuditPrint( msg ); + } } if (trk->index < 8*sizeof used) { if (BIT_SET(used,trk->index)) { @@ -1723,45 +1872,52 @@ EXPORT void AuditTracks( char * event, ... ) SET_BIT(used, trk->index); } for (i=0; i<trk->endCnt; i++) { - if ( (tn = trk->endPt[i].track) != NULL ) { - if (IsTrackDeleted(trk)) { + trkEndPt_p epp = EndPtIndex( trk->endPt, i ); + if ( (tn = GetEndPtTrack(epp)) != NULL ) { + if (IsTrackDeleted(tn)) { sprintf( msgp, "T%d[%d]: T%d is deleted\n", trk->index, i, tn->index ); AuditPrint( msg ); - trk->endPt[i].track = NULL; + SetEndPtTrack( epp, NULL ); } else { - for (j=0;j<tn->endCnt;j++) - if (tn->endPt[j].track == trk) + for (j=0; j<tn->endCnt; j++) { + if (GetEndPtTrack( EndPtIndex( tn->endPt, j ) ) == trk) { goto nextEndPt; + } + } sprintf( msgp, "T%d[%d]: T%d doesn\'t point back\n", trk->index, i, tn->index ); AuditPrint( msg ); - trk->endPt[i].track = NULL; + SetEndPtTrack( epp, NULL ); } } nextEndPt:; } if (!trk->next) { if (to_last != &trk->next) { - sprintf( msgp, "last track (T%d @ %lx) is not to_last (%lx)\n", - trk->index, (long)trk, (long)to_last ); + sprintf( msgp, "last track (T%d @ "SLOG_FMT") is not to_last ("SLOG_FMT")\n", + trk->index, (uintptr_t)trk, (uintptr_t)to_last ); AuditPrint( msg ); } } } InfoCount( trackCount ); if (auditFile != NULL) { - if (auditStop) - if (NoticeMessage( MSG_AUDIT_WRITE_FILE, _("Yes"), _("No"))) { - fprintf( auditFile, "# before undo\n" ); - WriteTracks(auditFile, TRUE); - Rdump( auditFile ); - if (strcmp("undoUndo",event)==0) { - fprintf( auditFile, "# failure in undo\n" ); - } else if (UndoUndo()) { - fprintf( auditFile, "# after undo\n" ); + if (auditStop) { + if (NoticeMessage( MSG_AUDIT_WRITE_FILE, _("Yes"), _("No"))) { + fprintf( auditFile, "# before undo\n" ); WriteTracks(auditFile, TRUE); Rdump( auditFile ); - } else { - fprintf( auditFile, "# undo stack is empty\n" ); + if (strcmp("undoUndo",event)==0) { + fprintf( auditFile, "# failure in undo\n" ); + } else { + UndoUndo( NULL ); + if ( undoStatus ) { + fprintf( auditFile, "# after undo\n" ); + WriteTracks(auditFile, TRUE); + Rdump( auditFile ); + } else { + fprintf( auditFile, "# undo stack is empty\n" ); + } + } } } if (NoticeMessage( MSG_AUDIT_ABORT, _("Yes"), _("No"))) { @@ -1787,103 +1943,26 @@ EXPORT void ComputeBoundingBox( track_p trk ) { EPINX_T i; - if (trk->endCnt <= 0) - AbortProg("computeBoundingBox - endCnt<=0"); + CHECK( trk->endCnt > 0 ); - trk->hi.x = trk->lo.x = (float)trk->endPt[0].pos.x; - trk->hi.y = trk->lo.y = (float)trk->endPt[0].pos.y; + coOrd pos = GetEndPtPos( trk->endPt ); + trk->hi.x = trk->lo.x = (float)pos.x; + trk->hi.y = trk->lo.y = (float)pos.y; for ( i=1; i<trk->endCnt; i++ ) { - if (trk->endPt[i].pos.x > trk->hi.x) - trk->hi.x = (float)trk->endPt[i].pos.x; - if (trk->endPt[i].pos.y > trk->hi.y) - trk->hi.y = (float)trk->endPt[i].pos.y; - if (trk->endPt[i].pos.x < trk->lo.x) - trk->lo.x = (float)trk->endPt[i].pos.x; - if (trk->endPt[i].pos.y < trk->lo.y) - trk->lo.y = (float)trk->endPt[i].pos.y; - } -} - - - -EXPORT DIST_T EndPtDescriptionDistance( - coOrd pos, - track_p trk, - 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) - 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 ); -} - - -EXPORT STATUS_T EndPtDescriptionMove( - track_p trk, - EPINX_T ep, - wAction_t action, - coOrd pos ) -{ - static coOrd p0, p1; - static BOOL_T editState = FALSE; - elev_t *e, *e1; - track_p trk1; - - e = &trk->endPt[ep].elev; - switch (action) { - case C_DOWN: - p0 = GetTrkEndPos(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: - editState = TRUE; - p1 = pos; - e->doff.x = (pos.x-p0.x); - e->doff.y = (pos.y-p0.y); - if ((trk1=GetTrkEndTrk(trk,ep))) { - e1 = &trk1->endPt[GetEndPtConnectedToMe(trk1,trk)].elev; - e1->doff = e->doff; + pos = GetEndPtPos( EndPtIndex( trk->endPt, i ) ); + if (pos.x > trk->hi.x) { + trk->hi.x = (float)pos.x; } - if ( action == C_UP ) { - editState = FALSE; - wDrawColor color = GetTrkColor( trk, &mainD ); - DrawEndElev( &mainD, trk, ep, color ); + if (pos.y > trk->hi.y) { + trk->hi.y = (float)pos.y; } - return action==C_UP?C_TERMINATE:C_CONTINUE; - - case C_REDRAW: - DrawEndElev( &tempD, trk, ep, wDrawColorBlue ); - if ( editState ) { - DrawLine( &tempD, p0, p1, 0, wDrawColorBlue ); + if (pos.x < trk->lo.x) { + trk->lo.x = (float)pos.x; + } + if (pos.y < trk->lo.y) { + trk->lo.y = (float)pos.y; } - break; } - return C_CONTINUE; } @@ -1894,119 +1973,118 @@ EXPORT STATUS_T EndPtDescriptionMove( */ -static DIST_T distanceEpsilon = 0.0; -static ANGLE_T angleEpsilon = 0.0; +//static DIST_T distanceEpsilon = 0.0; +//static ANGLE_T angleEpsilon = 0.0; -EXPORT void LoosenTracks( void ) +EXPORT int ConnectTracks( track_p trk0, EPINX_T inx0, track_p trk1, + EPINX_T inx1 ) { - track_p trk, trk1; - EPINX_T ep0, ep1; - ANGLE_T angle0, angle1; - coOrd pos0, pos1; DIST_T d; ANGLE_T a; - int count; + coOrd pos0, pos1; + trkEndPt_p epp0 = EndPtIndex( trk0->endPt, inx0 ); + trkEndPt_p epp1 = EndPtIndex( trk1->endPt, inx1 ); - count = 0; - TRK_ITERATE(trk) { - for (ep0=0; ep0<trk->endCnt; ep0++) { - trk1 = GetTrkEndTrk( trk, ep0 ); - if (trk1 == NULL) - continue; - ASSERT( !IsTrackDeleted(trk1) ); - ep1 = GetEndPtConnectedToMe( trk1, trk ); - if (ep1 < 0) - continue; - pos0 = GetTrkEndPos( trk, ep0 ); - pos1 = GetTrkEndPos( trk1, ep1 ); - angle0 = GetTrkEndAngle( trk, ep0 ); - angle1 = GetTrkEndAngle( trk1, ep1 ); - d = FindDistance( pos0, pos1 ); - a = NormalizeAngle( 180+angle0-angle1+angleEpsilon ); - if (d > distanceEpsilon || a > angleEpsilon*2.0) { - DisconnectTracks( trk, ep0, trk1, ep1 ); - count++; - InfoMessage( _("%d Track(s) loosened"), count ); - } + if (QueryTrack(trk0,Q_ISTRAIN)) { + if (!QueryTrack(trk1,Q_ISTRAIN)) { + NoticeMessage( _("Connecting a car to a non-car T%d T%d"), _("Continue"), NULL, + GetTrkIndex(trk0), GetTrkIndex(trk1) ); + return -1; } + SetEndPtTrack( epp0, trk1 ); + SetEndPtTrack( epp1, trk0 ); + return 0; } - if (count) - MainRedraw(); // LoosenTracks - else - InfoMessage(_("No tracks loosened")); -} - -EXPORT int ConnectTracks( track_p trk0, EPINX_T inx0, track_p trk1, EPINX_T inx1 ) -{ - DIST_T d; - ANGLE_T a; - coOrd pos0, pos1; if ( !IsTrack(trk0) ) { - NoticeMessage( _("Connecting a non-track(%d) to (%d)"), _("Continue"), NULL, GetTrkIndex(trk0), GetTrkIndex(trk1) ); + NoticeMessage( _("Connecting a non-track(%d) to (%d)"), _("Continue"), NULL, + GetTrkIndex(trk0), GetTrkIndex(trk1) ); return -1; } if ( !IsTrack(trk1) ) { - NoticeMessage( _("Connecting a non-track(%d) to (%d)"), _("Continue"), NULL, GetTrkIndex(trk1), GetTrkIndex(trk0) ); + NoticeMessage( _("Connecting a non-track(%d) to (%d)"), _("Continue"), NULL, + GetTrkIndex(trk1), GetTrkIndex(trk0) ); 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 ) ) + pos0 = GetEndPtPos( epp0 ); + pos1 = GetEndPtPos( epp1 ); + 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 = fabs(DifferenceBetweenAngles( trk0->endPt[inx0].angle, - trk1->endPt[inx1].angle + 180.0 )); + a = fabs(DifferenceBetweenAngles( GetEndPtAngle(epp0), + GetEndPtAngle(epp1) + 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 ); + 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 ); - if (!suspendElevUpdates) + if (!suspendElevUpdates) { SetTrkElevModes( TRUE, trk0, inx0, trk1, inx1 ); - trk0->endPt[inx0].track = trk1; - trk1->endPt[inx1].track = trk0; - AuditTracks( "connectTracks T%d[%d], T%d[%d]", trk0->index, inx0, trk1->index, inx1 ); + } + SetEndPtTrack( epp0, trk1 ); + SetEndPtTrack( epp1, trk0 ); + AuditTracks( "connectTracks T%d[%d], T%d[%d]", trk0->index, inx0, trk1->index, + inx1 ); return 0; } -EXPORT void DisconnectTracks( track_p trk1, EPINX_T ep1, track_p trk2, EPINX_T ep2 ) +EXPORT void DisconnectTracks( track_p trk1, EPINX_T ep1, track_p trk2, + EPINX_T ep2 ) { - if (trk1->endPt[ep1].track != trk2 || - trk2->endPt[ep2].track != trk1 ) - AbortProg("disconnectTracks: tracks not connected" ); + trkEndPt_p epp1 = EndPtIndex( trk1->endPt, ep1 ); + trkEndPt_p epp2 = EndPtIndex( trk2->endPt, ep2 ); + // Check tracks are connected + CHECK( GetEndPtTrack(epp1) == trk2 ); + CHECK( GetEndPtTrack(epp2) == trk1 ); + if (QueryTrack(trk1,Q_ISTRAIN)) { + if (!QueryTrack(trk2,Q_ISTRAIN)) { + NoticeMessage( _("Disconnecting a car from a non-car T%d T%d"), _("Continue"), + NULL, GetTrkIndex(trk1), GetTrkIndex(trk2) ); + return; + } + SetEndPtTrack( epp1, NULL ); + SetEndPtTrack( epp2, NULL ); + return; + } + UndoModify( trk1 ); UndoModify( trk2 ); - trk1->endPt[ep1].track = NULL; - trk2->endPt[ep2].track = NULL; - if (!suspendElevUpdates) + SetEndPtTrack( epp1, NULL ); + SetEndPtTrack( epp2, NULL ); + if (!suspendElevUpdates) { SetTrkElevModes( FALSE, trk1, ep1, trk2, ep2 ); + } } EXPORT BOOL_T ConnectAbuttingTracks( - track_p trk0, - EPINX_T ep0, - track_p trk1, - EPINX_T ep1 ) + track_p trk0, + EPINX_T ep0, + track_p trk1, + EPINX_T ep1 ) { DIST_T d; ANGLE_T a; d = FindDistance( GetTrkEndPos(trk0,ep0), - GetTrkEndPos(trk1,ep1 ) ); + GetTrkEndPos(trk1,ep1 ) ); a = NormalizeAngle( GetTrkEndAngle(trk0,ep0) - - GetTrkEndAngle(trk1,ep1) + - (180.0+connectAngle/2.0) ); - if ( a < connectAngle && - d < connectDistance ) { - UndoStart( _("Join Abutting Tracks"), "ConnectAbuttingTracks( T%d[%d] T%d[%d] )", GetTrkIndex(trk0), ep0, GetTrkIndex(trk1), ep1 ); + GetTrkEndAngle(trk1,ep1) + + (180.0+connectAngle/2.0) ); + if ( a < connectAngle && + d < connectDistance ) { + UndoStart( _("Join Abutting Tracks"), + "ConnectAbuttingTracks( T%d[%d] T%d[%d] )", GetTrkIndex(trk0), ep0, + GetTrkIndex(trk1), ep1 ); DrawEndPt( &mainD, trk0, ep0, wDrawColorWhite ); DrawEndPt( &mainD, trk1, ep1, wDrawColorWhite ); ConnectTracks( trk0, ep0, - trk1, ep1 ); + trk1, ep1 ); DrawEndPt( &mainD, trk0, ep0, wDrawColorBlack ); DrawEndPt( &mainD, trk1, ep1, wDrawColorBlack ); UndoEnd(); @@ -2016,20 +2094,22 @@ EXPORT BOOL_T ConnectAbuttingTracks( } -EXPORT ANGLE_T GetAngleAtPoint( track_p trk, coOrd pos, EPINX_T *ep0, EPINX_T *ep1 ) +EXPORT ANGLE_T GetAngleAtPoint( track_p trk, coOrd pos, EPINX_T *ep0, + EPINX_T *ep1 ) { ANGLE_T (*getAngleCmd)( track_p, coOrd, EPINX_T *, EPINX_T * ); - if ((getAngleCmd = trackCmds(trk->type)->getAngle) != NULL) + if ((getAngleCmd = trackCmds(trk->type)->getAngle) != NULL) { return getAngleCmd( trk, pos, ep0, ep1 ); - else { + } else { NoticeMessage( MSG_GAAP_BAD_TYPE, _("Continue"), NULL, trk->type, trk->index ); return 0; } } -EXPORT BOOL_T SplitTrack( track_p trk, coOrd pos, EPINX_T ep, track_p *leftover, BOOL_T disconnect ) +EXPORT BOOL_T SplitTrack( track_p trk, coOrd pos, EPINX_T ep, track_p *leftover, + BOOL_T disconnect ) { DIST_T d; track_p trk0, trk2, trkl; @@ -2038,28 +2118,45 @@ EXPORT BOOL_T SplitTrack( track_p trk, coOrd pos, EPINX_T ep, track_p *leftover, BOOL_T (*splitCmd)( track_p, coOrd, EPINX_T, track_p *, EPINX_T *, EPINX_T * ); coOrd pos0; + if (!IsTrack(trk)) { + if ((splitCmd = trackCmds(trk->type)->split) == NULL) { return FALSE; } + UndrawNewTrack( trk ); + UndoModify( trk ); + rc = splitCmd( trk, pos, ep, leftover, &epl, &ep1 ); + if (*leftover) { + SetTrkLayer(*leftover,GetTrkLayer( trk )); + DrawNewTrack( *leftover ); + } + DrawNewTrack( trk ); + return rc; + } + trk0 = trk; epl = ep; epCnt = GetTrkEndPtCnt(trk); *leftover = NULL; -LOG( log_track, 2, ( "SplitTrack( T%d[%d], (%0.3f %0.3f)\n", trk->index, ep, pos.x, pos.y ) ) + LOG( log_track, 2, ( "SplitTrack( T%d[%d], (%0.3f %0.3f)\n", trk->index, ep, + pos.x, pos.y ) ) + trkEndPt_p epp = EndPtIndex( trk->endPt, ep ); + pos0 = GetEndPtPos( epp ); if (((splitCmd = trackCmds(trk->type)->split) == NULL)) { - if (!(FindDistance( trk->endPt[ep].pos, pos) <= minLength)) { - ErrorMessage( MSG_CANT_SPLIT_TRK, trackCmds(trk->type)->name ); - return FALSE; + if (!(FindDistance( pos0, pos) <= minLength)) { + ErrorMessage(MSG_SPLITTED_OBJECT_TOO_SHORT, PutDim(fabs(minLength))); + return FALSE; } } UndrawNewTrack( trk ); UndoModify( trk ); - pos0 = trk->endPt[ep].pos; if ((d = FindDistance( pos0, pos )) <= minLength) { /* easy: just disconnect */ - if ((trk2=trk->endPt[ep].track) != NULL) { + trk2 = GetEndPtTrack(epp); + if (trk2 != NULL) { UndrawNewTrack( trk2 ); ep2 = GetEndPtConnectedToMe( trk2, trk ); - if (ep2 < 0) + if (ep2 < 0) { return FALSE; + } DisconnectTracks( trk, ep, trk2, ep2 ); LOG( log_track, 2, ( " at endPt with T%d[%d]\n", trk2->index, ep2 ) ) DrawNewTrack( trk2 ); @@ -2070,13 +2167,15 @@ LOG( log_track, 2, ( "SplitTrack( T%d[%d], (%0.3f %0.3f)\n", trk->index, ep, pos } else if ( epCnt == 2 && - (d = FindDistance( trk->endPt[1-ep].pos, pos )) <= minLength) { + (d = FindDistance( GetEndPtPos(EndPtIndex(trk->endPt,1-ep)), + pos )) <= minLength) { /* easy: just disconnect */ - if ((trk2=trk->endPt[1-ep].track) != NULL) { + if ((trk2=GetEndPtTrack(EndPtIndex(trk->endPt,1-ep))) != NULL) { UndrawNewTrack( trk2 ); ep2 = GetEndPtConnectedToMe( trk2, trk ); - if (ep2 < 0) + if (ep2 < 0) { return FALSE; + } DisconnectTracks( trk, 1-ep, trk2, ep2 ); LOG( log_track, 2, ( " at endPt with T%d[%d]\n", trk2->index, ep2 ) ) DrawNewTrack( trk2 ); @@ -2089,16 +2188,18 @@ LOG( log_track, 2, ( "SplitTrack( T%d[%d], (%0.3f %0.3f)\n", trk->index, ep, pos } else { /* TODO circle's don't have ep's */ trk2 = GetTrkEndTrk( trk, ep ); - if ( !disconnect ) + if ( !disconnect ) { suspendElevUpdates = TRUE; + } if (trk2 != NULL) { ep2 = GetEndPtConnectedToMe( trk2, trk ); DisconnectTracks( trk, ep, trk2, ep2 ); } rc = splitCmd( trk, pos, ep, leftover, &epl, &ep1 ); if (!rc) { - if ( trk2 != NULL ) + if ( trk2 != NULL ) { ConnectTracks( trk, ep, trk2, ep2 ); + } suspendElevUpdates = FALSE; DrawNewTrack( trk ); return FALSE; @@ -2107,20 +2208,23 @@ LOG( log_track, 2, ( "SplitTrack( T%d[%d], (%0.3f %0.3f)\n", trk->index, ep, pos if (*leftover) { trkl = *leftover; ep0 = epl; - if ( !disconnect ) + if ( !disconnect ) { ConnectTracks( trk, ep, trkl, epl ); + } ep0 = 1-epl; while ( 1 ) { CopyAttributes( trk, trkl ); ClrTrkElev( trkl ); trk0 = GetTrkEndTrk(trkl,ep0); - if ( trk0 == NULL || trk0->type == T_TURNOUT ) + if ( trk0 == NULL || trk0->type == T_TURNOUT ) { break; + } ep0 = 1-GetEndPtConnectedToMe(trk0,trkl); trkl = trk0; } - if (trk2) + if (trk2) { ConnectTracks( trkl, ep0, trk2, ep2 ); + } LOG( log_track, 2, ( " midTrack (leftover = T%d)\n", (trkl)->index ) ) } suspendElevUpdates = FALSE; @@ -2131,8 +2235,9 @@ 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 || trk0->type == T_TURNOUT) + if ( trk0 == NULL || trk0 == trk2 || trk0->type == T_TURNOUT) { break; + } ep0 = 1-GetEndPtConnectedToMe(trk0,trkl); trkl = trk0; } @@ -2143,30 +2248,35 @@ LOG( log_track, 2, ( "SplitTrack( T%d[%d], (%0.3f %0.3f)\n", trk->index, ep, pos EXPORT BOOL_T TraverseTrack( - traverseTrack_p trvTrk, - DIST_T * distR ) + traverseTrack_p trvTrk, + DIST_T * distR ) { track_p oldTrk; EPINX_T ep; while ( *distR > 0.0 && trvTrk->trk ) { - if ( trackCmds((trvTrk->trk)->type)->traverse == NULL ) + if ( trackCmds((trvTrk->trk)->type)->traverse == NULL ) { return FALSE; + } oldTrk = trvTrk->trk; - if ( !trackCmds((trvTrk->trk)->type)->traverse( trvTrk, distR ) ) + if ( !trackCmds((trvTrk->trk)->type)->traverse( trvTrk, distR ) ) { return FALSE; - if ( *distR <= 0.0 ) + } + if ( *distR <= 0.0 ) { return TRUE; - if ( !trvTrk->trk ) + } + if ( !trvTrk->trk ) { return FALSE; + } ep = GetNearestEndPtConnectedToMe( trvTrk->trk, oldTrk, trvTrk->pos ); if ( ep != -1 ) { trvTrk->pos = GetTrkEndPos( trvTrk->trk, ep ); trvTrk->angle = NormalizeAngle( GetTrkEndAngle( trvTrk->trk, ep ) + 180.0 ); } if ( trackCmds((trvTrk->trk)->type)->checkTraverse && - !trackCmds((trvTrk->trk)->type)->checkTraverse( trvTrk->trk, trvTrk->pos ) ) + !trackCmds((trvTrk->trk)->type)->checkTraverse( trvTrk->trk, trvTrk->pos ) ) { return FALSE; + } trvTrk->length = -1; trvTrk->dist = 0.0; @@ -2181,20 +2291,25 @@ EXPORT BOOL_T RemoveTrack( track_p * trk, EPINX_T * ep, DIST_T *dist ) track_p trk1; EPINX_T ep1=-1; while ( *dist > 0.0 ) { - if (trackCmds((*trk)->type)->getLength == NULL) + if (trackCmds((*trk)->type)->getLength == NULL) { return FALSE; - if (GetTrkEndPtCnt(*trk) != 2) + } + if (GetTrkEndPtCnt(*trk) != 2) { return FALSE; + } dist1 = trackCmds((*trk)->type)->getLength(*trk); - if ( dist1 > *dist ) + if ( dist1 > *dist ) { break; + } *dist -= dist1; trk1 = GetTrkEndTrk( *trk, 1-*ep ); - if (trk1) + if (trk1) { ep1 = GetEndPtConnectedToMe( trk1, *trk ); + } DeleteTrack( *trk, FALSE ); - if (!trk1) + if (!trk1) { return FALSE; + } *trk = trk1; *ep = ep1; } @@ -2204,22 +2319,26 @@ EXPORT BOOL_T RemoveTrack( 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 ) +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) + if (trackCmds(trk->type)->trim) { return trackCmds(trk->type)->trim( trk, ep, dist, pos, angle, radius, center ); - else + } else { return FALSE; + } } -EXPORT BOOL_T MergeTracks( track_p trk0, EPINX_T ep0, track_p trk1, EPINX_T ep1 ) +EXPORT BOOL_T MergeTracks( track_p trk0, EPINX_T ep0, track_p trk1, + EPINX_T ep1 ) { if (trk0->type == trk1->type && - trackCmds(trk0->type)->merge) + trackCmds(trk0->type)->merge) { return trackCmds(trk0->type)->merge( trk0, ep0, trk1, ep1 ); - else + } else { return FALSE; + } } EXPORT STATUS_T ExtendTrackFromOrig( track_p trk, wAction_t action, coOrd pos ) @@ -2236,15 +2355,17 @@ EXPORT STATUS_T ExtendTrackFromOrig( track_p trk, wAction_t action, coOrd pos ) switch ( action ) { case C_DOWN: ep = PickUnconnectedEndPoint( pos, trk ); - if ( ep == -1 ) + if ( ep == -1 ) { return C_ERROR; + } pos = GetTrkEndPos(trk,ep); - if (!GetTrackParams(PARAMS_CORNU,trk,pos,¶ms)) return C_ERROR; + if (!GetTrackParams(PARAMS_CORNU,trk,pos,¶ms)) { return C_ERROR; } end_pos = pos; + DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); if (params.type == curveTypeCurve) { curved = TRUE; tempSegs(0).type = SEG_CRVTRK; - tempSegs(0).width = 0; + tempSegs(0).lineWidth = 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)); @@ -2252,23 +2373,29 @@ EXPORT STATUS_T ExtendTrackFromOrig( track_p trk, wAction_t action, coOrd pos ) } else { curved = FALSE; tempSegs(0).type = SEG_STRTRK; - tempSegs(0).width = 0; + tempSegs(0).lineWidth = 0; tempSegs(0).u.l.pos[0] = tempSegs(0).u.l.pos[1] = GetTrkEndPos( trk, ep ); } valid = FALSE; InfoMessage( _("Drag to change track length") ); + DYNARR_RESET( trkSeg_t, tempSegs_da ); return C_CONTINUE; - /*no break*/ + case C_MOVE: + DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); 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); + 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) + if (action == C_MOVE) { ErrorMessage( MSG_TRK_TOO_SHORT, _("Connecting "), PutDim(fabs(minLength-d)) ); + } valid = FALSE; + DYNARR_RESET( trkSeg_t, tempSegs_da ); return C_CONTINUE; } //Restrict to outside track @@ -2278,6 +2405,7 @@ EXPORT STATUS_T ExtendTrackFromOrig( track_p trk, wAction_t action, coOrd pos ) tempSegs(0).u.c.a1 = 0; tempSegs(0).u.c.a0 = end_angle; InfoMessage( _("Inside turnout track")); + DYNARR_RESET( trkSeg_t, tempSegs_da ); return C_CONTINUE; } end_angle = GetTrkEndAngle( trk, ep ); @@ -2285,51 +2413,57 @@ EXPORT STATUS_T ExtendTrackFromOrig( track_p trk, wAction_t action, coOrd 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))) { + (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) ) ); + FormatDistance( d ), FormatDistance(tempSegs(0).u.c.radius), + PutAngle( tempSegs(0).u.c.a1 )); return C_CONTINUE; } else { d = FindDistance( end_pos, pos ); valid = TRUE; if ( d <= minLength ) { - if (action == C_MOVE) + if (action == C_MOVE) { ErrorMessage( MSG_TRK_TOO_SHORT, _("Connecting "), PutDim(fabs(minLength-d)) ); + } valid = FALSE; + DYNARR_RESET( trkSeg_t, tempSegs_da ); return C_CONTINUE; } - ANGLE_T diff = NormalizeAngle(GetTrkEndAngle( trk, ep )-FindAngle(end_pos, pos)); + 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")); + DYNARR_RESET( trkSeg_t, tempSegs_da ); return C_CONTINUE; } - Translate( &tempSegs(0).u.l.pos[1], tempSegs(0).u.l.pos[0], GetTrkEndAngle( trk, ep ), d ); - tempSegs_da.cnt = 1; + + Translate( &tempSegs(0).u.l.pos[1], tempSegs(0).u.l.pos[0], GetTrkEndAngle( trk, + ep ), d ); if (action == C_MOVE) InfoMessage( _("Straight: Length=%s Angle=%0.3f"), - FormatDistance( d ), PutAngle( GetTrkEndAngle( trk, ep ) ) ); + FormatDistance( d ), PutAngle( GetTrkEndAngle( trk, ep ) ) ); } return C_CONTINUE; case C_UP: - if (!valid) + if (!valid) { return C_TERMINATE; + } + DYNARR_RESET( trkSeg_t, tempSegs_da ); 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); + 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] ); @@ -2347,7 +2481,8 @@ EXPORT STATUS_T ExtendTrackFromOrig( track_p trk, wAction_t action, coOrd pos ) return C_ERROR; } -EXPORT STATUS_T ExtendStraightFromOrig( track_p trk, wAction_t action, coOrd pos ) +EXPORT STATUS_T ExtendStraightFromOrig( track_p trk, wAction_t action, + coOrd pos ) { static EPINX_T ep; static BOOL_T valid; @@ -2357,10 +2492,12 @@ EXPORT STATUS_T ExtendStraightFromOrig( track_p trk, wAction_t action, coOrd pos switch ( action ) { case C_DOWN: ep = PickUnconnectedEndPoint( pos, trk ); - if ( ep == -1 ) + if ( ep == -1 ) { return C_ERROR; + } + DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); tempSegs(0).type = SEG_STRTRK; - tempSegs(0).width = 0; + tempSegs(0).lineWidth = 0; tempSegs(0).u.l.pos[0] = GetTrkEndPos( trk, ep ); InfoMessage( _("Drag to change track length") ); @@ -2368,21 +2505,23 @@ EXPORT STATUS_T ExtendStraightFromOrig( track_p trk, wAction_t action, coOrd pos d = FindDistance( tempSegs(0).u.l.pos[0], pos ); valid = TRUE; if ( d <= minLength ) { - if (action == C_MOVE) + if (action == C_MOVE) { ErrorMessage( MSG_TRK_TOO_SHORT, _("Connecting "), PutDim(fabs(minLength-d)) ); + } valid = FALSE; return C_CONTINUE; } - Translate( &tempSegs(0).u.l.pos[1], tempSegs(0).u.l.pos[0], GetTrkEndAngle( trk, ep ), d ); - tempSegs_da.cnt = 1; + Translate( &tempSegs(0).u.l.pos[1], tempSegs(0).u.l.pos[0], GetTrkEndAngle( trk, + ep ), d ); if (action == C_MOVE) InfoMessage( _("Straight: Length=%s Angle=%0.3f"), - FormatDistance( d ), PutAngle( GetTrkEndAngle( trk, ep ) ) ); + FormatDistance( d ), PutAngle( GetTrkEndAngle( trk, ep ) ) ); return C_CONTINUE; case C_UP: - if (!valid) + if (!valid) { return C_TERMINATE; + } UndrawNewTrack( trk ); trk1 = NewStraightTrack( tempSegs(0).u.l.pos[0], tempSegs(0).u.l.pos[1] ); CopyAttributes( trk, trk1 ); @@ -2409,12 +2548,13 @@ EXPORT STATUS_T ModifyTrack( track_p trk, wAction_t action, coOrd pos ) } -EXPORT BOOL_T GetTrackParams( int inx, track_p trk, coOrd pos, trackParams_t * params ) +EXPORT BOOL_T GetTrackParams( int inx, track_p trk, coOrd pos, + trackParams_t * params ) { if ( trackCmds(trk->type)->getTrackParams ) { return trackCmds(trk->type)->getTrackParams( inx, trk, pos, params ); } else { - ASSERT( FALSE ); /* CHECKME */ + CHECK( FALSE ); /* CHECKME */ return FALSE; } } @@ -2473,23 +2613,29 @@ EXPORT DIST_T GetFlexLength( track_p trk0, EPINX_T ep, coOrd * pos ) d = 0.0; while(1) { trk1 = GetTrkEndTrk( trk, ep ); - if (trk1 == NULL) + if (trk1 == NULL) { break; - if (trk1 == trk0) + } + if (trk1 == trk0) { break; + } ep1 = GetEndPtConnectedToMe( trk1, trk ); - if (ep1 < 0 || ep1 > 1) + if (ep1 < 0 || ep1 > 1) { break; - if (trackCmds(trk1->type)->getLength == NULL) + } + if (trackCmds(trk1->type)->getLength == NULL) { break; + } dd = trackCmds(trk1->type)->getLength(trk1); - if (dd <= 0.0) + if (dd <= 0.0) { break; + } d += dd; trk = trk1; ep = 1-ep1; - if (d>1000000.0) + if (d>DIST_INF) { break; + } } *pos = GetTrkEndPos( trk, ep ); return d; @@ -2500,12 +2646,13 @@ EXPORT DIST_T GetTrkLength( track_p trk, EPINX_T ep0, EPINX_T ep1 ) { coOrd pos0, pos1; DIST_T d; - if (ep0 == ep1) + if (ep0 == ep1) { return 0.0; - else if (trackCmds(trk->type)->getLength != NULL) { + } else if (trackCmds(trk->type)->getLength != NULL) { d = trackCmds(trk->type)->getLength(trk); - if (ep1==-1) - d /= 2.0; + if (ep1==-1) { + d = d/2.0; + } return d; } else { pos0 = GetTrkEndPos(trk,ep0); @@ -2545,13 +2692,10 @@ EXPORT DIST_T GetTrkLength( track_p trk, EPINX_T ep0, EPINX_T ep1 ) return fabs(pos1.y); } } -#endif /*#define DRAW_TUNNEL_NONE (0)*/ #define DRAW_TUNNEL_DASH (1) #define DRAW_TUNNEL_SOLID (2) EXPORT long drawTunnel = DRAW_TUNNEL_DASH; -EXPORT long colorTrack; -EXPORT long colorDraw; /****************************************************************************** * @@ -2561,33 +2705,86 @@ EXPORT long colorDraw; EXPORT long tieDrawMode = TIEDRAWMODE_SOLID; EXPORT wDrawColor tieColor; +EXPORT wDrawColor bridgeColor; +EXPORT wDrawColor roadbedColor; + +/** + * Draw tracks with 2 rails when zoomed in + * + * \param d drawing context + * \return true is we draw tracks with 2 rails + */ +EXPORT BOOL_T DrawTwoRails( drawCmd_p d, DIST_T factor ) +{ + DIST_T scale = twoRailScale; + if ( d->options&DC_PRINT ) { + scale = scale*2+1; + } + scale /= factor; + return d->scale <= scale; +} + + +/** + * Centerline drawing test + * + * \param d drawing context + * \return true for centerline, false if no centerline to draw + */ + +EXPORT BOOL_T +hasTrackCenterline( drawCmd_p d ) +{ + // for printing, drawing of center line depends on the scale + if( d->options & DC_CENTERLINE && d->options & DC_PRINT ) { + return DrawTwoRails(d,1); + } + + // all other cases of explicit centerline option (ie. bitmap) + if( d->options & DC_CENTERLINE ) { + return true; + } + + // if zoomed in beyond 1:1 draw centerline when not doing a simple draw + if( ( d->scale <= 1.0 ) && !( d->options & DC_SIMPLE ) ) { + return true; + } + + return false; +} -static wBool_t DoDrawTies( drawCmd_p d, track_cp trk ) +EXPORT wBool_t +DoDrawTies( drawCmd_p d, track_cp trk ) { - DIST_T scale2rail = (d->options&DC_PRINT)?(twoRailScale*2+1):twoRailScale; - if ( !trk ) + if ( !trk ) { return FALSE; - if (GetTrkNoTies(trk)) - return FALSE; //No Ties for this Track - if ( tieDrawMode == TIEDRAWMODE_NONE ) + } + if (GetTrkNoTies(trk)) { + return FALSE; //No Ties for this Track + } + if ( tieDrawMode == TIEDRAWMODE_NONE ) { return FALSE; - if ( d == &mapD ) + } + if ( d == &mapD ) { return FALSE; - if ( d->scale >= scale2rail ) + } + if ( !DrawTwoRails(d,1) ) { return FALSE; - if ( !(GetTrkVisible(trk) || drawTunnel==DRAW_TUNNEL_SOLID) ) + } + if ( !(GetTrkVisible(trk) || drawTunnel==DRAW_TUNNEL_SOLID) ) { return FALSE; + } return TRUE; } EXPORT void DrawTie( - drawCmd_p d, - coOrd pos, - ANGLE_T angle, - DIST_T length, - DIST_T width, - wDrawColor color, - BOOL_T solid ) + drawCmd_p d, + coOrd pos, + ANGLE_T angle, + DIST_T length, + DIST_T width, + wDrawColor color, + BOOL_T solid ) { coOrd lo, hi; coOrd p[4]; @@ -2609,7 +2806,7 @@ 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++) { + for (int i=0; i<4; i++) { t[i] = 0; } @@ -2618,342 +2815,53 @@ EXPORT void DrawTie( lo.y -= TBORDER/mainD.dpi*mainD.scale; hi.x += LBORDER/mainD.dpi*mainD.scale; hi.y += BBORDER/mainD.dpi*mainD.scale; - if ( OFF_D( d->orig, d->size, lo, hi ) ) + if ( OFF_D( d->orig, d->size, lo, hi ) ) { return; - } - if ( solid ) { - DrawPoly( d, 4, p, t, color, 0, 1, 0 ); - } else { - DrawPoly( d, 4, p, t, color, 0, 0, 0); - } -} - - -static void DrawCurvedTies( - drawCmd_p d, - SCALEINX_T scaleInx, - coOrd p, - DIST_T r, - ANGLE_T a0, - ANGLE_T a1, - wDrawColor color ) -{ - tieData_p td; - DIST_T len; - ANGLE_T ang, dang; - coOrd pos; - int cnt; - - if ( (d->options&DC_SIMPLE) != 0 ) - return; - - if ( scaleInx < 0 ) - return; - td = GetScaleTieData( scaleInx ); - - if (color == wDrawColorBlack) - color = tieColor; - len = 2*M_PI*r*a1/360.0; - 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 = (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 ); - } - - } -} - - -EXPORT void DrawCurvedTrack( - drawCmd_p d, - coOrd p, - DIST_T r, - ANGLE_T a0, - ANGLE_T a1, - coOrd p0, - coOrd p1, - track_p trk, - wDrawColor color, - long options ) -{ - DIST_T scale2rail; - DIST_T trackGauge = GetTrkGauge(trk); - wDrawWidth width=0; - trkSeg_p segPtr; - - if ( (d->options&DC_SEGTRACK) ) { - DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 ); - segPtr = &tempSegs(tempSegs_da.cnt-1); - segPtr->type = SEG_CRVTRK; - segPtr->width = 0; - segPtr->color = wDrawColorBlack; - segPtr->u.c.center = p; - segPtr->u.c.a0 = a0; - segPtr->u.c.a1 = a1; - segPtr->u.c.radius = r; - return; - } - - scale2rail = (d->options&DC_PRINT)?(twoRailScale*2+1):twoRailScale; - 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); -#else - if (d->options&DC_PRINT) - width *= 300/75; -#endif - -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 ( 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->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 - long options = d->options; - d->options |= DC_DASH; - DrawArc( d, p, r, a0, a1, 0, 0, color ); - d->options = options; - } - DrawArc( d, p, r+trackGauge/2.0, a0, a1, 0, width, color ); - DrawArc( d, p, r-trackGauge/2.0, a0, a1, (centerDrawMode && !(options&DTS_NOCENTER) ? 1: 0), width, color ); - if ( (d->options&DC_PRINT) && roadbedWidth > trackGauge && d->scale <= scale2rail/2 ) { - wDrawWidth rbw = (wDrawWidth)floor(roadbedLineWidth*(d->dpi/d->scale)+0.5); - if ( options&DTS_RIGHT ) { - DrawArc( d, p, r+roadbedWidth/2.0, a0, a1, 0, rbw, color ); - } - if ( options&DTS_LEFT ) { - DrawArc( d, p, r-roadbedWidth/2.0, a0, a1, 0, rbw, color ); - } - } - } - 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 ); - } - -} - - -static void DrawStraightTies( - drawCmd_p d, - SCALEINX_T scaleInx, - coOrd p0, - coOrd p1, - wDrawColor color ) -{ - tieData_p td; - DIST_T tieOff0=0.0, tieOff1=0.0; - DIST_T len, dlen; - coOrd pos; - int cnt; - ANGLE_T angle; - - if ( (d->options&DC_SIMPLE) != 0 ) - return; - - if ( color == wDrawColorBlack ) - color = tieColor; - if ( scaleInx < 0 ) - return; - td = GetScaleTieData( scaleInx ); - len = FindDistance( p0, p1 ); - len -= tieOff0+tieOff1; - angle = FindAngle( p0, p1 ); - 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 = 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 ); - } - } -} - - -EXPORT void DrawStraightTrack( - drawCmd_p d, - coOrd p0, - coOrd p1, - ANGLE_T angle, - track_cp trk, - wDrawColor color, - long options ) -{ - coOrd pp0, pp1; - DIST_T scale2rail; - DIST_T trackGauge = GetTrkGauge(trk); - wDrawWidth width=0; - trkSeg_p segPtr; - - if ( (d->options&DC_SEGTRACK) ) { - DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 ); - segPtr = &tempSegs(tempSegs_da.cnt-1); - segPtr->type = SEG_STRTRK; - segPtr->width = 0; - segPtr->color = wDrawColorBlack; - segPtr->u.l.pos[0] = p0; - segPtr->u.l.pos[1] = p1; - segPtr->u.l.angle = angle; - segPtr->u.l.option = 0; - return; } - - scale2rail = (d->options&DC_PRINT)?(twoRailScale*2+1):twoRailScale; - - 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); -#else - if (d->options&DC_PRINT) - width *= 300/75; -#endif -LOG( log_track, 4, ( "DST( (%0.3f %0.3f) .. (%0.3f..%0.3f)\n", - p0.x, p0.y, p1.x, p1.y ) ) - 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 ); + if ( solid ) { + DrawPoly( d, 4, p, t, color, 0, DRAW_FILL ); } 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 - long options = d->options; - d->options |= DC_DASH; - DrawLine( d, p0, p1, 0, color ); - d->options = options; - } - Translate( &pp0, p0, angle+90, trackGauge/2.0 ); - Translate( &pp1, p1, angle+90, trackGauge/2.0 ); - DrawLine( d, pp0, pp1, width, color ); - Translate( &pp0, p0, angle-90, trackGauge/2.0 ); - Translate( &pp1, p1, angle-90, trackGauge/2.0 ); - DrawLine( d, pp0, pp1, width, color ); - if ( (d->options&DC_PRINT) && roadbedWidth > trackGauge && d->scale <= scale2rail/2.0) { - wDrawWidth rbw = (wDrawWidth)floor(roadbedLineWidth*(d->dpi/d->scale)+0.5); - if ( options&DTS_RIGHT ) { - Translate( &pp0, p0, angle+90, roadbedWidth/2.0 ); - Translate( &pp1, p1, angle+90, roadbedWidth/2.0 ); - DrawLine( d, pp0, pp1, rbw, color ); - } - if ( options&DTS_LEFT ) { - Translate( &pp0, p0, angle-90, roadbedWidth/2.0 ); - Translate( &pp1, p1, angle-90, roadbedWidth/2.0 ); - DrawLine( d, pp0, pp1, rbw, color ); - } - } - } - 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 ); - + DrawPoly( d, 4, p, t, color, 0, DRAW_CLOSED); } } EXPORT wDrawColor GetTrkColor( track_p trk, drawCmd_p d ) { - DIST_T len, len1, elev0, elev1; + DIST_T len, elev0, elev1; ANGLE_T grade = 0.0; if ( IsTrack( trk ) && GetTrkEndPtCnt(trk) == 2 ) { - 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; - } + ComputeElev( trk, 0, FALSE, &elev0, NULL, FALSE ); + len = GetTrkLength( trk, 0, 1 ); + ComputeElev( trk, 1, FALSE, &elev1, NULL, FALSE ); + if (len>0.1) { + grade = fabs( (elev1-elev0)/len)*100.0; } } - if ( (d->options&(DC_SIMPLE|DC_SEGTRACK)) != 0 ) + if ( (d->options&(DC_SIMPLE|DC_SEGTRACK)) != 0 ) { return wDrawColorBlack; - if ( grade > GetLayoutMaxTrackGrade()) + } + if ( grade > GetLayerMaxTrackGrade(GetTrkLayer(trk))) { return exceptionColor; - if ( QueryTrack( trk, Q_EXCEPTION ) ) + } + if ( QueryTrack( trk, Q_EXCEPTION ) ) { return exceptionColor; + } if ( (d->options&(DC_PRINT)) == 0 ) { - if (GetTrkBits(trk)&TB_PROFILEPATH) + if (GetTrkBits(trk)&TB_PROFILEPATH) { return profilePathColor; - if ((d->options&DC_PRINT)==0 && GetTrkSelected(trk)) + } + if ((d->options&DC_PRINT)==0 && GetTrkSelected(trk) && d == &tempD) { return selectedColor; + } } if ( (IsTrack(trk)?(colorTrack):(colorDraw)) ) { unsigned int iLayer = GetTrkLayer( trk ); - if (GetLayerUseColor( iLayer ) ) + if (GetLayerUseColor( iLayer ) ) { return GetLayerColor( iLayer ); + } } return wDrawColorBlack; } @@ -2964,31 +2872,37 @@ EXPORT void DrawTrack( track_cp trk, drawCmd_p d, wDrawColor color ) TRKTYP_T trkTyp; // Hack for WINDOWS - if ( trk->bits & TB_UNDRAWN ) + if ( trk->bits & TB_UNDRAWN ) { return; + } trkTyp = GetTrkType(trk); curTrackLayer = GetTrkLayer(trk); if (d != &mapD ) { if ( (!GetTrkVisible(trk)) ) { - if ( drawTunnel==DRAW_TUNNEL_NONE ) + if ( drawTunnel==DRAW_TUNNEL_NONE ) { return; - if ( drawTunnel==DRAW_TUNNEL_DASH ) + } + if ( drawTunnel==DRAW_TUNNEL_DASH ) { d->options |= DC_DASH; + } } if (color == wDrawColorBlack) { color = GetTrkColor( trk, d ); } - if (color == wDrawColorPreviewSelected || color == wDrawColorPreviewUnselected ) { + if (color == wDrawColorPreviewSelected + || color == wDrawColorPreviewUnselected ) { d->options |= DC_THICK; } } - if (d == &mapD && !GetLayerOnMap(curTrackLayer)) + if (d == &mapD && !GetLayerOnMap(curTrackLayer)) { return; + } if ( (IsTrack(trk)?(colorTrack):(colorDraw)) && - d != &mapD && color == wDrawColorBlack ) - if (GetLayerUseColor((unsigned int)curTrackLayer)) + (d != &mapD) && (color == wDrawColorBlack) ) + if (GetLayerUseColor((unsigned int)curTrackLayer)) { color = GetLayerColor((unsigned int)curTrackLayer); + } trackCmds(trkTyp)->draw( trk, d, color ); d->options &= ~DC_DASH; @@ -3022,17 +2936,21 @@ EXPORT void DrawPositionIndicators( void ) { track_p trk; coOrd hi, lo; - if ( !doDrawPositionIndicator ) + if ( !doDrawPositionIndicator ) { return; + } TRK_ITERATE( trk ) { if ( trackCmds(trk->type)->drawPositionIndicator ) { - if ( drawTunnel==DRAW_TUNNEL_NONE && (!GetTrkVisible(trk)) ) + if ( drawTunnel==DRAW_TUNNEL_NONE && (!GetTrkVisible(trk)) ) { continue; + } GetBoundingBox( trk, &hi, &lo ); - if ( OFF_MAIND( lo, hi ) ) + if ( OFF_MAIND( lo, hi ) ) { continue; - if (!GetLayerVisible( GetTrkLayer(trk) ) ) + } + if (!GetLayerVisible( GetTrkLayer(trk) ) ) { continue; + } trackCmds(trk->type)->drawPositionIndicator( trk, selectedColor ); } } @@ -3040,13 +2958,14 @@ EXPORT void DrawPositionIndicators( void ) EXPORT void AdvancePositionIndicator( - track_p trk, - coOrd pos, - coOrd * posR, - ANGLE_T * angleR ) + track_p trk, + coOrd pos, + coOrd * posR, + ANGLE_T * angleR ) { - if ( trackCmds(trk->type)->advancePositionIndicator ) + if ( trackCmds(trk->type)->advancePositionIndicator ) { trackCmds(trk->type)->advancePositionIndicator( trk, pos, posR, angleR ); + } } /***************************************************************************** * @@ -3054,84 +2973,23 @@ EXPORT void AdvancePositionIndicator( * */ -static void DrawUnconnectedEndPt( drawCmd_p d, coOrd p, ANGLE_T a, DIST_T trackGauge, wDrawColor color ) +static void DrawUnconnectedEndPt( drawCmd_p d, coOrd p, ANGLE_T a, + DIST_T trackGauge, wDrawColor color ) { coOrd p0, p1; + Translate( &p0, p, a, trackGauge ); + Translate( &p1, p, a-180.0, trackGauge ); + DrawLine( d, p0, p1, 0, color ); + if (d->scale < 8 || drawUnconnectedEndPt > 0) { + Translate( &p, p, a+90.0, 0.2 ); Translate( &p0, p, a, trackGauge ); Translate( &p1, p, a-180.0, trackGauge ); - DrawLine( d, p0, p1, 0, color ); - if (d->scale < 8 || drawUnconnectedEndPt > 0) { - 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, (color==wDrawColorWhite)?color:(drawUnconnectedEndPt>1)?exceptionColor:color ); - } -} - - -EXPORT void DrawEndElev( drawCmd_p d, track_p trk, EPINX_T ep, wDrawColor color ) -{ - coOrd pp; - wFont_p fp; - elev_t * elev; - track_p trk1; - DIST_T elev0, grade; - ANGLE_T a=0; - int style = BOX_BOX; - BOOL_T gradeOk = TRUE; - char *elevStr; - - if ((labelEnable&LABELENABLE_ENDPT_ELEV)==0) - return; - elev = &trk->endPt[ep].elev; /* TRACKDEP */ - if ( (elev->option&ELEV_MASK)==ELEV_NONE || - (elev->option&ELEV_VISIBLE)==0 ) - return; - if ( (trk1=GetTrkEndTrk(trk,ep)) && GetTrkIndex(trk1)<GetTrkIndex(trk) ) - return; - - fp = wStandardFont( F_HELV, FALSE, FALSE ); - pp = GetTrkEndPos( trk, ep ); - switch ((elev->option&ELEV_MASK)) { - case ELEV_COMP: - case ELEV_GRADE: - if ( color == wDrawColorWhite ) { - elev0 = grade = elev->u.height; - } else if ( !ComputeElev( trk, ep, FALSE, &elev0, &grade, FALSE ) ) { - elev0 = grade = 0; - gradeOk = FALSE; - } - if ((elev->option&ELEV_MASK)==ELEV_COMP) { - elevStr = FormatDistance(elev0); - elev->u.height = elev0; - } else if (gradeOk) { - sprintf( message, "%0.1f%%", round(fabs(grade*100.0)*10)/10 ); - elevStr = message; - a = GetTrkEndAngle( trk, ep ); - style = BOX_ARROW; - if (grade <= -0.001) - a = NormalizeAngle( a+180.0 ); - else if ( grade < 0.001 ) - style = BOX_BOX; - elev->u.height = grade; - } else { - elevStr = "????%%"; - } - break; - case ELEV_DEF: - elevStr = FormatDistance( elev->u.height); - break; - case ELEV_STATION: - elevStr = elev->u.name; - break; - default: - return; + DrawLine( d, p0, p1, (drawUnconnectedEndPt>0)?4:0, + (color==wDrawColorWhite)?color:(drawUnconnectedEndPt>1)?exceptionColor:color ); } - pp.x += elev->doff.x; - pp.y += elev->doff.y; - DrawBoxedString( style, d, pp, elevStr, fp, (wFontSize_t)descriptionFontSize, color, a ); } + /** * Draw track endpoints. The correct track endpoint (connected, unconnected etc.) * is drawn to the track. In case the endpoint is on the transition into a @@ -3144,127 +3002,154 @@ EXPORT void DrawEndElev( drawCmd_p d, track_p trk, EPINX_T ep, wDrawColor color */ EXPORT void DrawEndPt( - drawCmd_p d, - track_p trk, - EPINX_T ep, - wDrawColor color ) + drawCmd_p d, + track_p trk, + EPINX_T ep, + wDrawColor color) { coOrd p; ANGLE_T a; track_p trk1; - coOrd p0, p1, p2; + coOrd p0,p1,p2; BOOL_T sepBoundary; + BOOL_T showBridge = 1; DIST_T trackGauge; wDrawWidth width; wDrawWidth width2; - if ( (d->options & (DC_SIMPLE|DC_SEGTRACK)) != 0) + if((d->options & (DC_SIMPLE | DC_SEGTRACK)) != 0) { return; - if ( trk && QueryTrack( trk, Q_NODRAWENDPT ) ) + } + if(trk && QueryTrack(trk,Q_NODRAWENDPT)) { return; - if (trk == NULL || ep < 0) + } + if(trk == NULL || ep < 0) { return; + } + + // line width for the tunnel portal and bridge parapets, make sure it is rounded correctly + width2 = (wDrawWidth)round((2.0 * d->dpi) / BASE_DPI); + if ((d->options&DC_PRINT) && (d->dpi>2*BASE_DPI)) { + width2 = (wDrawWidth)round(d->dpi / BASE_DPI); + } - // line width for the tunnel portal, make sure it is rounded correctly - width2 = (wDrawWidth)round((2.0 * d->dpi)/75.0); - if (color == wDrawColorBlack) + if(color == wDrawColorBlack) { color = normalColor; + } - if (labelScale >= d->scale) - DrawEndElev( d, trk, ep, color ); + if(((d->options & DC_PRINT) ? (labelScale * 2 + 1) : labelScale) >= d->scale) { + DrawEndElev(d,trk,ep,color); + } trk1 = GetTrkEndTrk(trk,ep); - p = GetTrkEndPos( trk, ep ); - a = GetTrkEndAngle( trk, ep ) + 90.0; + p = GetTrkEndPos(trk,ep); + a = GetTrkEndAngle(trk,ep) + 90.0; trackGauge = GetTrkGauge(trk); - if (trk1 == NULL) { - DrawUnconnectedEndPt( d, p, a, trackGauge, color ); + if(trk1 == NULL) { + DrawUnconnectedEndPt(d,p,a,trackGauge,color); return; } - if ( d->scale >= ((d->options&DC_PRINT)?(twoRailScale*2+1):twoRailScale) ) - return; - sepBoundary = FALSE; - 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( d, p0, p1, 2, selectedColor ); - Translate( &p0, p, a-45, len ); - Translate( &p1, p, a-225, len ); - 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; + if ( DrawTwoRails(d,1) ) { + 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(d,p0,p1,2,selectedColor); + Translate(&p0,p,a - 45,len); + Translate(&p1,p,a - 225,len); + 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; + } } // is the endpoint a transition into a tunnel? - if (GetTrkVisible(trk) && (!GetTrkVisible(trk1))) { + if(GetTrkVisible(trk) && (!GetTrkVisible(trk1))) { // yes, draw tunnel portal - Translate( &p0, p, a, trackGauge ); - Translate( &p1, p, a+180, trackGauge ); - DrawLine( d, p0, p1, width2, color ); - Translate( &p2, p0, a+45, trackGauge/2.0 ); - DrawLine( d, p0, p2, width2, color ); - Translate( &p2, p1, a+135, trackGauge/2.0 ); - DrawLine( d, p1, p2, width2, color ); - if ( d == &mainD ) { - width = (wDrawWidth)ceil(trackGauge*d->dpi/2.0/d->scale); - if ( width > 1 ) { - if ( (GetTrkEndOption(trk,ep)&EPOPT_GAPPED) != 0 ) { - Translate( &p0, p, a, trackGauge ); - DrawLine( d, p0, p, width, color ); + Translate(&p0,p,a,trackGauge); + Translate(&p1,p,a + 180,trackGauge); + DrawLine(d,p0,p1,width2,color); + Translate(&p2,p0,a + 45,trackGauge / 2.0); + DrawLine(d,p0,p2,width2,color); + Translate(&p2,p1,a + 135,trackGauge / 2.0); + DrawLine(d,p1,p2,width2,color); + if(d == &mainD) { + width = (wDrawWidth)ceil(trackGauge * d->dpi / 2.0 / d->scale); + if(width > 1) { + if((GetTrkEndOption(trk,ep) & EPOPT_GAPPED) != 0) { + Translate(&p0,p,a,trackGauge); + DrawLine(d,p0,p,width,color); } trk1 = GetTrkEndTrk(trk,ep); - if ( trk1 ) { - ep = GetEndPtConnectedToMe( trk1, trk ); - if ( (GetTrkEndOption(trk1,ep)&EPOPT_GAPPED) != 0 ) { - Translate( &p0, p, a+180.0, trackGauge ); - DrawLine( d, p0, p, width, color ); + if(trk1) { + ep = GetEndPtConnectedToMe(trk1,trk); + if((GetTrkEndOption(trk1,ep) & EPOPT_GAPPED) != 0) { + Translate(&p0,p,a + 180.0,trackGauge); + DrawLine(d,p0,p,width,color); } } } + showBridge = 0; } - } else if ((!GetTrkVisible(trk)) && GetTrkVisible(trk1)) { - ; - } else if ( GetLayerVisible( GetTrkLayer( trk ) ) && !GetLayerVisible( GetTrkLayer( trk1 ) ) ) { + } else if((!GetTrkVisible(trk)) && GetTrkVisible(trk1)) { + showBridge = 0; + } else if(GetLayerVisible(GetTrkLayer(trk)) + && !GetLayerVisible(GetTrkLayer(trk1))) { a -= 90.0; - Translate( &p, p, a, trackGauge/2.0 ); - Translate( &p0, p, a-135.0, trackGauge*2.0 ); - DrawLine( d, p0, p, width2, color ); - Translate( &p0, p, a+135.0, trackGauge*2.0 ); - DrawLine( d, p0, p, width2, color ); - } else if ( !GetLayerVisible( GetTrkLayer( trk ) ) && GetLayerVisible( GetTrkLayer( trk1 ) ) ) { - ; - } else if ( sepBoundary ) { + Translate(&p,p,a,trackGauge / 2.0); + Translate(&p0,p,a - 135.0,trackGauge * 2.0); + DrawLine(d,p0,p,width2,color); + Translate(&p0,p,a + 135.0,trackGauge * 2.0); + DrawLine(d,p0,p,width2,color); + + showBridge = 0; + } else if(!GetLayerVisible(GetTrkLayer(trk)) + && GetLayerVisible(GetTrkLayer(trk1))) { + showBridge = 0; + } else if(sepBoundary) { ; - } else if ( (drawEndPtV == 1 && (QueryTrack(trk,Q_DRAWENDPTV_1) || QueryTrack(trk1,Q_DRAWENDPTV_1)) ) || - (drawEndPtV == 2) ) { - Translate( &p0, p, a, trackGauge ); + } else if((drawEndPtV == 1 && (QueryTrack(trk,Q_DRAWENDPTV_1) + || QueryTrack(trk1,Q_DRAWENDPTV_1))) || (drawEndPtV == 2)) { + Translate(&p0,p,a,trackGauge); width = 0; - if ( d != &mapD && d != &tempD && (GetTrkEndOption(trk,ep)&EPOPT_GAPPED) != 0 ) - width = (wDrawWidth)ceil(trackGauge*d->dpi/2.0/d->scale); - DrawLine( d, p0, p, width, color ); + if(d != &mapD && d != &tempD && (GetTrkEndOption(trk,ep) & EPOPT_GAPPED) != 0) { + width = (wDrawWidth)ceil(trackGauge * d->dpi / 2.0 / d->scale); + } + DrawLine(d,p0,p,width,color); } else { ; } + + if(showBridge && GetTrkBridge(trk) && (!GetTrkBridge(trk1))) { + Translate(&p0,p,a,trackGauge * 1.5); + Translate(&p1,p0,a - 45.0,trackGauge * 1.5); + DrawLine(d,p0,p1,width2,color); + Translate(&p0,p,a,-trackGauge * 1.5); + Translate(&p1,p0,a + 45.0,-trackGauge * 1.5); + DrawLine(d,p0,p1,width2,color); + } } EXPORT void DrawEndPt2( - drawCmd_p d, - track_p trk, - EPINX_T ep, - wDrawColor color ) + drawCmd_p d, + track_p trk, + EPINX_T ep, + wDrawColor color ) { track_p trk1; EPINX_T ep1; @@ -3272,8 +3157,9 @@ EXPORT void DrawEndPt2( trk1 = GetTrkEndTrk( trk, ep ); if (trk1) { ep1 = GetEndPtConnectedToMe( trk1, trk ); - if (ep1>=0) + if (ep1>=0) { DrawEndPt( d, trk1, ep1, color ); + } } } @@ -3284,46 +3170,53 @@ EXPORT void DrawTracks( drawCmd_p d, DIST_T scale, coOrd orig, coOrd size ) wIndex_t count = 0; coOrd lo, hi; BOOL_T doSelectRecount = FALSE; - + unsigned long time0 = wGetTimer(); + inDrawTracks = TRUE; InfoCount( 0 ); TRK_ITERATE( trk ) { if ( (d->options&DC_PRINT) != 0 && - wPrintQuit() ) { + wPrintQuit() ) { inDrawTracks = FALSE; return; } - if ( GetTrkSelected(trk) && - ( (!GetLayerVisible(GetTrkLayer(trk))) || - (drawTunnel==0 && !GetTrkVisible(trk)) ) ) { + if ( GetTrkSelected(trk) && + ( (!GetLayerVisible(GetTrkLayer(trk))) || + (drawTunnel==0 && !GetTrkVisible(trk)) ) ) { ClrTrkBits( trk, TB_SELECTED ); doSelectRecount = TRUE; } GetBoundingBox( trk, &hi, &lo ); if ( OFF_D( orig, size, lo, hi ) || - (d != &mapD && !GetLayerVisible( GetTrkLayer(trk) ) ) || - (d == &mapD && !GetLayerOnMap( GetTrkLayer(trk) ) ) ) + (d != &mapD && !GetLayerVisible( GetTrkLayer(trk) ) ) || + (d == &mapD && !GetLayerOnMap( GetTrkLayer(trk) ) ) ) { continue; + } DrawTrack( trk, d, wDrawColorBlack ); count++; - if (count%10 == 0) + if (count%10 == 0) { InfoCount( count ); + } } if (d == &mainD) { for (inx=1; inx<trackCmds_da.cnt; inx++) - if (trackCmds(inx)->redraw != NULL) + if (trackCmds(inx)->redraw != NULL) { trackCmds(inx)->redraw(); + } + LOG( log_timedrawtracks, 1, ( "DrawTracks time = %lu mS\n", + wGetTimer()-time0 ) ); } InfoCount( trackCount ); inDrawTracks = FALSE; - if ( doSelectRecount ) + if ( doSelectRecount ) { SelectRecount(); + } } -EXPORT void DrawSelectedTracks( drawCmd_p d ) +EXPORT void DrawSelectedTracks( drawCmd_p d, BOOL_T all ) { track_cp trk; wIndex_t count; @@ -3332,11 +3225,12 @@ EXPORT void DrawSelectedTracks( drawCmd_p d ) InfoCount( 0 ); TRK_ITERATE( trk ) { - if ( GetTrkSelected( trk ) ) { + if ( (all && GetLayerVisible(GetTrkLayer(trk))) || GetTrkSelected( trk ) ) { DrawTrack( trk, d, wDrawColorBlack ); count++; - if (count%10 == 0) + if (count%10 == 0) { InfoCount( count ); + } } } InfoCount( trackCount ); @@ -3354,24 +3248,29 @@ EXPORT void HilightElevations( BOOL_T hilight ) DIST_T radius; radius = 0.05*mainD.scale; - if ( radius < trackGauge/2.0 ) + if ( radius < trackGauge/2.0 ) { radius = trackGauge/2.0; + } TRK_ITERATE( trk ) { - for (ep=0;ep<GetTrkEndPtCnt(trk);ep++) { - GetTrkEndElev( trk, ep, &mode, &elev ); /* TRACKDEP */ + for (ep=0; ep<GetTrkEndPtCnt(trk); ep++) { + GetTrkEndElev( trk, ep, &mode, &elev ); if ((mode&ELEV_MASK)==ELEV_DEF || (mode&ELEV_MASK)==ELEV_IGNORE) { if ((trk1=GetTrkEndTrk(trk,ep)) != NULL && - GetTrkIndex(trk1) < GetTrkIndex(trk)) + GetTrkIndex(trk1) < GetTrkIndex(trk)) { continue; - if (drawTunnel == DRAW_TUNNEL_NONE && (!GetTrkVisible(trk)) && (trk1==NULL||!GetTrkVisible(trk1)) ) + } + if (drawTunnel == DRAW_TUNNEL_NONE && (!GetTrkVisible(trk)) && (trk1==NULL + ||!GetTrkVisible(trk1)) ) { continue; + } if ((!GetLayerVisible(GetTrkLayer(trk))) && - (trk1==NULL||!GetLayerVisible(GetTrkLayer(trk1)))) + (trk1==NULL||!GetLayerVisible(GetTrkLayer(trk1)))) { continue; + } pos = GetTrkEndPos(trk,ep); if ( !OFF_MAIND( pos, pos ) ) { DrawFillCircle( &tempD, pos, radius, - ((mode&ELEV_MASK)==ELEV_DEF?elevColorDefined:elevColorIgnore) ); + ((mode&ELEV_MASK)==ELEV_DEF?elevColorDefined:elevColorIgnore) ); } } } @@ -3382,7 +3281,7 @@ EXPORT void HilightElevations( BOOL_T hilight ) EXPORT void HilightSelectedEndPt( BOOL_T show, track_p trk, EPINX_T ep ) { coOrd pos; - if (!trk || (ep==-1)) return; + if (!trk || (ep==-1)) { return; } pos = GetTrkEndPos( trk, ep ); if ( show == TRUE ) { pos = GetTrkEndPos( trk, ep ); @@ -3404,15 +3303,17 @@ EXPORT void LabelLengths( drawCmd_p d, track_p trk, wDrawColor color ) char * msg; coOrd textsize; - if ((labelEnable&LABELENABLE_LENGTHS)==0) + if ((labelEnable&LABELENABLE_LENGTHS)==0) { return; + } fp = wStandardFont( F_HELV, FALSE, FALSE ); fs = (float)descriptionFontSize/d->scale; for (i=0; i<GetTrkEndPtCnt(trk); i++) { p0 = GetTrkEndPos( trk, i ); dist = GetFlexLength( trk, i, &p1 ); - if (dist < 0.1) + if (dist < 0.1) { continue; + } if (dist < 3.0) { p0.x = (p0.x+p1.x)/2.0; p0.y = (p0.y+p1.y)/2.0; @@ -3426,3 +3327,62 @@ EXPORT void LabelLengths( drawCmd_p d, track_p trk, wDrawColor color ) DrawString( d, p0, 0.0, msg, fp, fs*d->scale, color ); } } + +EXPORT void AddTrkDetails(drawCmd_p d,track_p trk,coOrd pos, DIST_T length, + wDrawColor color) +{ +#define DESC_LENGTH 6.0; + double division; + division = length/DESC_LENGTH; + division = ceil(division); + DIST_T dist = length/division, dist1; + traverseTrack_t tt; + tt.trk = trk; + tt.angle = GetTrkEndAngle(trk,0)+180.0; + tt.pos = GetTrkEndPos(trk,0); + + dynArr_t pos_array; + DYNARR_INIT( pos_angle_t, pos_array ); + + typedef struct { + coOrd pos; + ANGLE_T angle; + } pos_angle_t; + + DYNARR_SET(pos_angle_t,pos_array,(int)division+1); + DYNARR_N(pos_angle_t,pos_array,0).pos = GetTrkEndPos(trk,0); + DYNARR_N(pos_angle_t,pos_array,0).angle = NormalizeAngle(GetTrkEndAngle(trk, + 0)+180.0); + for (int i=1; i<pos_array.cnt; i++) { + tt.dist = dist; + dist1 = dist; + TraverseTrack(&tt,&dist1); + if (dist1 > 0 || tt.trk != trk + || IsClose(FindDistance(tt.pos,GetTrkEndPos(trk,1)))) { + DYNARR_N(pos_angle_t,pos_array,i).pos = GetTrkEndPos(trk,1); + DYNARR_N(pos_angle_t,pos_array,i).angle = GetTrkEndAngle(trk,1); + // Truncate pos_array + DYNARR_SET( pos_angle_t, pos_array, i+1 ); + break; + } + DYNARR_N(pos_angle_t,pos_array,i).pos = tt.pos; + DYNARR_N(pos_angle_t,pos_array,i).angle = tt.angle; + } + message[0]='\0'; + for (int i=0; i<pos_array.cnt; i++) { + if (i==pos_array.cnt-1) { + sprintf( &message[strlen(message)], _("[%0.2f,%0.2f] A%0.2f"), + PutDim(DYNARR_N(pos_angle_t,pos_array,i).pos.x),PutDim(DYNARR_N(pos_angle_t, + pos_array,i).pos.y),DYNARR_N(pos_angle_t,pos_array,i).angle ); + } else { + sprintf( &message[strlen(message)], _("[%0.2f,%0.2f] A%0.2f\n"), + PutDim(DYNARR_N(pos_angle_t,pos_array,i).pos.x),PutDim(DYNARR_N(pos_angle_t, + pos_array,i).pos.y),DYNARR_N(pos_angle_t,pos_array,i).angle); + } + } + wFont_p fp = wStandardFont( F_TIMES, FALSE, FALSE ); + DrawBoxedString(BOX_BOX,d,pos,message,fp,(wFontSize_t)descriptionFontSize,color, + 0.0); + DYNARR_FREE( pos_angle_t, pos_array ); +} + |