From 7b358424ebad9349421acd533c2fa1cbf6cf3e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Wed, 28 Dec 2016 16:52:56 +0100 Subject: Initial import of xtrkcad version 1:4.0.2-2 --- app/bin/elev.c | 1317 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1317 insertions(+) create mode 100644 app/bin/elev.c (limited to 'app/bin/elev.c') 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= 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; i1trk = 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 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; itrk), 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; i2dist < 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; i2dist)/d2)*w->elev; + } + + if (log_fillElev >= 4) { + for ( i2=0; i2elev, 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; i1trk)) { + 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; i2trk) { + 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; eptrk && 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)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; i2ep >= 0 ) + continue; + trk = n1->trk; + GetTrkOnElevPath( trk, &e ); + cnt = GetTrkEndPtCnt(trk); + for (ep=0; eptrk, &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; eptrk = 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; i2elev = 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 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; ep0.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 ); +} + + -- cgit v1.2.3