summaryrefslogtreecommitdiff
path: root/app/bin/elev.c
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2016-12-28 16:52:56 +0100
committerJörg Frings-Fürst <debian@jff-webhosting.net>2016-12-28 16:52:56 +0100
commit7b358424ebad9349421acd533c2fa1cbf6cf3e3e (patch)
tree686678532eefed525c242fd214d0cfb2914726c5 /app/bin/elev.c
Initial import of xtrkcad version 1:4.0.2-2
Diffstat (limited to 'app/bin/elev.c')
-rw-r--r--app/bin/elev.c1317
1 files changed, 1317 insertions, 0 deletions
diff --git a/app/bin/elev.c b/app/bin/elev.c
new file mode 100644
index 0000000..ec232a4
--- /dev/null
+++ b/app/bin/elev.c
@@ -0,0 +1,1317 @@
+/*
+ * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/bin/elev.c,v 1.1 2005-12-07 15:47:20 rc-flyer Exp $
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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.
+ */
+
+#include "track.h"
+#include "shrtpath.h"
+#include "ccurve.h"
+
+
+EXPORT long oldElevationEvaluation = 0;
+static int log_fillElev = 0;
+static int log_dumpElev = 0;
+static BOOL_T log_fillElev_initted;
+static int checkTrk = 0;
+static char * elevPrefix;
+
+static void SetTrkOnElevPath( track_p trk, int mode, DIST_T elev );
+
+typedef struct {
+ track_p trk;
+ EPINX_T ep;
+ DIST_T len;
+ } elist_t;
+static dynArr_t elist_da;
+#define elist(N) DYNARR_N( elist_t, elist_da, N )
+#define elistAppend( T, E, L ) \
+ { DYNARR_APPEND( elist_t, elist_da, 10 );\
+ elist(elist_da.cnt-1).trk = T; elist(elist_da.cnt-1).len = L; elist(elist_da.cnt-1).ep = E; }
+
+EPINX_T GetNextTrkOnPath( track_p trk, EPINX_T ep )
+{
+/* Get next track on Path:
+ 1 - there is only 1 connected (not counting ep)
+ 2 - there are >1 but only 1 on Path
+ 3 - one of them is PST:PSE or PET:PEE
+*/
+ EPINX_T ep2;
+ track_p trkN;
+ int epCnt = GetTrkEndPtCnt(trk);
+
+ for ( ep2=0; ep2<epCnt; ep2++) {
+ if ( ep2 == ep )
+ continue;
+ trkN = GetTrkEndTrk(trk,ep2);
+ if (trkN && (GetTrkBits(trkN)&TB_PROFILEPATH))
+ return ep2;
+ }
+ return -1;
+}
+
+
+EXPORT int FindDefinedElev(
+ track_p trk,
+ EPINX_T ep,
+ int dir,
+ BOOL_T onpath,
+ DIST_T * Relev,
+ DIST_T *Rdist )
+{
+ track_p trk0, trk1;
+ EPINX_T ep0, ep1, ep2;
+ DIST_T dist=0.0;
+
+ if (dir) {
+ trk1 = GetTrkEndTrk( trk, ep );
+ if (trk1 == NULL)
+ return FDE_END;
+ ep = GetEndPtConnectedToMe( trk1, trk );
+ trk = trk1;
+ }
+ trk0 = trk;
+ ep0 = ep;
+ while (1) {
+ for (ep2=0; ep2<GetTrkEndPtCnt(trk); ep2++) {
+ if ((trk!=trk0||ep2!=ep0)&&
+ EndPtIsDefinedElev(trk,ep2) ) {
+ dist += GetTrkLength( trk, ep, ep2 );
+ *Relev = GetTrkEndElevHeight(trk,ep2);
+ *Rdist = dist;
+ return FDE_DEF;
+ }
+ }
+ if (onpath) {
+ ep2 = GetNextTrkOnPath( trk, ep );
+ if ( ep2 >= 0 ) {
+ trk1 = GetTrkEndTrk( trk, ep2 );
+ ep1 = GetEndPtConnectedToMe( trk1, trk );
+ } else {
+ trk1 = NULL;
+ }
+ } else {
+ ep2 = GetNextTrk( trk, ep, &trk1, &ep1, GNTignoreIgnore );
+ }
+ if (ep2 < 0) {
+ if (trk1) {
+ /* more than one branch */
+ return FDE_UDF;
+ } else {
+ /* end of the line */
+ return FDE_END;
+ }
+ }
+ dist += GetTrkLength( trk, ep, ep2 );
+ trk = trk1;
+ ep = ep1;
+ if (trk == trk0)
+ return FDE_UDF;
+ }
+}
+
+
+BOOL_T ComputeElev(
+ track_p trk,
+ EPINX_T ep,
+ BOOL_T onpath,
+ DIST_T *elevR,
+ DIST_T *gradeR )
+{
+ DIST_T grade;
+ DIST_T elev0, elev1, dist0, dist1;
+ BOOL_T rc = FALSE;
+if (oldElevationEvaluation) {
+ int rc0, rc1;
+ if (GetTrkEndElevMode(trk,ep) == ELEV_DEF) {
+ if (elevR)
+ *elevR = GetTrkEndElevHeight(trk,ep);
+ if (gradeR)
+ *gradeR = 0.0;
+ return TRUE;
+ }
+ rc0 = FindDefinedElev( trk, ep, 0, onpath, &elev0, &dist0 );
+ rc1 = FindDefinedElev( trk, ep, 1, onpath, &elev1, &dist1 );
+ if ( rc0 == FDE_DEF && rc1 == FDE_DEF ) {
+ if (dist0+dist1 > 0.1)
+ grade = (elev1-elev0)/(dist0+dist1);
+ else
+ grade = 0.0;
+ elev0 += grade*dist0;
+ rc = TRUE;
+ } else if ( rc0 == FDE_DEF && rc1 == FDE_END ) {
+ grade = 0.0;
+ rc = TRUE;
+ } else if ( rc1 == FDE_DEF && rc0 == FDE_END ) {
+ grade = 0.0;
+ elev0 = elev1;
+ rc = TRUE;
+ } else if ( rc0 == FDE_END && rc1 == FDE_END ) {
+ grade = 0.0;
+ elev0 = 0.0;
+ rc = TRUE;
+ } else {
+ grade = 0.0;
+ elev0 = 0.0;
+ }
+} else {
+ track_p trk1;
+ EPINX_T ep1;
+ grade = -1;
+ rc = TRUE;
+ if ( EndPtIsDefinedElev(trk,ep) ) {
+ elev0 = GetTrkEndElevHeight(trk,ep);
+ rc = FALSE;
+ } else {
+ elev0 = GetElevation( trk );
+ dist0 = GetTrkLength( trk, ep, -1 );
+ trk1 = GetTrkEndTrk( trk, ep );
+ if (trk1!=NULL) {
+ ep1 = GetEndPtConnectedToMe(trk1,trk);
+ elev1 = GetElevation( trk1 );
+ dist1 = GetTrkLength( trk1, ep1, -1 );
+ if (dist0+dist1>0.1) {
+ grade = (elev1-elev0)/(dist0+dist1);
+ elev0 += grade*dist0;
+ } else {
+ elev0 = (elev0+elev1)/2.0;
+ rc = FALSE;
+ }
+ } else {
+ grade = 0.0;
+ }
+ }
+}
+ if ( elevR )
+ *elevR = elev0;
+ if ( gradeR )
+ *gradeR = grade;
+ return rc;
+}
+
+
+
+/*
+ * DYNAMIC ELEVATION COMPUTATION
+ *
+ * Step 1: Find DefElev's marking the border of the area of interest (or all of them)
+ */
+
+typedef struct {
+ track_p trk;
+ EPINX_T ep;
+ DIST_T elev;
+ } defelev_t;
+static dynArr_t defelev_da;
+#define defelev(N) DYNARR_N( defelev_t, defelev_da, N )
+
+static void FindDefElev( void )
+{
+ track_p trk;
+ EPINX_T ep, cnt;
+ defelev_t * dep;
+ long time0 = wGetTimer();
+
+ DYNARR_RESET( defelev_t, defelev_da );
+ trk = NULL;
+ while ( TrackIterate( &trk ) ) {
+ cnt = GetTrkEndPtCnt( trk );
+ for ( ep = 0; ep < cnt; ep++ ) {
+ if ( !EndPtIsDefinedElev( trk, ep ) )
+ continue;
+ DYNARR_APPEND( defelev_t, defelev_da, 10 );
+ dep = &defelev( defelev_da.cnt-1 );
+ dep->trk = trk;
+ dep->ep = ep;
+ dep->elev = GetTrkEndElevHeight(trk,ep);
+ }
+ }
+LOG( log_fillElev, 1, ( "%s: findDefElev [%d] (%ld)\n", elevPrefix, defelev_da.cnt, wGetTimer()-time0 ) )
+}
+
+
+static int foundNewDefElev;
+static void FindAttachedDefElev( track_p trk, BOOL_T remove )
+/* Find all DefElev's attached (directly or not) to this trk
+ * if 'remove' then clr ELEVPATH bit
+ * Working:
+ * elist_da
+ * Outputs:
+ * defelev_da - list of DefElev
+ * foundNewDefElev - found a DefElev not already on ElevPath
+ */
+{
+ int i1;
+ track_p trk1;
+ EPINX_T ep, cnt;
+ defelev_t * dep;
+
+ foundNewDefElev = FALSE;
+ DYNARR_RESET( elist_t, elist_da );
+ elistAppend( trk, 0, 0 );
+ SetTrkBits( trk, TB_PROCESSED );
+ if (remove)
+ ClrTrkBits( trk, TB_ELEVPATH );
+ for ( i1=0; i1<elist_da.cnt; i1++ ) {
+ trk = elist(i1).trk;
+ if (!IsTrack(trk))
+ continue;
+ cnt = GetTrkEndPtCnt(trk);
+ for ( ep=0; ep<cnt; ep++ ) {
+ if ( EndPtIsDefinedElev(trk,ep) ) {
+ DYNARR_APPEND( defelev_t, defelev_da, 10 );
+ dep = &defelev( defelev_da.cnt-1 );
+ dep->trk = trk;
+ dep->ep = ep;
+ dep->elev = GetTrkEndElevHeight(trk,ep);
+ if ( !(GetTrkBits(trk)&TB_ELEVPATH) ) {
+ foundNewDefElev = TRUE;
+ }
+ } else {
+ trk1 = GetTrkEndTrk(trk,ep);
+ if (trk1) {
+#ifdef LATER
+ if ( defElevOnIsland == FALSE && (GetTrkBits(trk1)&TB_ELEVPATH) ) {
+ /* so far this island is only connected to forks */
+ DYNARR_APPEND( fork_t, fork_da, 10 );
+ n = &fork(fork_da.cnt-1);
+ n->trk = trk1;
+ n->ep = ep;
+ n->dist = dist;
+ n->elev = dep->elev;
+ n->ntrk = dep->trk;
+ n->nep = dep->ep;
+ }
+#endif
+ if ( !(GetTrkBits(trk1)&TB_PROCESSED) ) {
+ elistAppend( trk1, 0, 0 );
+ SetTrkBits( trk1, TB_PROCESSED );
+ if (remove)
+ ClrTrkBits( trk1, TB_ELEVPATH );
+ }
+ }
+ }
+ }
+ }
+}
+
+static int FindObsoleteElevs( void )
+{
+ track_p trk;
+ int cnt;
+ long time0 = wGetTimer();
+
+ ClrAllTrkBits( TB_PROCESSED );
+ DYNARR_RESET( defelev_t, defelev_da );
+ cnt = 0;
+ trk = NULL;
+ while ( TrackIterate( &trk ) ) {
+ if ( (!(GetTrkBits(trk)&(TB_ELEVPATH|TB_PROCESSED))) && IsTrack(trk) ) {
+ cnt++;
+ FindAttachedDefElev( trk, TRUE );
+ }
+ }
+LOG( log_fillElev, 1, ( "%s: findObsoleteElevs [%d] (%ld)\n", elevPrefix, cnt, wGetTimer()-time0 ) )
+ return cnt;
+}
+
+
+
+
+/*
+ * DYNAMIC ELEVATION COMPUTATION
+ *
+ * Step 2: Find Forks on Shortest Path between the DefElev's found in Step 1
+ */
+
+typedef struct {
+ track_p trk;
+ EPINX_T ep;
+ EPINX_T ep2;
+ DIST_T dist;
+ DIST_T elev;
+ } fork_t;
+static dynArr_t fork_da;
+#define fork(N) DYNARR_N( fork_t, fork_da, N )
+
+static int FillElevShortestPathFunc(
+ SPTF_CMD cmd,
+ track_p trk,
+ EPINX_T ep,
+ EPINX_T ep2,
+ DIST_T dist,
+ void * data )
+{
+ defelev_t * dep = (defelev_t *)data;
+ track_p trk1;
+ EPINX_T ep1, cnt, epRc;
+ fork_t * n;
+
+ switch ( cmd ) {
+ case SPTC_MATCH:
+ /*if ( (GetTrkBits(trk)&TB_PROCESSED) )
+ epRc = 0;
+ else*/ if ( (dep->trk!=trk || dep->ep!=ep) && EndPtIsDefinedElev(trk,ep))
+ epRc = 1;
+ else
+ epRc = 0;
+ break;
+
+ case SPTC_MATCHANY:
+ cnt = GetTrkEndPtCnt( trk );
+ epRc = -1;
+ /*if ( (GetTrkBits(trk)&TB_PROCESSED) )
+ break;*/
+ for ( ep1=0; ep1<cnt; ep1++ ) {
+ if ( ep != ep1 && EndPtIsDefinedElev( trk, ep1 ) ) {
+ epRc = ep1;
+ break;
+ }
+ }
+ break;
+
+ case SPTC_ADD_TRK:
+ if (!(GetTrkBits(trk)&TB_PROCESSED)) {
+ SetTrkBits(trk, TB_PROCESSED);
+ if ( EndPtIsDefinedElev( trk, ep ) ) {
+if (log_shortPath<=0||logTable(log_shortPath).level<4) LOG( log_fillElev, 5, ( " ADD_TRK: T%d:%d D=%0.1f -> DefElev\n", GetTrkIndex(trk), ep, dist ) )
+LOG( log_shortPath, 4, ( "DefElev " ) )
+ } else if ( GetNextTrk( trk, ep, &trk1, &ep1, GNTignoreIgnore ) < 0 && trk1 != NULL ) {
+if (log_shortPath<=0||logTable(log_shortPath).level<4) LOG( log_fillElev, 4, ( " ADD_TRK: T%d:%d D=%0.3f E=%0.3f -> Fork[%d]\n", GetTrkIndex(trk), ep, dist, dep->elev, fork_da.cnt ) )
+LOG( log_shortPath, 4, ( "E:%0.3f Fork[%d] ", dep->elev, fork_da.cnt ) )
+ DYNARR_APPEND( fork_t, fork_da, 10 );
+ n = &fork(fork_da.cnt-1);
+ n->trk = trk;
+ n->ep = ep;
+ n->ep2 = ep2;
+ n->dist = dist;
+ n->elev = dep->elev;
+#ifdef LATER
+ n->ntrk = dep->trk;
+ n->nep = dep->ep;
+#endif
+ } else {
+LOG( log_shortPath, 4, ( "Normal " ) )
+ }
+ } else {
+LOG( log_shortPath, 4, ( "Processed " ) )
+ }
+ return 0;
+
+ case SPTC_TERMINATE:
+ epRc = 0;
+ break;
+
+ case SPTC_IGNNXTTRK:
+ if ( EndPtIsIgnoredElev(trk,ep2) ) {
+LOG( log_shortPath, 4, ( "2 Ignore " ) )
+ epRc = 1;
+ } else if ( (!EndPtIsDefinedElev(trk,ep)) && GetTrkEndTrk(trk,ep)==NULL ) {
+LOG( log_shortPath, 4, ( "1 Null && !DefElev " ) )
+ epRc = 1;
+ } else {
+ epRc = 0;
+ }
+ break;
+
+ case SPTC_VALID:
+ epRc = (GetTrkBits(trk)&TB_PROCESSED)==0?1:0;
+ break;
+
+ default:
+ epRc = 0;
+ break;
+ }
+ return epRc;
+}
+
+static void FindForks( void )
+/* Find the Shortest Path between all DevElev's (in defelev_da)
+ * and record all Forks (Turnouts with >2 connections) with distance to and elevation of the DefElev
+ * Inputs:
+ * defelev_da - list of DefElev to consider
+ * Outputs:
+ * fork_da - list of distances btw Forks and DefElev (plus other info)
+ */
+{
+ int i;
+ defelev_t * dep;
+ int rc;
+ long time0 = wGetTimer();
+
+ DYNARR_RESET( fork_t, fork_da );
+ for ( i=0; i<defelev_da.cnt; i++ ) {
+ dep = &defelev(i);
+
+ ClrAllTrkBits( TB_PROCESSED );
+LOG( log_fillElev, 3, ( " findForks from T%d:%d\n", GetTrkIndex(dep->trk), dep->ep ) )
+ rc = FindShortestPath( dep->trk, dep->ep, FALSE, FillElevShortestPathFunc, dep );
+ }
+ ClrAllTrkBits( TB_PROCESSED );
+LOG( log_fillElev, 1, ( "%s: findForks [%d] (%ld)\n", elevPrefix, fork_da.cnt, wGetTimer()-time0 ) )
+}
+
+
+
+
+/*
+ * DYNAMIC ELEVATION COMPUTATION
+ *
+ * Step 3: Compute the elevation of each Fork based on the weighted sum of the elevations
+ * of the DefElev's that it is connected to.
+ */
+
+typedef struct {
+ DIST_T elev;
+ DIST_T dist;
+ } elevdist_t;
+static dynArr_t elevdist_da;
+#define elevdist(N) DYNARR_N( elevdist_t, elevdist_da, N );
+
+static DIST_T ComputeWeightedElev( DIST_T totalDist )
+/* Compute weighted elevation
+ * Inputs:
+ * totalDist - total distance of all tracks between DevElev's
+ * elevdist_da - elev + dist to DefElev from current node
+ * Outputs:
+ * elev (returned)
+ */
+{
+ int i2;
+ DIST_T d2;
+ elevdist_t * w;
+ DIST_T e;
+
+ /* Compute inverse weighted Distance (d2) */
+ d2 = 0;
+ for ( i2=0; i2<elevdist_da.cnt; i2++ ) {
+ w = &elevdist(i2);
+ if (w->dist < 0.001) {
+ e = w->elev;
+LOG( log_fillElev, 3, ( " computeWeightedElev: close! D%0.3f E%0.3f\n", w->dist, e ) )
+ return e;
+ }
+ d2 += totalDist/w->dist;
+ }
+
+ /* Compute weighted elevation (e) */
+ e = 0;
+ for ( i2=0; i2<elevdist_da.cnt; i2++ ) {
+ w = &elevdist(i2);
+ e += ((totalDist/w->dist)/d2)*w->elev;
+ }
+
+ if (log_fillElev >= 4) {
+ for ( i2=0; i2<elevdist_da.cnt; i2++ ) {
+ w = &elevdist(i2);
+ lprintf( " E%0.3f D%0.3f\n", w->elev, w->dist );
+ }
+ }
+LOG( log_fillElev, 3, ( " computeWeightedElev: E%0.3f\n", e ) )
+ return e;
+}
+
+
+static int forkCnt;
+static void ComputeForkElev( void )
+/* Compute elevations of all Forks
+ * Inputs:
+ * fork_da - fork distance/elev data (overwritten)
+ * Outputs:
+ * fork_da - just .trk used for forks
+ * forkCnt - numer of forks found
+ */
+{
+ int i1, i2;
+ fork_t * n1, * n2, * n3;
+ track_p trk, trk1;
+ EPINX_T ep, cnt;
+ DIST_T d1, e;
+ elevdist_t * w;
+ BOOL_T singlePath;
+ long time0 = wGetTimer();
+
+ forkCnt = 0;
+ for (i1=0; i1<fork_da.cnt; i1++) {
+ n1 = &fork(i1);
+ if ((trk=n1->trk)) {
+ cnt = GetTrkEndPtCnt(n1->trk);
+ if (cnt<=0)
+ continue;
+
+ /* collect dist/elev to connected DefElev points */
+ d1 = 0;
+ DYNARR_RESET( elevdist_t, elevdist_da );
+ singlePath = TRUE;
+ for (i2=i1; i2<fork_da.cnt; i2++) {
+ n2 = &fork(i2);
+ if (trk == n2->trk) {
+ DYNARR_APPEND( elevdist_t, elevdist_da, 10 );
+ w = &elevdist(elevdist_da.cnt-1);
+ w->dist = n2->dist;
+ w->elev = n2->elev;
+ w->dist += GetTrkLength( n2->trk, n2->ep, -1 );
+ n2->trk = NULL;
+ d1 += w->dist;
+ if ( ! ( ( n1->ep == n2->ep && n1->ep2 == n2->ep2 ) ||
+ ( n1->ep == n2->ep2 && n1->ep2 == n2->ep ) ) )
+ singlePath = FALSE;
+ }
+ }
+
+ /* Also check my EPs */
+ for (ep=0; ep<cnt; ep++) {
+ if ( (trk1=GetTrkEndTrk(trk,ep)) )
+ SetTrkBits( trk1, TB_PROCESSED );
+ if (!EndPtIsDefinedElev(trk,ep))
+ continue;
+ for (i2=i1; i2<fork_da.cnt; i2++) {
+ n2 = &fork(i2);
+ if (trk==n2->trk && ep==n2->ep)
+ break;
+ }
+ if (i2 >= fork_da.cnt) {
+ DYNARR_APPEND( elevdist_t, elevdist_da, 10 );
+ w = &elevdist(elevdist_da.cnt-1);
+ w->elev = GetTrkEndElevHeight(trk,ep);
+ w->dist = GetTrkLength( trk, ep, -1 );
+ d1 += w->dist;
+ singlePath = FALSE;
+ }
+ }
+
+ n3 = &fork(forkCnt);
+ n3->trk = trk;
+ if ( singlePath == TRUE ) {
+ /* only 2 EP are connected to DefElevs, treat other EPs as ignored */
+ n3->ep = n1->ep;
+ n3->ep2 = n1->ep2;
+ } else {
+ e = ComputeWeightedElev( d1 );
+ SetTrkOnElevPath( trk, ELEV_FORK, e );
+ /* 3 or more EPs are to DefElevs */
+ n3->ep = -1;
+LOG( log_fillElev, 2, ( " 1 T%d E%0.3f\n", GetTrkIndex(trk), e ) )
+ }
+ forkCnt++;
+ }
+ }
+LOG( log_fillElev, 1, ( "%s: computeForkElev [%d] (%ld)\n", elevPrefix, forkCnt, wGetTimer()-time0 ) )
+}
+
+
+
+
+/*
+ * DYNAMIC ELEVATION COMPUTATION
+ *
+ * Step 4: Compute the elevation of tracks on the Shortest Path between Forks and DefElev's
+ */
+
+static void RedrawCompGradeElev( track_p trk, EPINX_T ep )
+{
+ int mode;
+ coOrd pos;
+ track_p trk1;
+ mode = GetTrkEndElevMode( trk, ep );
+ if ( mode == ELEV_COMP || mode == ELEV_GRADE ) {
+ pos = GetTrkEndPos( trk, ep );
+ if (!OFF_MAIND( pos, pos ) ) {
+ trk1 = GetTrkEndTrk( trk, ep );
+ if ( (trk1=GetTrkEndTrk(trk,ep)) && GetTrkIndex(trk1)<GetTrkIndex(trk) )
+{
+ ep = GetEndPtConnectedToMe( trk1, trk );
+ trk = trk1;
+ }
+ DrawEndElev( &mainD, trk, ep, wDrawColorWhite );
+ DrawEndElev( &mainD, trk, ep, wDrawColorBlack );
+ }
+ }
+}
+
+
+static void PropogateForkElev(
+ track_p trk1,
+ EPINX_T ep1,
+ DIST_T d1,
+ DIST_T e )
+/* Propogate elev from fork connection
+ * The track list starting from trk1:ep1 ends at a DefElev or a Fork
+ * Inputs:
+ * Working:
+ * elist_da
+ * Outputs:
+ * Sets trk elev
+ */
+{
+ DIST_T d2;
+ DIST_T e1;
+ EPINX_T ep2, epN, cnt2;
+ track_p trkN;
+ fork_t * n1;
+ int i2, i3;
+
+ DYNARR_RESET( elist_t, elist_da );
+ while (trk1) {
+ if ( GetTrkIndex(trk1) == checkTrk )
+ printf( "found btw forks\n" );
+ if ( GetTrkOnElevPath( trk1, &e1 ) ) {
+ d1 += GetTrkLength( trk1, ep1, -1 );
+ goto nextStep;
+ }
+ cnt2 = GetTrkEndPtCnt(trk1);
+ for ( ep2=0; ep2<cnt2; ep2++ ) {
+ if ( ep2!=ep1 && EndPtIsDefinedElev(trk1,ep2) ) {
+ e1 = GetTrkEndElevHeight( trk1, ep2 );
+ d2 = GetTrkLength( trk1, ep1, ep2 )/2.0;
+ d1 += d2;
+ elistAppend( trk1, ep1, d1 );
+ d1 += d2;
+ goto nextStep;
+ }
+ }
+ ep2 = GetNextTrk( trk1, ep1, &trkN, &epN, GNTignoreIgnore );
+ if ( ep2<0 ) {
+ /* is this really a fork? */
+ for ( i2=0; i2<forkCnt; i2++ ) {
+ n1 = &fork(i2);
+ if ( trk1 == n1->trk && n1->ep >= 0 ) {
+ /* no: make sure we are on the path */
+ if ( n1->ep == ep1 )
+ ep2 = n1->ep2;
+ else if ( n1->ep2 == ep1 )
+ ep2 = n1->ep;
+ else
+ return;
+ trkN = GetTrkEndTrk(trk1,ep2);
+ epN = GetEndPtConnectedToMe( trkN, trk1 );
+ break;
+ }
+ }
+ if ( i2 >= forkCnt )
+ return;
+ }
+ d2 = GetTrkLength( trk1, ep1, ep2 )/2.0;
+ d1 += d2;
+ elistAppend( trk1, ep1, d1 );
+ d1 += d2;
+ trk1 = trkN;
+ ep1 = epN;
+ }
+nextStep:
+ ASSERT(d1>0.0);
+ e1 = (e1-e)/d1;
+ trk1 = NULL;
+ i3 = elist_da.cnt;
+ for (i2=0; i2<elist_da.cnt; i2++) {
+ trk1 = elist(i2).trk;
+ ep1 = elist(i2).ep;
+ if ( GetTrkOnElevPath( trk1, &e1 ) ) {
+ i3=i2;
+ break;
+ }
+ d2 = elist(i2).len;
+ SetTrkOnElevPath( trk1, ELEV_BRANCH, e+e1*d2 );
+LOG( log_fillElev, 2, ( " 2 T%d E%0.3f\n", GetTrkIndex(trk1), e+e1*d2 ) )
+ }
+ for (i2=0; i2<i3; i2++) {
+ trk1 = elist(i2).trk;
+ ep1 = elist(i2).ep;
+ RedrawCompGradeElev( trk1, ep1 );
+ }
+}
+
+static void PropogateForkElevs( void )
+/* For all Forks, For all connections not already processed or not on ElevPath do
+ * propogate elev along connection
+ * Inputs:
+ * fork_da - list of forks
+ * forkCnt - number of forks
+ * Working:
+ * elist_da (by subrtn)
+ * Outputs:
+ * Sets trk elev (by subrtn)
+ */
+{
+ int i1;
+ fork_t * n1;
+ track_p trk, trk1;
+ EPINX_T ep, cnt, ep1;
+ DIST_T d1, e;
+ long time0 = wGetTimer();
+
+ /* propogate elevs between forks */
+ for ( i1=0; i1<forkCnt; i1++ ) {
+ n1 = &fork(i1);
+ if ( n1->ep >= 0 )
+ continue;
+ trk = n1->trk;
+ GetTrkOnElevPath( trk, &e );
+ cnt = GetTrkEndPtCnt(trk);
+ for (ep=0; ep<cnt; ep++) {
+ trk1 = GetTrkEndTrk(trk,ep);
+ if ( trk1 && (GetTrkBits(trk1)&TB_PROCESSED) && !GetTrkOnElevPath(trk1,NULL) ) {
+ /* should find a fork with a computed elev */
+ ep1 = GetEndPtConnectedToMe( trk1, trk );
+ if ( EndPtIsDefinedElev(trk,ep) ) {
+ PropogateForkElev( trk1, ep1, 0, GetTrkEndElevHeight(trk,ep) );
+ } else {
+ d1 = GetTrkLength(trk,ep,-1);
+ PropogateForkElev( trk1, ep1, d1, e );
+ }
+ }
+ }
+ }
+LOG( log_fillElev, 1, ( "%s: propogateForkElev (%ld)\n", elevPrefix, wGetTimer()-time0 ) )
+}
+
+static void PropogateDefElevs( void )
+/* Propogate Elev from DefElev (if not handled already)
+ * Inputs:
+ * develev_da - list of DefElev
+ * Outputs:
+ * Set trk elev
+ */
+{
+ int i1;
+ defelev_t * dep;
+ DIST_T e;
+ long time0 = wGetTimer();
+
+ /* propogate elevs between DefElev pts (not handled by propogateForkElevs) */
+ for ( i1=0; i1<defelev_da.cnt; i1++ ) {
+ dep = &defelev(i1);
+ if (GetTrkOnElevPath( dep->trk, &e ))
+ /* propogateForkElevs beat us to it */
+ continue;
+ e = GetTrkEndElevHeight( dep->trk, dep->ep );
+ PropogateForkElev( dep->trk, dep->ep, 0, e );
+ }
+LOG( log_fillElev, 1, ( "%s: propogateDefElevs [%d] (%ld)\n", elevPrefix, defelev_da.cnt, wGetTimer()-time0 ) )
+}
+
+
+
+
+/*
+ * DYNAMIC ELEVATION COMPUTATION
+ *
+ * Step 5: Remaining tracks form either Islands connected to zero or more DefElev, Forks
+ * or Branches (Pivots). The elevation of these tracks is determined by the distance to
+ * the Pivots. Tracks which are not connected to Pivots are labeled 'Alone' and have no
+ * elevation.
+ */
+
+typedef struct {
+ track_p trk;
+ coOrd pos;
+ DIST_T elev;
+ } pivot_t;
+static dynArr_t pivot_da;
+#define pivot(N) DYNARR_N(pivot_t, pivot_da, N)
+
+static void SurveyIsland(
+ track_p trk,
+ BOOL_T stopAtElevPath )
+/* Find the tracks in this island and the pivots of this island
+ * Outputs:
+ * elist_da - tracks in the island
+ * pivot_da - pivots connecting island to tracks with some elev
+ */
+{
+ int i1;
+ track_p trk1;
+ EPINX_T ep, cnt;
+ pivot_t * pp;
+ coOrd hi, lo;
+ DIST_T elev;
+
+ DYNARR_RESET( elist_t, elist_da );
+ DYNARR_RESET( pivot_t, pivot_da );
+ ClrAllTrkBits( TB_PROCESSED );
+ elistAppend( trk, 0, 0 );
+ SetTrkBits( trk, TB_PROCESSED );
+ for ( i1=0; i1 < elist_da.cnt; i1++ ) {
+ trk = elist(i1).trk;
+ if ( GetTrkIndex(trk) == checkTrk )
+ printf( "found in island\n" );
+ cnt = GetTrkEndPtCnt(trk);
+ for ( ep=0; ep<cnt; ep++ ) {
+ trk1 = GetTrkEndTrk( trk, ep );
+ if ( EndPtIsDefinedElev(trk,ep)) {
+ DYNARR_APPEND( pivot_t, pivot_da, 10 );
+ pp = &pivot(pivot_da.cnt-1);
+ pp->trk = trk;
+ pp->pos = GetTrkEndPos(trk,ep);
+ pp->elev = GetTrkEndElevHeight(trk,ep);
+ } else if ( stopAtElevPath && trk1 && GetTrkOnElevPath(trk1, &elev) ) {
+ DYNARR_APPEND( pivot_t, pivot_da, 10 );
+ pp = &pivot(pivot_da.cnt-1);
+ pp->trk = trk1;
+ GetBoundingBox( trk1, &hi, &lo );
+ pp->pos.x = (hi.x+lo.x)/2.0;
+ pp->pos.y = (hi.y+lo.y)/2.0;
+ pp->elev = elev;
+ } else if ( trk1 && !(GetTrkBits(trk1)&TB_PROCESSED) ) {
+ SetTrkBits( trk1, TB_PROCESSED );
+ elistAppend( trk1, 0, 0 );
+ }
+ }
+ }
+ ClrAllTrkBits( TB_PROCESSED );
+}
+
+static void ComputeIslandElev(
+ track_p trk )
+/* Compute elev of tracks connected to 'trk'
+ * An island is the set of tracks bounded by a DefElev EP or a track already on ElevPath
+ * Inputs:
+ * Working:
+ * elist_da
+ * Outputs:
+ * pivot_da - list of tracks on boundary of Island
+ */
+{
+ int i1, i2;
+ coOrd hi, lo, pos;
+ pivot_t * pp;
+ DIST_T elev;
+ DIST_T totalDist;
+ elevdist_t * w;
+ int mode;
+ EPINX_T ep, epCnt;
+
+ SurveyIsland( trk, TRUE );
+
+ for ( i1=0; i1 < elist_da.cnt; i1++ ) {
+ trk = elist(i1).trk;
+ if ( !IsTrack(trk) )
+ continue;
+ mode = ELEV_ISLAND;
+ if (pivot_da.cnt == 0) {
+ elev = 0;
+ mode = ELEV_ALONE;
+ } else if (pivot_da.cnt == 1) {
+ elev = pivot(0).elev;
+ } else {
+ if ( !GetCurveMiddle( trk, &pos ) ) {
+ GetBoundingBox( trk, &hi, &lo );
+ pos.x = (hi.x+lo.x)/2.0;
+ pos.y = (hi.y+lo.y)/2.0;
+ }
+ DYNARR_RESET( elevdist_t, elevdist_da );
+ totalDist = 0;
+ for ( i2=0; i2<pivot_da.cnt; i2++ ) {
+ pp = &pivot(i2);
+ DYNARR_APPEND( elevdist_t, elevdist_da, 10 );
+ w = &elevdist(elevdist_da.cnt-1);
+ w->elev = pp->elev;
+ w->dist = FindDistance( pos, pp->pos );
+ totalDist += w->dist;
+ }
+ elev = ComputeWeightedElev( totalDist );
+ }
+ SetTrkOnElevPath( trk, mode, elev );
+LOG( log_fillElev, 1, ( " 3 T%d E%0.3f\n", GetTrkIndex(trk), elev ) )
+ }
+
+ for ( i1=0; i1<elist_da.cnt; i1++ ) {
+ trk = elist(i1).trk;
+ epCnt = GetTrkEndPtCnt( trk );
+ for ( ep=0; ep<epCnt; ep++ ) {
+ mode = GetTrkEndElevMode( trk, ep );
+ if ( (mode == ELEV_GRADE || mode == ELEV_COMP) ) {
+ RedrawCompGradeElev( trk, ep );
+ }
+ }
+ }
+}
+
+
+static void FindIslandElevs( void )
+{
+ track_p trk;
+ DIST_T elev;
+ int islandCnt;
+ long time0 = wGetTimer();
+
+ trk = NULL;
+ islandCnt = 0;
+ while ( TrackIterate( &trk ) ) {
+ if ( !GetTrkOnElevPath( trk, &elev ) ) {
+ if (IsTrack(trk)) {
+ ComputeIslandElev( trk );
+ islandCnt++;
+ }
+ }
+ }
+LOG( log_fillElev, 1, ( "%s: findIslandElevs [%d] (%ld)\n", elevPrefix, islandCnt, wGetTimer()-time0 ) )
+}
+
+/*
+ * DYNAMIC ELEVATION COMPUTATION
+ *
+ * Drivers
+ *
+ */
+
+EXPORT void RecomputeElevations( void )
+{
+ long time0 = wGetTimer();
+ elevPrefix = "RECELV";
+ if ( !log_fillElev_initted ) { log_fillElev = LogFindIndex( "fillElev" ); log_dumpElev = LogFindIndex( "dumpElev" ); log_fillElev_initted = TRUE; }
+ ClearElevPath();
+ FindDefElev();
+ FindForks();
+ ComputeForkElev();
+ PropogateForkElevs();
+ PropogateDefElevs();
+ FindIslandElevs();
+ MainRedraw();
+LOG( log_fillElev, 1, ( "%s: Total (%ld)\n", elevPrefix, wGetTimer()-time0 ) )
+ if ( log_dumpElev > 0 ) {
+ track_p trk;
+ DIST_T elev;
+ for ( trk=NULL; TrackIterate( &trk ); ) {
+ printf( "T%4.4d = ", GetTrkIndex(trk) );
+ if ( GetTrkOnElevPath( trk, &elev ) )
+ printf( "%d:%0.2f\n", GetTrkElevMode(trk), elev );
+ else
+ printf( "noelev\n" );
+#ifdef LATER
+ EPINX_T ep;
+ int mode;
+ for ( ep=0; ep<GetTrkEndPtCnt(trk); ep++ ) {
+ mode = GetTrkEndElevMode( trk, ep );
+ ComputeElev( trk, ep, FALSE, &elev, NULL );
+ printf( "T%4.4d[%2.2d] = %s:%0.3f\n",
+ GetTrkIndex(trk), ep,
+ mode==ELEV_NONE?"None":mode==ELEV_DEF?"Def":mode==ELEV_COMP?"Comp":
+ mode==ELEV_GRADE?"Grade":mode==ELEV_IGNORE?"Ignore":mode==ELEV_STATION?"Station":"???",
+ elev );
+ }
+#endif
+ }
+ }
+}
+
+
+static BOOL_T needElevUpdate = FALSE;
+EXPORT void UpdateAllElevations( void )
+{
+ int work;
+ long time0 = wGetTimer();
+
+ elevPrefix = "UPDELV";
+ if ( !log_fillElev_initted ) { log_fillElev = LogFindIndex( "fillElev" ); log_dumpElev = LogFindIndex( "dumpElev" ); log_fillElev_initted = TRUE; }
+ if (!needElevUpdate)
+ return;
+ work = FindObsoleteElevs();
+ if (!work)
+ return;
+ FindForks();
+ ComputeForkElev();
+ PropogateForkElevs();
+ PropogateDefElevs();
+ FindIslandElevs();
+ needElevUpdate = FALSE;
+LOG( log_fillElev, 1, ( "%s: Total (%ld)\n", elevPrefix, wGetTimer()-time0 ) )
+}
+
+
+EXPORT DIST_T GetElevation( track_p trk )
+{
+ DIST_T elev;
+
+ if ( !IsTrack(trk) ) {
+ return 0;
+ }
+ if ( GetTrkOnElevPath(trk,&elev) ) {
+ return elev;
+ }
+
+ elevPrefix = "GETELV";
+ if ( !log_fillElev_initted ) { log_fillElev = LogFindIndex( "fillElev" ); log_dumpElev = LogFindIndex( "dumpElev" ); log_fillElev_initted = TRUE; }
+ ClrAllTrkBits( TB_PROCESSED );
+ DYNARR_RESET( defelev_t, defelev_da );
+ FindAttachedDefElev( trk, TRUE );
+ /* at least one DevElev to be processed */
+ FindForks();
+ ComputeForkElev();
+ PropogateForkElevs();
+ PropogateDefElevs();
+ if ( GetTrkOnElevPath(trk,&elev) )
+ return elev;
+
+ ComputeIslandElev( trk );
+
+ if ( GetTrkOnElevPath(trk,&elev) )
+ return elev;
+
+ printf( "GetElevation(T%d) failed\n", GetTrkIndex(trk) );
+ return 0;
+}
+
+
+/*
+ * DYNAMIC ELEVATION COMPUTATION
+ *
+ * Utilities
+ *
+ */
+
+
+EXPORT void ClrTrkElev( track_p trk )
+{
+ needElevUpdate = TRUE;
+ DrawTrackElev( trk, &mainD, FALSE );
+ ClrTrkBits( trk, TB_ELEVPATH );
+}
+
+
+static void PropogateElevMode( track_p trk, DIST_T elev, int mode )
+{
+ int i1;
+ SurveyIsland( trk, FALSE );
+ for ( i1=0; i1<elist_da.cnt; i1++ )
+ SetTrkOnElevPath( elist(i1).trk, mode, elev );
+}
+
+
+static BOOL_T CheckForElevAlone( track_p trk )
+{
+ int i1;
+ SurveyIsland( trk, FALSE );
+ if ( pivot_da.cnt!=0 )
+ return FALSE;
+ for ( i1=0; i1<elist_da.cnt; i1++ )
+ SetTrkOnElevPath( elist(i1).trk, ELEV_ALONE, 0.0 );
+ return TRUE;
+}
+
+
+EXPORT void SetTrkElevModes( BOOL_T connect, track_p trk0, EPINX_T ep0, track_p trk1, EPINX_T ep1 )
+{
+ int mode0, mode1;
+ DIST_T elev, diff, elev0, elev1;
+ char * station;
+ BOOL_T update = TRUE;
+
+ mode0 = GetTrkElevMode( trk0 );
+ mode1 = GetTrkElevMode( trk1 );
+ if ( mode0 == ELEV_ALONE && mode1 == ELEV_ALONE ) {
+ update = FALSE;;
+ } else if ( connect ) {
+ if ( mode0 == ELEV_ALONE ) {
+ ComputeElev( trk1, ep1, FALSE, &elev, NULL );
+ PropogateElevMode( trk0, elev, ELEV_ISLAND );
+ update = FALSE;
+ } else if ( mode1 == ELEV_ALONE ) {
+ ComputeElev( trk0, ep0, FALSE, &elev, NULL );
+ PropogateElevMode( trk1, elev, ELEV_ISLAND );
+ update = FALSE;
+ }
+ } else {
+ if ( mode0 == ELEV_ISLAND ) {
+ if (CheckForElevAlone( trk0 ))
+ update = FALSE;
+ } else if ( mode1 == ELEV_ISLAND ) {
+ if (CheckForElevAlone( trk1 ))
+ update = FALSE;
+ }
+ }
+
+ if ( connect ) {
+ mode0 = GetTrkEndElevMode( trk0, ep0 );
+ mode1 = GetTrkEndElevMode( trk1, ep1 );
+ elev = 0.0;
+ station = NULL;
+ if (mode0 == ELEV_DEF && mode1 == ELEV_DEF) {
+ mode0 = GetTrkEndElevUnmaskedMode( trk0, ep0 ) | GetTrkEndElevUnmaskedMode( trk1, ep1 );
+ elev0 = GetTrkEndElevHeight( trk0, ep0 );
+ elev1 = GetTrkEndElevHeight( trk1, ep1 );
+ elev = (elev0+elev1)/2.0;
+ diff = fabs( elev0-elev1 );
+ if (diff>0.1)
+ ErrorMessage( MSG_JOIN_DIFFER_ELEV, PutDim(diff) );
+ } else if (mode0 == ELEV_DEF) {
+ mode0 = GetTrkEndElevUnmaskedMode( trk0, ep0 );
+ elev = GetTrkEndElevHeight( trk0, ep0 );
+ } else if (mode1 == ELEV_DEF) {
+ mode1 = GetTrkEndElevUnmaskedMode( trk1, ep1 );
+ elev = GetTrkEndElevHeight( trk1, ep1 );
+ } else if (mode0 == ELEV_STATION) {
+ station = GetTrkEndElevStation( trk0, ep0 );
+ } else if (mode1 == ELEV_STATION) {
+ station = GetTrkEndElevStation( trk1, ep1 );
+ mode0 = mode1;
+ } else if (mode0 == ELEV_GRADE) {
+ ;
+ } else if (mode1 == ELEV_GRADE) {
+ mode0 = mode1;
+ } else if (mode0 == ELEV_COMP) {
+ ;
+ } else if (mode1 == ELEV_COMP) {
+ mode0 = mode1;
+ } else {
+ ;
+ }
+ SetTrkEndElev( trk0, ep0, mode0, elev, station );
+ SetTrkEndElev( trk1, ep1, mode0, elev, station );
+ }
+
+ if (update) {
+ needElevUpdate = TRUE;
+ ClrTrkElev( trk0 );
+ ClrTrkElev( trk1 );
+ }
+}
+
+
+EXPORT void UpdateTrkEndElev(
+ track_p trk,
+ EPINX_T ep,
+ int newMode,
+ DIST_T newElev,
+ char * newStation )
+{
+ int oldMode;
+ DIST_T oldElev;
+ char * oldStation;
+ BOOL_T changed = TRUE;
+ track_p trk1;
+ EPINX_T ep1;
+
+ oldMode = GetTrkEndElevUnmaskedMode( trk, ep );
+ if ( (oldMode&ELEV_MASK) == (newMode&ELEV_MASK) ) {
+ switch ( (oldMode&ELEV_MASK) ) {
+ case ELEV_DEF:
+ oldElev = GetTrkEndElevHeight( trk, ep );
+ if ( oldElev == newElev ) {
+ if ( oldMode == newMode )
+ return;
+ changed = FALSE;
+ }
+ break;
+ case ELEV_STATION:
+ oldStation = GetTrkEndElevStation( trk, ep );
+ if ( strcmp( oldStation, newStation ) == 0 ) {
+ return;
+ }
+ break;
+ default:
+ return;
+ }
+ } else {
+ changed = TRUE;
+ if ( (newMode&ELEV_MASK)==ELEV_DEF || (oldMode&ELEV_MASK)==ELEV_DEF ||
+ (newMode&ELEV_MASK)==ELEV_IGNORE || (oldMode&ELEV_MASK)==ELEV_IGNORE )
+ changed = TRUE;
+ }
+ UndoModify( trk );
+ if ( (trk1 = GetTrkEndTrk( trk, ep )) ) {
+ UndoModify( trk1 );
+ }
+ DrawEndPt2( &mainD, trk, ep, drawColorWhite );
+ SetTrkEndElev( trk, ep, newMode, newElev, newStation );
+ DrawEndPt2( &mainD, trk, ep, drawColorBlack );
+ if ( changed ) {
+ ClrTrkElev( trk );
+ if ( trk1 ) {
+ ep1 = GetEndPtConnectedToMe( trk1, trk );
+ ClrTrkElev( trk1 );
+ }
+ UpdateAllElevations();
+ }
+}
+
+static void SetTrkOnElevPath( track_p trk, int mode, DIST_T elev )
+{
+ BOOL_T redraw = FALSE;
+ int oldMode = GetTrkElevMode( trk );
+ DIST_T oldElev;
+ coOrd hi, lo;
+
+ if ( !GetTrkOnElevPath( trk, &oldElev ) )
+ oldElev = 0.0;
+ GetBoundingBox( trk, &hi, &lo );
+ if ((labelEnable&LABELENABLE_TRACK_ELEV) &&
+ labelScale >= mainD.scale &&
+ (! OFF_MAIND( lo, hi ) ) &&
+ (GetTrkVisible(trk) || drawTunnel!=0/*DRAW_TUNNEL_NONE*/) &&
+ GetLayerVisible(GetTrkLayer(trk)) )
+ redraw = TRUE;
+
+ if ( (GetTrkBits(trk)&TB_ELEVPATH) && (oldElev == elev && oldMode == mode) )
+ return;
+ if ( redraw && (GetTrkBits(trk)&TB_ELEVPATH))
+ DrawTrackElev( trk, &mainD, FALSE );
+ SetTrkElev( trk, mode, elev );
+ if ( redraw )
+ DrawTrackElev( trk, &mainD, TRUE );
+}
+
+
+EXPORT void DrawTrackElev( track_cp trk, drawCmd_p d, BOOL_T drawIt )
+{
+ coOrd pos;
+ wFont_p fp;
+ wDrawColor color=(wDrawColor)0;
+ DIST_T elev;
+ coOrd lo, hi;
+
+ if ( (!IsTrack(trk)) ||
+ (!(labelEnable&LABELENABLE_TRACK_ELEV)) ||
+ (d == &mapD) ||
+ (labelScale < d->scale) ||
+ (!GetTrkOnElevPath( trk, &elev )) ||
+ ((GetTrkBits(trk)&TB_ELEVPATH) == 0) ||
+ (d->funcs->options & wDrawOptTemp) != 0 ||
+ (d->options & DC_QUICK) != 0 )
+ return;
+
+ if ( !GetCurveMiddle( trk, &pos ) ) {
+ GetBoundingBox( trk, &hi, &lo );
+ pos.x = (hi.x+lo.x)/2.0;
+ pos.y = (hi.y+lo.y)/2.0;
+ }
+ if ( d==&mainD && OFF_MAIND( pos, pos ) )
+ return;
+
+ switch ( GetTrkElevMode(trk) ) {
+ case ELEV_FORK:
+ color = drawColorBlue;
+ break;
+ case ELEV_BRANCH:
+ color = drawColorPurple;
+ break;
+ case ELEV_ISLAND:
+ color = drawColorGold;
+ break;
+ case ELEV_ALONE:
+ return;
+ }
+ if ( !drawIt )
+ color = wDrawColorWhite;
+ sprintf( message, "%s", FormatDistance(elev));
+ fp = wStandardFont( F_HELV, FALSE, FALSE );
+ DrawBoxedString( BOX_INVERT, d, pos, message, fp, (wFontSize_t)descriptionFontSize, color, 0 );
+}
+
+