diff options
Diffstat (limited to 'app/bin/cturnout.c')
-rw-r--r-- | app/bin/cturnout.c | 4890 |
1 files changed, 3397 insertions, 1493 deletions
diff --git a/app/bin/cturnout.c b/app/bin/cturnout.c index 150f381..02eadef 100644 --- a/app/bin/cturnout.c +++ b/app/bin/cturnout.c @@ -1,30 +1,26 @@ /** \file cturnout.c - * T_TURNOUT + * Turnout object handling and drawing */ -/* 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 <ctype.h> -#include <math.h> -#include <stdint.h> -#include <string.h> - + /* 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 "common.h" #include "ccurve.h" #include "tbezier.h" #include "tcornu.h" @@ -34,14 +30,13 @@ #include "cundo.h" #include "custom.h" #include "fileio.h" -#include "i18n.h" #include "layout.h" -#include "messages.h" #include "param.h" +#include "cselect.h" #include "include/paramfile.h" #include "track.h" #include "trackx.h" -#include "utility.h" +#include "common-ui.h" EXPORT TRKTYP_T T_TURNOUT = -1; @@ -51,13 +46,17 @@ EXPORT TRKTYP_T T_TURNOUT = -1; EXPORT dynArr_t turnoutInfo_da; -EXPORT turnoutInfo_t * curTurnout = NULL; +EXPORT turnoutInfo_t* curTurnout = NULL; EXPORT long curTurnoutEp = 0; static int curTurnoutInx = -1; +/** @logcmd @showrefby turnout=n cturnout.c */ static int log_turnout = 0; +/** @logcmd @showrefby traverseTurnout=n cturnout.c */ static int log_traverseTurnout = 0; +/** @logcmd @showrefby suppresscheckpaths=n cturnout.c */ static int log_suppressCheckPaths = 0; +/** @logcmd @showrefby splitturnout=n cturnout.c */ static int log_splitturnout = 0; static wMenu_p turnoutPopupM; @@ -75,33 +74,99 @@ static drawCmd_t turnoutD = { static wIndex_t turnoutHotBarCmdInx; static wIndex_t turnoutInx; static long hideTurnoutWindow; -static void RedrawTurnout(void); -static void SelTurnoutEndPt( wIndex_t, coOrd ); -static void HilightEndPt( void ); +static void RedrawTurnout( wDraw_p d, void * context, wWinPix_t x, wWinPix_t y ); +static void SelTurnoutEndPt(wIndex_t, coOrd); +static void HilightEndPt(void); -static wPos_t turnoutListWidths[] = { 80, 80, 220 }; -static const char * turnoutListTitles[] = { N_("Manufacturer"), N_("Part No"), N_("Description") }; +static wWinPix_t turnoutListWidths[] = { 80, 80, 220 }; +static const char* turnoutListTitles[] = { N_("Manufacturer"), N_("Part No"), N_("Description") }; static paramListData_t listData = { 13, 400, 3, turnoutListWidths, turnoutListTitles }; -static const char * hideLabels[] = { N_("Hide"), NULL }; -static paramDrawData_t turnoutDrawData = { 490, 200, (wDrawRedrawCallBack_p)RedrawTurnout, SelTurnoutEndPt, &turnoutD }; +static const char* hideLabels[] = { N_("Hide"), NULL }; +static paramDrawData_t turnoutDrawData = { 490, 200, RedrawTurnout, SelTurnoutEndPt, &turnoutD }; static paramData_t turnoutPLs[] = { #define I_LIST (0) #define turnoutListL ((wList_p)turnoutPLs[I_LIST].control) - { PD_LIST, &turnoutInx, "list", PDO_NOPREF|PDO_DLGRESIZEW, &listData, NULL, BL_DUP }, + { PD_LIST, &turnoutInx, "list", PDO_NOPREF | PDO_DLGRESIZEW, &listData, NULL, BL_DUP }, #define I_DRAW (1) #define turnoutDrawD ((wDraw_p)turnoutPLs[I_DRAW].control) - { PD_DRAW, NULL, "canvas", PDO_NOPSHUPD|PDO_DLGUNDERCMDBUTT|PDO_DLGRESIZE, &turnoutDrawData, NULL, 0 }, + { PD_DRAW, NULL, "canvas", PDO_NOPSHUPD | PDO_DLGUNDERCMDBUTT | PDO_DLGRESIZE, &turnoutDrawData, NULL, 0 }, #define I_NEW (2) #define turnoutNewM ((wMenu_p)turnoutPLs[I_NEW].control) { PD_MENU, NULL, "new", PDO_DLGCMDBUTTON, NULL, N_("New") }, #define I_HIDE (3) #define turnoutHideT ((wChoice_p)turnoutPLs[I_HIDE].control) - { PD_TOGGLE, &hideTurnoutWindow, "hide", PDO_DLGCMDBUTTON, /*CAST_AWAY_CONST*/(void*)hideLabels, NULL, BC_NOBORDER } }; -static paramGroup_t turnoutPG = { "turnout", 0, turnoutPLs, sizeof turnoutPLs/sizeof turnoutPLs[0] }; + { PD_TOGGLE, &hideTurnoutWindow, "hide", PDO_DLGCMDBUTTON, hideLabels, NULL, BC_NOBORDER } }; +static paramGroup_t turnoutPG = { "turnout", 0, turnoutPLs, COUNT( turnoutPLs ) }; #endif +/* Draw turnout data */ + +/** + * The types of turnouts that get enhanced drawing methods + */ +enum dtoType { + DTO_INVALID, + DTO_NORMAL, + DTO_THREE, + DTO_WYE, + + DTO_CURVED, + + DTO_XING, + DTO_XNG9, + DTO_SSLIP, + DTO_DSLIP, + + DTO_LCROSS, + DTO_RCROSS, + DTO_DCROSS +}; + +// Define to plot control points (DTO_NORMAL, DTO_CURVED, DTO_XING, DTO_LCROSS) +// #define DTO_DEBUG DTO_XING + +#define DTO_DIM 4 // Maximum number of paths +#define DTO_SEGS 24 // Maximum number of control points + +static struct DrawToData_t { + TRKINX_T index; + enum dtoType toType; + track_p trk; + int bridge; + int endCnt; + int pathCnt; + int routeCnt; + int strCnt; + int crvCnt; + int rgtCnt; + int lftCnt; + int strPath; + int str2Path; + int crvPath; + int crv2Path; + int origCnt; + int origins[DTO_DIM]; + coOrd midPt; + struct extraDataCompound_t* xx; +} dtod; + +struct DrawTo_t { + int n; + trkSeg_p trkSeg[DTO_SEGS]; + coOrd base[DTO_SEGS]; + coOrd baseLast; + DIST_T dy[DTO_SEGS]; + ANGLE_T angle; + ANGLE_T crvAngle; + coOrd pts[DTO_SEGS]; + coOrd ptsLast; + char type; +}; + +static struct DrawTo_t dto[DTO_DIM]; + + - /**************************************** * * TURNOUT LIST MANAGEMENT @@ -109,47 +174,49 @@ static paramGroup_t turnoutPG = { "turnout", 0, turnoutPLs, sizeof turnoutPLs/si */ -EXPORT turnoutInfo_t * CreateNewTurnout( - char * scale, - char * title, - wIndex_t segCnt, - trkSeg_p segData, - wIndex_t pathLen, - PATHPTR_T paths, - EPINX_T endPtCnt, - trkEndPt_t * endPts, - DIST_T * radii, - wBool_t updateList ) +EXPORT turnoutInfo_t* CreateNewTurnout( + char* scale, + char* title, + wIndex_t segCnt, + trkSeg_p segData, + PATHPTR_T paths, + EPINX_T endPtCnt, + trkEndPt_t* endPts, + wBool_t updateList, + long options) { - turnoutInfo_t * to; - long changes=0; + turnoutInfo_t* to; + long changes = 0; - to = FindCompound( FIND_TURNOUT, scale, title ); + to = FindCompound(FIND_TURNOUT, scale, title); if (to == NULL) { - DYNARR_APPEND( turnoutInfo_t *, turnoutInfo_da, 10 ); - to = (turnoutInfo_t*)MyMalloc( sizeof *to ); - turnoutInfo(turnoutInfo_da.cnt-1) = to; - to->title = MyStrdup( title ); - to->scaleInx = LookupScale( scale ); + DYNARR_APPEND(turnoutInfo_t*, turnoutInfo_da, 10); + to = (turnoutInfo_t*)MyMalloc(sizeof * to); + turnoutInfo(turnoutInfo_da.cnt - 1) = to; + to->title = MyStrdup(title); + to->scaleInx = LookupScale(scale); changes = CHANGE_PARAMS; } to->segCnt = segCnt; trkSeg_p seg_p; - to->segs = (trkSeg_p)memdup( segData, (sizeof (*segData) * segCnt )); + to->segs = (trkSeg_p)memdup(segData, (sizeof(*segData) * segCnt)); seg_p = to->segs; - for (int i=0;i<segCnt;i++) { + for (int i = 0; i < segCnt; i++) { seg_p[i].bezSegs.ptr = NULL; seg_p[i].bezSegs.cnt = 0; seg_p[i].bezSegs.max = 0; } - CopyPoly(to->segs,segCnt); - FixUpBezierSegs(to->segs,to->segCnt); - GetSegBounds( zero, 0.0, segCnt, to->segs, &to->orig, &to->size ); + CopyPoly(to->segs, segCnt); + FixUpBezierSegs(to->segs, to->segCnt); + GetSegBounds(zero, 0.0, segCnt, to->segs, &to->orig, &to->size); to->endCnt = endPtCnt; - to->endPt = (trkEndPt_t*)memdup( endPts, (sizeof *endPts) * to->endCnt ); + to->endPt = (trkEndPt_t*)memdup(endPts, (sizeof * endPts) * to->endCnt); - to->pathLen = pathLen; - to->paths = (PATHPTR_T)memdup( paths, (sizeof *to->paths) * to->pathLen ); + if (options & COMPOUND_OPTION_PATH_OVERRIDE) + to->pathOverRide = TRUE; + if (options & COMPOUND_OPTION_PATH_NOCOMBINE) + to->pathNoCombine = TRUE; + SetParamPaths( to, paths ); to->paramFileIndex = curParamFileIndex; if (curParamFileIndex == PARAM_CUSTOM) to->contentsLabel = MyStrdup("Custom Turnouts"); @@ -157,42 +224,40 @@ EXPORT turnoutInfo_t * CreateNewTurnout( to->contentsLabel = curSubContents; #ifdef TURNOUTCMD if (updateList && turnoutListL != NULL) { - FormatCompoundTitle( LABEL_TABBED|LABEL_MANUF|LABEL_PARTNO|LABEL_DESCR, title ); + FormatCompoundTitle(LABEL_TABBED | LABEL_MANUF | LABEL_PARTNO | LABEL_DESCR, title); if (message[0] != '\0') - wListAddValue( turnoutListL, message, NULL, to ); + wListAddValue(turnoutListL, message, NULL, to); } #endif - to->barScale = curBarScale>0?curBarScale:-1; + to->barScale = curBarScale > 0 ? curBarScale : -1; to->special = TOnormal; - if (radii) { - to->special = TOcurved; - DYNARR_SET(DIST_T,to->u.curved.radii,to->endCnt); - for (int i=0;i<to->endCnt;i++) { - DYNARR_N(DIST_T,to->u.curved.radii,i) = radii[i]; - } - } if (updateList && changes) - DoChangeNotification( changes ); + DoChangeNotification(changes); return to; } /** * Delete a turnout parameter from the list and free the related memory * - * \param [IN] to turnout definition to be deleted + * \param [IN] toInfo turnout definition to be deleted + * + * \returns True if it succeeds */ BOOL_T -DeleteTurnout(void *toInfo) +DeleteTurnout(void* toInfo) { - turnoutInfo_t * to = (turnoutInfo_t *)toInfo; + turnoutInfo_t* to = (turnoutInfo_t*)toInfo; MyFree(to->title); MyFree(to->segs); MyFree(to->endPt); MyFree(to->paths); if (to->special) { - DYNARR_FREE(DIST_T, to->u.curved.radii); + switch (to->special) { + case TOadjustable: + default:; + } } MyFree(to); @@ -200,62 +265,62 @@ DeleteTurnout(void *toInfo) } /** - * Delete all turnout definitions that came from a specific parameter file. - * Due to the way the definitions are loaded from file it is safe to + * Delete all turnout definitions that came from a specific parameter file. + * Due to the way the definitions are loaded from file it is safe to * assume that they form a contiguous block in the array. - * + * * \param [IN] fileIndex parameter file */ void DeleteTurnoutParams(int fileIndex) { - int inx=0; - int startInx = -1; - int cnt = 0; - - // go to the start of the block - while (inx < turnoutInfo_da.cnt && - turnoutInfo(inx)->paramFileIndex != fileIndex) { - startInx = inx++; - } + int inx = 0; + int startInx = -1; + int cnt = 0; + + // go to the start of the block + while (inx < turnoutInfo_da.cnt && + turnoutInfo(inx)->paramFileIndex != fileIndex) { + startInx = inx++; + } - // delete them - for (; inx < turnoutInfo_da.cnt && - turnoutInfo(inx)->paramFileIndex == fileIndex; inx++) { - turnoutInfo_t * to = turnoutInfo(inx); - if (to->paramFileIndex == fileIndex) { - DeleteTurnout(to); - cnt++; - } - } + // delete them + for (; inx < turnoutInfo_da.cnt && + turnoutInfo(inx)->paramFileIndex == fileIndex; inx++) { + turnoutInfo_t* to = turnoutInfo(inx); + if (to->paramFileIndex == fileIndex) { + DeleteTurnout(to); + cnt++; + } + } - // copy down the rest of the list to fill the gap - startInx++; - while (inx < turnoutInfo_da.cnt) { - turnoutInfo(startInx++) = turnoutInfo(inx++); - } + // copy down the rest of the list to fill the gap + startInx++; + while (inx < turnoutInfo_da.cnt) { + turnoutInfo(startInx++) = turnoutInfo(inx++); + } - // and reduce the actual number - turnoutInfo_da.cnt -= cnt; + // and reduce the actual number + turnoutInfo_da.cnt -= cnt; } -/** - * Check to find out to what extent the contents of the parameter file can be used with - * the current layout scale / gauge. - * +/** + * Check to find out to what extent the contents of the parameter file can be used with + * the current layout scale / gauge. + * * If parameter scale == layout and parameter gauge == layout we have an exact fit. - * If parameter gauge == layout we have compatible track. - * OO scale is special cased. If the layout is in OO scale track in HO is considered + * If parameter gauge == layout we have compatible track. + * OO, O and N scales are special cased. If the layout is in OO scale track in HO is considered * an exact fit in spite of scale differences. - * + * * \param paramFileIndex * \param scaleIndex - * \return + * \return enum paraFileState */ -enum paramFileState -GetTrackCompatibility(int paramFileIndex, SCALEINX_T scaleIndex) +enum paramFileState + GetTrackCompatibility(int paramFileIndex, SCALEINX_T scaleIndex) { int i; enum paramFileState ret = PARAMFILE_NOTUSABLE; @@ -267,224 +332,182 @@ GetTrackCompatibility(int paramFileIndex, SCALEINX_T scaleIndex) // loop over all parameter entries or until a exact fit is found for (i = 0; i < turnoutInfo_da.cnt && ret < PARAMFILE_FIT; i++) { - turnoutInfo_t *to = turnoutInfo( i ); - if (to->paramFileIndex == paramFileIndex ) { - if (to->scaleInx == scaleIndex ) { + turnoutInfo_t* to = turnoutInfo(i); + if (to->paramFileIndex == paramFileIndex) { + SCALE_FIT_T fit = CompatibleScale(FIT_TURNOUT, to->scaleInx, scaleIndex); + if (fit == FIT_EXACT) { ret = PARAMFILE_FIT; break; - } else { - if (GetScaleTrackGauge(to->scaleInx) == gauge && - ret < PARAMFILE_COMPATIBLE) { - ret = PARAMFILE_COMPATIBLE; - // handle special cases - // if layout is OO scale, HO scale track is considered exact - char *layoutScaleName = GetScaleName(scaleIndex); - char *paramScaleName = GetScaleName(to->scaleInx); - if (!strcmp(layoutScaleName, "OO") && - !strcmp(paramScaleName, "HO")) { - ret = PARAMFILE_FIT; - } - //if layout is in Japanese or British N scale, N scale is exact - if ((!strcmp(layoutScaleName, "N(UK)") || - !strcmp(layoutScaleName, "N(JP)")) && - !strcmp(paramScaleName, "N")) { - ret = PARAMFILE_FIT; - } - } + } + else if (fit == FIT_COMPATIBLE) { + ret = PARAMFILE_COMPATIBLE; } } } return(ret); } - +/** + * Check Paths verifies that each track segment is on at least one path. + * It will assume new-P or old-P order is possible and does not change it. + * + * \param segCnt + * \param segs + * \param paths + * + * \returns -1 if a track segment is not on a path + */ EXPORT wIndex_t CheckPaths( - wIndex_t segCnt, - trkSeg_p segs, - PATHPTR_T paths ) + wIndex_t segCnt, + trkSeg_p segs, + PATHPTR_T paths) { if ((segCnt == 0) || !segs) return -1; + if (!paths) return -1; int pc, ps; PATHPTR_T pp = 0; - int inx; - static dynArr_t segMap_da; + int segInx[2], segEp[2]; int segTrkLast = -1; - + // Check that each track segment is on at least one path + // Note - In new-P the tracks may be preceded by draws (or interspersed by them) int suppressCheckPaths = log_suppressCheckPaths > 0 ? logTable(log_suppressCheckPaths).level : 0; - if ( suppressCheckPaths == 0 ) { - char trkSegInx = 0; - for ( int inx = 0; inx<segCnt; inx++ ) { - if ( IsSegTrack( &segs[inx] ) ) { - trkSegInx++; + if (suppressCheckPaths == 0) { + for (int inx = 0; inx < segCnt; inx++) { + if (IsSegTrack(&segs[inx])) { PATHPTR_T cp = paths; - while ( *cp ) { - // path is: 'N' 'A' 'M' 'E' 0 1 2 0 3 4 0 0 - // skip name - for ( ; *cp; cp++ ); - cp++; + while (*cp) { + // 0-9 are x00 to x09 or the negative equivalent (backwards) + // Pathlist is: Path00Path000 + // Path is: NAME01203400 + for (; *cp; cp++); //Skip Name + cp++; //Skip 0 after name // check each path component - for ( ; cp[0] || cp[1]; cp++ ) - if ( abs(*cp) == trkSegInx ) - break; - if ( *cp ) // we broke early - break; - cp += 2;; // Skip 2nd 0 + for (; cp[0] || cp[1]; cp++) { //keeps going even if there are two or more parts + if (!cp[0]) continue; //ignore the 0 between parts of the same PATH!! + GetSegInxEP(cp[0], &segInx[0], &segEp[0]); //GetSegInxEP subtracts one to match inx + if (segInx[0] == inx) break; //Found it! + } + if (*cp) // we broke early + break; // get out - we found it + cp++; + cp++; // Go to next path - past two 0s } - if ( !*cp ) { // we looked and didn't find - InputError( "Track segment %d not on Path", FALSE, inx+1 ); + if (!*cp) { // we looked through all the paths and didn't find it + InputError("Track segment %d not on Path", FALSE, inx + 1); return -1;; } } } } -typedef struct { - trkSeg_p seg; - int indx; -} segMap_t, * segMap_p; - -#define segMap(N) DYNARR_N( segMap_t, segMap_da, N ) - segMap_p sg; - DYNARR_RESET( segMap_t, segMap_da ); - // Don't reshuffle segs, but build an offset map instead just of the tracks - // Use the map to set up the paths to point at the correct segs in the Turnout - for ( inx=0; inx<segCnt; inx++ ) { - if ( IsSegTrack(&segs[inx]) ) { - DYNARR_APPEND( segMap_t, segMap_da, 10 ); - sg = &DYNARR_LAST(segMap_t,segMap_da); - sg->seg = &segs[inx]; - sg->indx = inx; - } - } - - for ( pc=0,pp=paths; *pp; pp+=2,pc++ ) { - for ( ps=0,pp+=strlen((char *)pp)+1; pp[0]!=0 || pp[1]!=0; pp++,ps++ ) { -#ifdef LATER - if (*pp >= '0' && *pp <= '9') - *pp -= '0'; - else if (*pp >= 'A' && *pp <= 'Z') - *pp -= 'A' - 10; - if (*pp < 0 || *pp > segCnt) { - InputError( _("Turnout path[%d:%d] out of bounds: %d"), - FALSE, pc, ps, *pp); - return -1; + for (pc = 0, pp = paths; *pp; pp += 2, pc++) { + for (ps = 0, pp += strlen((char*)pp) + 1; pp[0] != 0 || pp[1] != 0; pp++, ps++) { + if (pp[0] != 0 && ps == 0) { // First or only one } -#endif - //Rewrite the Path to point to the nth Track seg using the Map - int old_inx; - EPINX_T old_EP; - if (pp[0]!=0 && ps==0) { // First or only one - GetSegInxEP( pp[0], &old_inx, &old_EP ); - if (old_inx<0 || old_inx>= segMap_da.cnt) { - InputError( _("Turnout path[%d] %d is not a valid track segment"), - FALSE, pc, ps ); - return -1; - } - SetSegInxEP( &pp[0], DYNARR_N(segMap_t,segMap_da,old_inx).indx, old_EP); - } - if (pp[0]!=0 && pp[1]!=0 ) { - //Rewrite the Path to point to the nth Track seg using the Map - GetSegInxEP( pp[1], &old_inx, &old_EP ); - if (old_inx<0 || old_inx>= segMap_da.cnt) { - InputError( _("Turnout path[%d] %d is not a valid track segment"), - FALSE, pc, ps ); - return -1; - } - SetSegInxEP( &pp[1], DYNARR_N(segMap_t,segMap_da,old_inx).indx, old_EP); + if (pp[0] != 0 && pp[1] != 0) { /* check connectivity */ DIST_T d; - GetSegInxEP( pp[0], &segInx[0], &segEp[0] ); - GetSegInxEP( pp[1], &segInx[1], &segEp[1] ); - if ( !IsSegTrack( &segs[segInx[0]] ) ) { - InputError( _("Turnout path[%d] %d is not a track segment"), - FALSE, pc, pp[0] ); + GetSegInxEP(pp[0], &segInx[0], &segEp[0]); + GetSegInxEP(pp[1], &segInx[1], &segEp[1]); + if (!IsSegTrack(&segs[segInx[0]])) { + InputError(_("CheckPath: Turnout path[%d] %d is not a track segment"), + FALSE, pc, pp[0]); return -1; } - if ( !IsSegTrack( &segs[segInx[1]] ) ) { - InputError( _("Turnout path[%d] %d is not a track segment"), - FALSE, pc, pp[1] ); + if (!IsSegTrack(&segs[segInx[1]])) { + InputError(_("CheckPath: Turnout path[%d] %d is not a track segment"), + FALSE, pc, pp[1]); return -1; } - coOrd p0 = GetSegEndPt( &segs[segInx[0]], 1-segEp[0], FALSE, NULL ); - coOrd p1 = GetSegEndPt( &segs[segInx[1]], segEp[1], FALSE, NULL ); - d = FindDistance(p0,p1); + coOrd p0 = GetSegEndPt(&segs[segInx[0]], 1 - segEp[0], FALSE, NULL); + coOrd p1 = GetSegEndPt(&segs[segInx[1]], segEp[1], FALSE, NULL); + d = FindDistance(p0, p1); if (d > MIN_TURNOUT_SEG_CONNECT_DIST) { - InputError( _("Turnout path[%d] %d-%d not connected: %0.3f P0(%f,%f) P1(%f,%f)"), - FALSE, pc, pp[0], pp[1], d, p0.x, p0.y, p1.x, p1.y ); + InputError(_("CheckPath: Turnout path[%d] %d-%d not connected: %0.3f P0(%f,%f) P1(%f,%f)"), + FALSE, pc, pp[0], pp[1], d, p0.x, p0.y, p1.x, p1.y); return -1; } } } } - return pp-paths+1; + return (wIndex_t)(pp - paths + 1); } static BOOL_T ReadTurnoutParam( - char * firstLine ) + char* firstLine) { char scale[10]; - char *title; - turnoutInfo_t * to; + char* title; + turnoutInfo_t* to; + PATHPTR_T cp; + long options = 0; - if ( !GetArgs( firstLine+8, "sq", scale, &title ) ) + if (!GetArgs(firstLine + 8, "sqc", scale, &title, &cp)) return FALSE; - DYNARR_RESET( trkEndPt_t, tempEndPts_da ); + if (cp != NULL) + if (!GetArgs((char*)cp, "l", &options)) + return FALSE; + DYNARR_RESET(trkEndPt_t, tempEndPts_da); pathCnt = 0; - if ( !ReadSegs() ) + if (!ReadSegs()) return FALSE; - CheckPaths( tempSegs_da.cnt, &tempSegs(0), pathPtr ); - to = CreateNewTurnout( scale, title, tempSegs_da.cnt, &tempSegs(0), - pathCnt, pathPtr, tempEndPts_da.cnt, &tempEndPts(0), NULL, FALSE ); - MyFree( title ); + PATHPTR_T pPaths = NULL; + if ( pathPtr && pathPtr[0] && pathCnt > 0 ) + pPaths = pathPtr; + CheckPaths( tempSegs_da.cnt, &tempSegs(0), pPaths ); + to = CreateNewTurnout(scale, title, tempSegs_da.cnt, &tempSegs(0), + pPaths, tempEndPts_da.cnt, &tempEndPts(0), FALSE, options ); + MyFree(title); if (to == NULL) return FALSE; if (tempSpecial[0] != '\0') { - if (strncmp( tempSpecial, ADJUSTABLE, strlen(ADJUSTABLE) ) == 0) { + if (strncmp(tempSpecial, ADJUSTABLE, strlen(ADJUSTABLE)) == 0) { to->special = TOadjustable; - if ( !GetArgs( tempSpecial+strlen(ADJUSTABLE), "ff", - &to->u.adjustable.minD, &to->u.adjustable.maxD ) ) + if (!GetArgs(tempSpecial + strlen(ADJUSTABLE), "ff", + &to->u.adjustable.minD, &to->u.adjustable.maxD)) return FALSE; - } else { + } + else { InputError(_("Unknown special case"), TRUE); return FALSE; } } if (tempCustom[0] != '\0') { - to->customInfo = MyStrdup( tempCustom ); + to->customInfo = MyStrdup(tempCustom); } return TRUE; } -EXPORT turnoutInfo_t * TurnoutAdd( long mode, SCALEINX_T scale, wList_p list, coOrd * maxDim, EPINX_T epCnt ) +EXPORT turnoutInfo_t* TurnoutAdd(long mode, SCALEINX_T scale, wList_p list, coOrd* maxDim, EPINX_T epCnt) { wIndex_t inx; - turnoutInfo_t * to, * to1 = NULL; + turnoutInfo_t* to, * to1 = NULL; turnoutInx = 0; - for ( inx = 0; inx < turnoutInfo_da.cnt; inx++ ) { + for (inx = 0; inx < turnoutInfo_da.cnt; inx++) { to = turnoutInfo(inx); - if ( IsParamValid(to->paramFileIndex) && - to->segCnt > 0 && - CompatibleScale( TRUE, to->scaleInx, scale ) && - /*strcasecmp( to->scale, scaleName ) == 0 && */ - ( epCnt <= 0 || epCnt == to->endCnt ) ) { - if (to1==NULL) + if (IsParamValid(to->paramFileIndex) && + to->segCnt > 0 && + (FIT_NONE != CompatibleScale(FIT_TURNOUT, to->scaleInx, scale)) && + /*strcasecmp( to->scale, scaleName ) == 0 && */ + (epCnt <= 0 || epCnt == to->endCnt)) { + if (to1 == NULL) to1 = to; - if ( to == curTurnout ) { + if (to == curTurnout) { to1 = to; - turnoutInx = wListGetCount( list ); + turnoutInx = wListGetCount(list); } - FormatCompoundTitle( mode, to->title ); + FormatCompoundTitle(mode, to->title); if (message[0] != '\0') { - wListAddValue( list, message, NULL, to ); + wListAddValue(list, message, NULL, to); if (maxDim) { - if (to->size.x > maxDim->x) + if (to->size.x > maxDim->x) maxDim->x = to->size.x; - if (to->size.y > maxDim->y) + if (to->size.y > maxDim->y) maxDim->y = to->size.y; } } @@ -492,7 +515,7 @@ EXPORT turnoutInfo_t * TurnoutAdd( long mode, SCALEINX_T scale, wList_p list, co } return to1; } - + /**************************************** * * Adjustable Track Support @@ -501,20 +524,20 @@ EXPORT turnoutInfo_t * TurnoutAdd( long mode, SCALEINX_T scale, wList_p list, co static void ChangeAdjustableEndPt( - track_p trk, - EPINX_T ep, - DIST_T d ) + track_p trk, + EPINX_T ep, + DIST_T d) { - struct extraData * xx = GetTrkExtraData(trk); + struct extraDataCompound_t* xx = GET_EXTRA_DATA(trk, T_TURNOUT, extraDataCompound_t); coOrd pos; trkSeg_p segPtr; - ANGLE_T angle = GetTrkEndAngle( trk, ep ); - Translate( &pos, GetTrkEndPos( trk, 1-ep ), angle, d ); + ANGLE_T angle = GetTrkEndAngle(trk, ep); + Translate(&pos, GetTrkEndPos(trk, 1 - ep), angle, d); UndoModify(trk); - SetTrkEndPoint( trk, ep, pos, angle ); - if ( ep == 0 ) + SetTrkEndPoint(trk, ep, pos, angle); + if (ep == 0) xx->orig = pos; - for ( segPtr=xx->segs; segPtr<&xx->segs[xx->segCnt]; segPtr++ ) { + for (segPtr = xx->segs; segPtr < &xx->segs[xx->segCnt]; segPtr++) { switch (segPtr->type) { case SEG_STRLIN: case SEG_STRTRK: @@ -524,19 +547,19 @@ static void ChangeAdjustableEndPt( ; } } - ComputeBoundingBox( trk ); - DrawNewTrack( trk ); + ComputeBoundingBox(trk); + DrawNewTrack(trk); } EXPORT BOOL_T ConnectAdjustableTracks( - track_p trk1, - EPINX_T ep1, - track_p trk2, - EPINX_T ep2 ) + track_p trk1, + EPINX_T ep1, + track_p trk2, + EPINX_T ep2) { - struct extraData * xx1; - struct extraData * xx2; + struct extraDataCompound_t* xx1; + struct extraDataCompound_t* xx2; BOOL_T adj1, adj2; coOrd p1, p2; ANGLE_T a, a1, a2; @@ -545,65 +568,74 @@ EXPORT BOOL_T ConnectAdjustableTracks( coOrd off; DIST_T beyond; - xx1 = GetTrkExtraData(trk1); - xx2 = GetTrkExtraData(trk2); + if ((GetTrkType(trk1) != T_TURNOUT) && (GetTrkType(trk2) != T_TURNOUT)) return FALSE; + adj1 = adj2 = FALSE; - if (GetTrkType(trk1) == T_TURNOUT && xx1->special == TOadjustable) - adj1 = TRUE; - if (GetTrkType(trk2) == T_TURNOUT && xx2->special == TOadjustable) - adj2 = TRUE; + + if (GetTrkType(trk1) == T_TURNOUT) { + xx1 = GET_EXTRA_DATA(trk1, T_TURNOUT, extraDataCompound_t); + if (xx1->special == TOadjustable) + adj1 = TRUE; + } + if (GetTrkType(trk2) == T_TURNOUT) { + xx2 = GET_EXTRA_DATA(trk2, T_TURNOUT, extraDataCompound_t); + if (xx2->special == TOadjustable) + adj2 = TRUE; + } if (adj1 == FALSE && adj2 == FALSE) return FALSE; - a1 = GetTrkEndAngle( trk1, ep1 ); - a2 = GetTrkEndAngle( trk2, ep2 ); - a = NormalizeAngle( a1 - a2 + 180.0 + connectAngle/2.0); - if (a>connectAngle) + a1 = GetTrkEndAngle(trk1, ep1); + a2 = GetTrkEndAngle(trk2, ep2); + a = NormalizeAngle(a1 - a2 + 180.0 + connectAngle / 2.0); + if (a > connectAngle) return FALSE; - UndoStart( _("Connect Adjustable Tracks"), "changeAdjustableEndPt" ); + UndoStart(_("Connect Adjustable Tracks"), "changeAdjustableEndPt"); maxD = 0.0; if (adj1) { - p1 = GetTrkEndPos( trk1, 1-ep1 ); - Translate( &p1, p1, a1, xx1->u.adjustable.minD ); - maxD += xx1->u.adjustable.maxD-xx1->u.adjustable.minD; - } else { - p1 = GetTrkEndPos( trk1, ep1 ); + p1 = GetTrkEndPos(trk1, 1 - ep1); + Translate(&p1, p1, a1, xx1->u.adjustable.minD); + maxD += xx1->u.adjustable.maxD - xx1->u.adjustable.minD; + } + else { + p1 = GetTrkEndPos(trk1, ep1); } if (adj2) { - p2 = GetTrkEndPos( trk2, 1-ep2 ); - Translate( &p2, p2, a2, xx2->u.adjustable.minD ); - maxD += xx2->u.adjustable.maxD-xx2->u.adjustable.minD; - } else { - p2 = GetTrkEndPos( trk2, ep2 ); + p2 = GetTrkEndPos(trk2, 1 - ep2); + Translate(&p2, p2, a2, xx2->u.adjustable.minD); + maxD += xx2->u.adjustable.maxD - xx2->u.adjustable.minD; + } + else { + p2 = GetTrkEndPos(trk2, ep2); } - d = FindDistance( p1, p2 ); + d = FindDistance(p1, p2); rc = TRUE; if (d > maxD) { d = maxD; rc = FALSE; } - FindPos( &off, &beyond, p1, p2, a1, 10000.0 ); + FindPos(&off, &beyond, p1, p2, a1, DIST_INF); if (fabs(off.y) > connectDistance) rc = FALSE; if (adj1) { - UndrawNewTrack( trk1 ); - d1 = d * (xx1->u.adjustable.maxD-xx1->u.adjustable.minD)/maxD + xx1->u.adjustable.minD; - ChangeAdjustableEndPt( trk1, ep1, d1 ); + UndrawNewTrack(trk1); + d1 = d * (xx1->u.adjustable.maxD - xx1->u.adjustable.minD) / maxD + xx1->u.adjustable.minD; + ChangeAdjustableEndPt(trk1, ep1, d1); } if (adj2) { - UndrawNewTrack( trk2 ); - d2 = d * (xx2->u.adjustable.maxD-xx2->u.adjustable.minD)/maxD + xx2->u.adjustable.minD; - ChangeAdjustableEndPt( trk2, ep2, d2 ); + UndrawNewTrack(trk2); + d2 = d * (xx2->u.adjustable.maxD - xx2->u.adjustable.minD) / maxD + xx2->u.adjustable.minD; + ChangeAdjustableEndPt(trk2, ep2, d2); } if (rc) { - DrawEndPt( &mainD, trk1, ep1, wDrawColorWhite ); - DrawEndPt( &mainD, trk2, ep2, wDrawColorWhite ); - ConnectTracks( trk1, ep1, trk2, ep2 ); - DrawEndPt( &mainD, trk1, ep1, wDrawColorBlack ); - DrawEndPt( &mainD, trk2, ep2, wDrawColorBlack ); + DrawEndPt(&mainD, trk1, ep1, wDrawColorWhite); + DrawEndPt(&mainD, trk2, ep2, wDrawColorWhite); + ConnectTracks(trk1, ep1, trk2, ep2); + DrawEndPt(&mainD, trk1, ep1, wDrawColorBlack); + DrawEndPt(&mainD, trk2, ep2, wDrawColorBlack); } return rc; } - + /**************************************** * * Draw Turnout Roadbed @@ -613,81 +645,84 @@ EXPORT BOOL_T ConnectAdjustableTracks( int roadbedOnScreen = 0; -void DrawTurnoutRoadbedSide( drawCmd_p d, wDrawColor color, coOrd orig, ANGLE_T angle, trkSeg_p sp, ANGLE_T side, int first, int last ) +void DrawTurnoutRoadbedSide(drawCmd_p d, wDrawColor color, coOrd orig, ANGLE_T angle, trkSeg_p sp, ANGLE_T side, int first, int last) { segProcData_t data; - if (last<=first) + if (last <= first) return; data.drawRoadbedSide.first = first; data.drawRoadbedSide.last = last; data.drawRoadbedSide.side = side; data.drawRoadbedSide.roadbedWidth = roadbedWidth; - data.drawRoadbedSide.rbw = (wDrawWidth)floor(roadbedLineWidth*(d->dpi/d->scale)+0.5); + data.drawRoadbedSide.rbw = (wDrawWidth)floor(roadbedLineWidth * (d->dpi / d->scale) + 0.5); data.drawRoadbedSide.orig = orig; data.drawRoadbedSide.angle = angle; data.drawRoadbedSide.color = color; data.drawRoadbedSide.d = d; - SegProc( SEGPROC_DRAWROADBEDSIDE, sp, &data ); + SegProc(SEGPROC_DRAWROADBEDSIDE, sp, &data); } static void ComputeAndDrawTurnoutRoadbedSide( - drawCmd_p d, - wDrawColor color, - coOrd orig, - ANGLE_T angle, - trkSeg_p segPtr, - int segCnt, - int segInx, - ANGLE_T side ) + drawCmd_p d, + wDrawColor color, + coOrd orig, + ANGLE_T angle, + trkSeg_p segPtr, + int segCnt, + int segInx, + ANGLE_T side) { unsigned long res, res1; int b0, b1; - res = ComputeTurnoutRoadbedSide( segPtr, segCnt, segInx, side, roadbedWidth ); + res = ComputeTurnoutRoadbedSide(segPtr, segCnt, segInx, side, roadbedWidth); if (res == 0L) { - } else if (res == 0xFFFFFFFF) { - DrawTurnoutRoadbedSide( d, color, orig, angle, &segPtr[segInx], side, 0, 32 ); - } else { - for ( b0=0, res1=0x00000001; res1&&(res1&res); b0++,res1<<=1 ); - for ( b1=32,res1=0x80000000; res1&&(res1&res); b1--,res1>>=1 ); - DrawTurnoutRoadbedSide( d, color, orig, angle, &segPtr[segInx], side, 0, b0 ); - DrawTurnoutRoadbedSide( d, color, orig, angle, &segPtr[segInx], side, b1, 32 ); + } + else if (res == 0xFFFFFFFF) { + DrawTurnoutRoadbedSide(d, color, orig, angle, &segPtr[segInx], side, 0, 32); + } + else { + for (b0 = 0, res1 = 0x00000001; res1 && (res1 & res); b0++, res1 <<= 1); + for (b1 = 32, res1 = 0x80000000; res1 && (res1 & res); b1--, res1 >>= 1); + DrawTurnoutRoadbedSide(d, color, orig, angle, &segPtr[segInx], side, 0, b0); + DrawTurnoutRoadbedSide(d, color, orig, angle, &segPtr[segInx], side, b1, 32); } } static void DrawTurnoutRoadbed( - drawCmd_p d, - wDrawColor color, - coOrd orig, - ANGLE_T angle, - trkSeg_p segPtr, - int segCnt ) -{ - int inx, trkCnt=0, segInx=0; - for (inx=0;inx<segCnt;inx++) { - if ( IsSegTrack(&segPtr[inx]) ) { + drawCmd_p d, + wDrawColor color, + coOrd orig, + ANGLE_T angle, + trkSeg_p segPtr, + int segCnt) +{ + int inx, trkCnt = 0, segInx = 0; + for (inx = 0; inx < segCnt; inx++) { + if (IsSegTrack(&segPtr[inx])) { segInx = inx; trkCnt++; - if (trkCnt>1) + if (trkCnt > 1) break; } } - if (trkCnt==0) + if (trkCnt == 0) return; if (trkCnt == 1) { - DrawTurnoutRoadbedSide( d, color, orig, angle, &segPtr[segInx], +90, 0, 32 ); - DrawTurnoutRoadbedSide( d, color, orig, angle, &segPtr[segInx], -90, 0, 32 ); - } else { - for (inx=0;inx<segCnt;inx++) { - if ( IsSegTrack(&segPtr[inx]) ) { - ComputeAndDrawTurnoutRoadbedSide( d, color, orig, angle, segPtr, segCnt, inx, +90 ); - ComputeAndDrawTurnoutRoadbedSide( d, color, orig, angle, segPtr, segCnt, inx, -90 ); + DrawTurnoutRoadbedSide(d, color, orig, angle, &segPtr[segInx], +90, 0, 32); + DrawTurnoutRoadbedSide(d, color, orig, angle, &segPtr[segInx], -90, 0, 32); + } + else { + for (inx = 0; inx < segCnt; inx++) { + if (IsSegTrack(&segPtr[inx])) { + ComputeAndDrawTurnoutRoadbedSide(d, color, orig, angle, segPtr, segCnt, inx, +90); + ComputeAndDrawTurnoutRoadbedSide(d, color, orig, angle, segPtr, segCnt, inx, -90); } } } } - + /**************************************** * * HAND LAID TURNOUTS @@ -695,47 +730,47 @@ static void DrawTurnoutRoadbed( */ track_p NewHandLaidTurnout( - coOrd p0, - ANGLE_T a0, - coOrd p1, - ANGLE_T a1, - coOrd p2, - ANGLE_T a2, - ANGLE_T frogA ) + coOrd p0, + ANGLE_T a0, + coOrd p1, + ANGLE_T a1, + coOrd p2, + ANGLE_T a2, + ANGLE_T frogA) { track_p trk; - struct extraData * xx; + struct extraDataCompound_t* xx; trkSeg_t segs[2]; - sprintf( message, "\tHand Laid Turnout, Angle=%0.1f\t", frogA ); - DYNARR_SET( trkEndPt_t, tempEndPts_da, 2 ); - memset( &tempEndPts(0), 0, tempEndPts_da.cnt * sizeof tempEndPts(0) ); + sprintf(message, "\tHand Laid Turnout, Angle=%0.1f\t", frogA); + DYNARR_SET(trkEndPt_t, tempEndPts_da, 2); + memset(&tempEndPts(0), 0, tempEndPts_da.cnt * sizeof tempEndPts(0)); tempEndPts(0).pos = p0; tempEndPts(0).angle = a0; tempEndPts(1).pos = p1; tempEndPts(1).angle = a1; tempEndPts(2).pos = p2; tempEndPts(2).angle = a2; - Rotate( &p1, p0, -a0 ); + Rotate(&p1, p0, -a0); p1.x -= p0.x; p1.y -= p0.y; segs[0].type = SEG_STRTRK; segs[0].color = wDrawColorBlack; segs[0].u.l.pos[0] = zero; segs[0].u.l.pos[1] = p1; - Rotate( &p2, p0, -a0 ); + Rotate(&p2, p0, -a0); p2.x -= p0.x; p2.y -= p0.y; segs[1].type = SEG_STRTRK; segs[1].color = wDrawColorBlack; segs[1].u.l.pos[0] = zero; segs[1].u.l.pos[1] = p2; - trk = NewCompound( T_TURNOUT, 0, p0, a0, message, 3, &tempEndPts(0), NULL, 22, "Normal\0\1\0\0Reverse\0\2\0\0\0", 2, segs ); - xx = GetTrkExtraData(trk); + trk = NewCompound(T_TURNOUT, 0, p0, a0, message, 3, &tempEndPts(0), (PATHPTR_T)"Normal\0\1\0\0Reverse\0\2\0\0\0", 2, segs); + xx = GET_EXTRA_DATA(trk, T_TURNOUT, extraDataCompound_t); xx->handlaid = TRUE; return trk; } - + /**************************************** * * GENERIC FUNCTIONS @@ -743,136 +778,1982 @@ track_p NewHandLaidTurnout( */ static coOrd MapPathPos( - struct extraData * xx, - signed char segInx, - EPINX_T ep ) + struct extraDataCompound_t* xx, + signed char segInx, + EPINX_T ep) { trkSeg_p segPtr; coOrd pos; - if ( segInx < 0 ) { - segInx = - segInx; - ep = 1-ep; + if (segInx < 0) { + segInx = -segInx; + ep = 1 - ep; } - segPtr=xx->segs+(segInx-1); + segPtr = xx->segs + (segInx - 1); if (!IsSegTrack(segPtr)) { - fprintf( stderr, "mapPathPos: bad segInx: %d\n", segInx ); + fprintf(stderr, "mapPathPos: bad segInx: %d\n", segInx); return zero; } - pos = GetSegEndPt( segPtr, ep, FALSE, NULL ); - REORIGIN1( pos, xx->angle, xx->orig ); + pos = GetSegEndPt(segPtr, ep, FALSE, NULL); + REORIGIN1(pos, xx->angle, xx->orig); return pos; } +static trkSeg_p MapPathSeg( + struct extraDataCompound_t* xx, + signed char segInx) { + if (segInx < 0) { + segInx = -segInx; + } + return xx->segs + (segInx - 1); +} + + +/**************************************** + * + * TURNOUT DRAWING + * + */ + + /** + * Get the paths from the turnout definition. Puts the results into static dto structure. + * Curved segments are broken up into short sections of the lesser of 5 degrees or 5 * tie spacing. + * + * \param trk track_p pointer to a track + * \param xx pointer to the extraDataCompound struct + * + * \returns the number of paths + */ +int GetTurnoutPaths(track_p trk, struct extraDataCompound_t* xx) { + wIndex_t segInx; + wIndex_t segEP; + + SCALEINX_T scaleInx = GetTrkScale(trk); + tieData_p td = GetScaleTieData(scaleInx); + + int i; + ANGLE_T a0, a1, aa0, aa1; + DIST_T r, len; + coOrd p0, p1; + + PATHPTR_T pp; + int pathCnt = 0, routeCnt = 0; + + for (i = 0; i < DTO_DIM; i++) + dto[i].n = 0; + + dtod.trk = trk; + dtod.index = trk->index; + dtod.xx = xx; + + // Validate that the first segment starts at (0, 0) + // and if STR p1.y == 0, if CRV angle == 0 or angle == 180 + GetSegInxEP(1, &segInx, &segEP); + trkSeg_p segPtr = &xx->segs[segInx]; + switch (segPtr->type) { + case SEG_STRTRK: + p0 = segPtr->u.l.pos[0]; + p1 = segPtr->u.l.pos[1]; + if ((FindDistance(p0, zero) > EPSILON) || (fabs(p1.y) > EPSILON)) + return -1; + break; + case SEG_CRVTRK: + r = fabs(segPtr->u.c.radius); + a0 = segPtr->u.c.a0; + a1 = segPtr->u.c.a1; + + if (segPtr->u.c.radius > 0) { + aa0 = a0; + } + else { + aa0 = a0 + a1; + } + PointOnCircle(&p0, segPtr->u.c.center, r, aa0); + if ((FindDistance(p0, zero) > EPSILON) + || ((fabs(aa0 - 180) > EPSILON) && (fabs(aa0) > EPSILON))) + return -1; + break; + } + + pp = GetPaths(trk); + while (pp[0]) { + pp += strlen((char*)pp) + 1; + + ANGLE_T angle = 0; + while (pp[0]) { + if (pathCnt < DTO_DIM) + dto[pathCnt].type = 'S'; + while (pp[0]) { + GetSegInxEP(pp[0], &segInx, &segEP); + // trkSeg_p + segPtr = &xx->segs[segInx]; + switch (segPtr->type) { + case SEG_STRTRK: + p0 = segPtr->u.l.pos[0]; + p1 = segPtr->u.l.pos[1]; + + wIndex_t n = dto[pathCnt].n; + dto[pathCnt].trkSeg[n] = segPtr; + dto[pathCnt].base[n] = p0; + n++; + dto[pathCnt].trkSeg[n] = segPtr; + dto[pathCnt].base[n] = p1; + // n++; + dto[pathCnt].n = n; + + if (n >= DTO_SEGS - 1) return -1; + + break; + case SEG_CRVTRK: + r = fabs(segPtr->u.c.radius); + + dto[pathCnt].type = segPtr->u.c.center.y < 0 ? 'R' : 'L'; + + a0 = segPtr->u.c.a0; + a1 = segPtr->u.c.a1; + + angle += a1; + + len = D2R(a1) * r; + // Every 5 degrees or 5 * tie spacing + int cnt = (int)floor(a1 / 5.0); + int cnt2 = (int)floor(len / 5 / td->spacing); + if (cnt2 > cnt) cnt = cnt2; + if (cnt <= 0) cnt = 1; + + aa1 = a1 / cnt; + if (dto[pathCnt].type == 'R') { + aa0 = a0; + } + else { + aa0 = a0 + a1; + aa1 = -aa1; + } + PointOnCircle(&p0, segPtr->u.c.center, r, aa0); + n = dto[pathCnt].n; + dto[pathCnt].trkSeg[n] = segPtr; + dto[pathCnt].base[n] = p0; + n++; + dto[pathCnt].n = n; + + while (cnt > 0) { + aa0 += aa1; + PointOnCircle(&p0, segPtr->u.c.center, r, aa0); + + // n = dto[pathCnt].n; + dto[pathCnt].trkSeg[n] = segPtr; + dto[pathCnt].base[n] = p0; + n++; + + if (n >= DTO_SEGS - 1) return -1; + + cnt--; + } + n--; // remove that last point count + dto[pathCnt].n = n; + } + pp++; + } + // Include the last point + dto[pathCnt].crvAngle = angle; + dto[pathCnt].n++; + + pathCnt++; + if (pathCnt > DTO_DIM) return -1; + pp++; + } + routeCnt++; + pp++; + } + dtod.pathCnt = pathCnt; + dtod.routeCnt = routeCnt; + dtod.endCnt = trk->endCnt; + + // Guard value: n < DTO_SEGS - 2 + for (i = 0; i < pathCnt; i++) + dto[i].pts[dto[i].n].x = DIST_INF; + + return pathCnt; +} + +/** +* Sets the turnout type if compatible with enhanced drawing methods. The data is +* from the path data saved in dtod and dto by GetTurnoutPaths. The turnout type is +* stored in the dtod.toType. DTO_INVALID (0) if the enhanced methods cannot handle +* it. +*/ +void GetTurnoutType() { + dtod.strPath = -1; + dtod.str2Path = -1; + dtod.crvPath = -1; + dtod.crv2Path = -1; + + dtod.toType = DTO_INVALID; + + int strCnt = 0, crvCnt = 0, lftCnt = 0, rgtCnt = 0; + enum dtoType toType = DTO_INVALID; + int i, j; + + // Count path origins + dtod.origCnt = 1; + dtod.origins[0] = 0; + + for (i = 1; i < dtod.pathCnt; i++) { + int eq = 0; + for (j = 0; j < i; j++) { + if (CoOrdEqual(dto[dtod.origins[j]].base[0], dto[i].base[0])) + eq++; + } + if (eq == 0) { + dtod.origins[dtod.origCnt] = i; + dtod.origCnt++; + } + + if (dtod.origCnt > 4) + return; + } + + // Determine the path type + for (i = 0; i < dtod.pathCnt; i++) { + switch (dto[i].type) { + case 'S': + strCnt++; + if (strCnt == 1) + dtod.strPath = i; + else + dtod.str2Path = i; + break; + case 'L': + lftCnt++; + crvCnt++; + if (crvCnt == 1) + dtod.crvPath = i; + else + dtod.crv2Path = i; + break; + case 'R': + rgtCnt++; + crvCnt++; + if (crvCnt == 1) + dtod.crvPath = i; + else + dtod.crv2Path = i; + break; + } + } + + dtod.strCnt = strCnt; + dtod.crvCnt = crvCnt; + dtod.lftCnt = lftCnt; + dtod.rgtCnt = rgtCnt; + + // Normal two- or three-way turnout, or a curved turnout + if (dtod.origCnt == 1) { + if (dtod.pathCnt == 2) { + if (strCnt == 1 && crvCnt == 1) { + dtod.toType = DTO_NORMAL; + } + else if ((strCnt == 0) && ((lftCnt == 2) || (rgtCnt == 2))) { + // Assumes outer curve is [0] and inner is [1] + if ((dto[0].crvAngle <= 20) && (dto[1].crvAngle - dto[0].crvAngle <= 15)) + dtod.toType = DTO_CURVED; + } + else if (lftCnt == 1 && rgtCnt == 1) { + dtod.toType = DTO_WYE; + } + } + else if ((dtod.pathCnt == 3) && (strCnt == 1) + && (lftCnt == 1) && (rgtCnt == 1)) { + dtod.toType = DTO_THREE; + } + } + else + // Crossing, single- and double-slip + if ((dtod.origCnt == 2) && (dtod.endCnt == 4) + && strCnt == 2) { + + ANGLE_T a0, a1, a2; + a1 = FindAngle(dto[dtod.strPath].base[0], dto[dtod.strPath].base[1]); + a2 = FindAngle(dto[dtod.str2Path].base[0], dto[dtod.str2Path].base[1]); + // Swap the ends of the strPath if large angle + if((a1 > 180.0) && (dto[dtod.strPath].n == 2)) + { + coOrd tmp = dto[dtod.strPath].base[0]; + dto[dtod.strPath].base[0] = dto[dtod.strPath].base[1]; + dto[dtod.strPath].base[1] = tmp; + + i = dto[dtod.strPath].n - 1; + tmp = dto[dtod.strPath].pts[0]; + dto[dtod.strPath].pts[0] = dto[dtod.strPath].pts[i]; + dto[dtod.strPath].pts[i] = tmp; + + a1 = a1 - 180.0; + dto[dtod.strPath].angle = a1; + } + // Swap the ends of the str2Path if large angle + if((a2 > 180.0) && (dto[dtod.str2Path].n == 2)) + { + coOrd tmp = dto[dtod.str2Path].base[0]; + dto[dtod.str2Path].base[0] = dto[dtod.str2Path].base[1]; + dto[dtod.str2Path].base[1] = tmp; + + i = dto[dtod.str2Path].n - 1; + tmp = dto[dtod.str2Path].pts[0]; + dto[dtod.str2Path].pts[0] = dto[dtod.str2Path].pts[i]; + dto[dtod.str2Path].pts[i] = tmp; + + a2 = a2 - 180.0; + dto[dtod.str2Path].angle = a2; + } + a0 = DifferenceBetweenAngles(a1, a2); + if(a0 < 0) + { + int tmp = dtod.strPath; + dtod.strPath = dtod.str2Path; + dtod.str2Path = tmp; + a0 = NormalizeAngle(-a0); + } + if ((a0 > 90.0) || (a0 < 0.0)) + return; + + coOrd p1 = dto[dtod.strPath].base[0]; + coOrd p2 = dto[dtod.str2Path].base[0]; + coOrd pos = zero; + int intersect = FindIntersection(&pos, p1, a1, p2, a2); + + if (intersect) { + if(strCnt == 2 && dtod.pathCnt == 2){ + if((a0 <= 61) && (a0 >= -61)) + dtod.toType = DTO_XING; + else + dtod.toType = DTO_XNG9; + } + else if(dtod.pathCnt == 3 && (lftCnt == 1 || rgtCnt == 1)){ + dtod.toType = DTO_SSLIP; + } + else if(dtod.pathCnt == 4 && lftCnt == 1 && rgtCnt == 1){ + dtod.toType = DTO_DSLIP; + } + } + // No intersect, it could be a crossover + else if (strCnt == 2) { + if (dtod.pathCnt == 4 && lftCnt == 1 && rgtCnt == 1) { + dtod.toType = DTO_DCROSS; + } + else if(dtod.pathCnt == 3){ + // Perverse test because the cross paths go Left then Right, for example + if(lftCnt == 1){ + dtod.toType = DTO_RCROSS; + } + else if(rgtCnt == 1){ + dtod.toType = DTO_LCROSS; + } + else{ + dtod.toType = DTO_INVALID; + } + } + } + } +} + +/** + * Draw Layout lines and points + * + * \param d The drawing object + * \param scaleInx The layout/track scale index + */ +static void DrawDtoLayout( + drawCmd_p d, + SCALEINX_T scaleInx +) +{ + tieData_p td; + td = GetScaleTieData(scaleInx); + + // Draw the points and lines from dto + double r = td->width / 2; + // if (r < 1) r = 1; + + int i, j; + for (i = 0; i < DTO_DIM; i++) { + for (j = 0; j < dto[i].n; j++) { + DrawFillCircle(d, dto[i].pts[j], r, drawColorPurple); + if (j < dto[i].n - 1) + DrawLine(d, dto[i].pts[j], dto[i].pts[j + 1], 0, drawColorPurple); + } + } +} + +/** +* Use the coOrds to build a polygon and draw the bridge fill. Note that the coordinates are +* passed as pairs, and rearranged into a polygon with the 1,2,4,3 order. +* +* \param d The drawing object +* \param b1 The first coordinate +* \param b2 The second coordinate +* \param b3 The third coordinate +* \param b4 The fourth coordinate +*/ +static void DrawBridgeFill( + drawCmd_p d, + coOrd b1, + coOrd b2, + coOrd b3, + coOrd b4 + ) +{ + coOrd p[4] = {b1, b2, b4, b3}; + DrawPoly(d,4,p,NULL,drawColorGrey90,0,DRAW_FILL ); +} + +/** +* Draw Bridge parapets and background for a turnout +* +* \param d The drawing object +* \param path1 The first path +* \param path2 The second path +*/ +static void DrawTurnoutBridge( + drawCmd_p d, + int path1, + int path2 +) +{ + DIST_T trackGauge = GetTrkGauge(dtod.trk); + wDrawWidth width2 = (wDrawWidth)round((2.0 * d->dpi) / BASE_DPI); + if (d->options&DC_PRINT) + width2 = (wDrawWidth)round(d->dpi / BASE_DPI); + + coOrd b1,b2,b3,b4,b5,b6; + ANGLE_T angle = dtod.xx->angle,a = 0.0; + int i,j,i1,i2; + i1 = path1; + i2 = path2; + if(dto[i1].base[dto[i1].n - 1].y < dto[i2].base[dto[i2].n - 1].y) { + i1 = path2; + i2 = path1; + // a = -a; + } + + if(dtod.toType == DTO_THREE) { + i = dtod.strPath; + DIST_T dy = fabs(dto[i].dy[0]) + trackGauge * 1.5; + b1 = dto[i].pts[0]; + Translate(&b3,b1,(angle + a),dy); + b1 = dto[i].pts[dto[i].n - 1]; + Translate(&b4,b1,(angle + a),dy); + b2 = dto[i].pts[0]; + Translate(&b5,b2,(angle + a),-dy); + b2 = dto[i].pts[dto[i].n - 1]; + Translate(&b6,b2,(angle + a),-dy); + + // Draw the bridge background + DrawBridgeFill(d,b3,b4,b5,b6); + } + + for(i = i1; 1; i = i2,a = 180.0) { + DIST_T dy = fabs(dto[i].dy[0]) + trackGauge * 1.5; + b1 = dto[i].pts[0]; + Translate(&b3,b1,(angle + a),dy); + Translate(&b5,b1,(angle + a),-(dy * 0.75)); + for(j = 1; j < dto[i].n; j++) { + dy = fabs(dto[i].dy[j]) + trackGauge * 1.5; + b2 = dto[i].pts[j]; + Translate(&b4,b2,(angle + a),dy); + Translate(&b6,b2,(angle + a),-(dy * 0.75)); + + // Draw the bridge background + DrawBridgeFill(d,b3,b4,b5,b6); + + // Draw the bridge edge + DrawLine(d,b3,b4,width2,drawColorBlack); + + b1 = b2; + b3 = b4; + b5 = b6; + } + + if(i == i2) + break; + } + + EPINX_T ep; + coOrd p; + track_p trk1; + coOrd p0,p1; + + for(ep = 0; ep < 3; ep++) { + trk1 = GetTrkEndTrk(dtod.trk,ep); + + if((trk1) && (!GetTrkBridge(trk1))) { + + p = GetTrkEndPos(dtod.trk,ep); + a = GetTrkEndAngle(dtod.trk,ep) + 90.0; + + int i = (dtod.lftCnt > 0) && (dtod.rgtCnt == 0) ? 2 : 1; + if(ep != i) { + Translate(&p0,p,a,trackGauge * 1.5); + Translate(&p1,p0,a - 45.0,trackGauge * 1.5); + DrawLine(d,p0,p1,width2,drawColorBlack); + } + if(ep != (3 - i)) { + Translate(&p0,p,a,-trackGauge * 1.5); + Translate(&p1,p0,a + 45.0,-trackGauge * 1.5); + DrawLine(d,p0,p1,width2,drawColorBlack); + } + } + } +} + +/** +* Draw Bridge parapets and background for a cross-over +* +* \param d The drawing object +* \param path1 The first path, straight +* \param path2 The second path, straight +*/ +static void DrawCrossBridge( + drawCmd_p d, + int path1, + int path2 +) +{ + DIST_T trackGauge = GetTrkGauge(dtod.trk); + wDrawWidth width2 = (wDrawWidth)round((2.0 * d->dpi)/BASE_DPI); + if (d->options&DC_PRINT) + width2 = (wDrawWidth)round(d->dpi / BASE_DPI); + + coOrd b1, b2, b3, b4, b5, b6; + ANGLE_T angle = dtod.xx->angle, a = 0.0; + int i1, i2; + i1 = path1; + i2 = path2; + if(dto[i1].base[dto[i1].n - 1].y < dto[i2].base[dto[i2].n - 1].y) { + i1 = path2; + i2 = path1; + // a = -a; + } + + DIST_T dy = fabs(dto[i1].dy[0]) + trackGauge * 1.5; + b1 = dto[i1].pts[0]; + Translate(&b3,b1,(angle + a),dy); + b1 = dto[i1].pts[dto[i1].n-1]; + Translate(&b4,b1,(angle + a),dy); + b2 = dto[i2].pts[0]; + Translate(&b5,b2,(angle + a),-dy); + b2 = dto[i2].pts[dto[i2].n-1]; + Translate(&b6,b2,(angle + a),-dy); + + // Draw the bridge background + DrawBridgeFill(d, b3, b4, b5, b6); + + // Draw the bridge edges + DrawLine(d,b3,b4,width2,drawColorBlack); + DrawLine(d,b5,b6,width2,drawColorBlack); + + EPINX_T ep; + coOrd p; + track_p trk1; + coOrd p0,p1; + + for(ep = 0; ep < 4; ep++) { + trk1 = GetTrkEndTrk(dtod.trk,ep); + + if((trk1) && (!GetTrkBridge(trk1))) { + p = GetTrkEndPos(dtod.trk,ep); + a = GetTrkEndAngle(dtod.trk,ep) + 90.0; + + if((ep == 1) || (ep == 2)) { + Translate(&p0,p,a,trackGauge * 1.5); + Translate(&p1,p0,a - 45.0,trackGauge * 1.5); + DrawLine(d,p0,p1,width2,drawColorBlack); + } + if((ep == 0) || (ep == 3)) { + Translate(&p0,p,a,-trackGauge * 1.5); + Translate(&p1,p0,a + 45.0,-trackGauge * 1.5); + DrawLine(d,p0,p1,width2,drawColorBlack); + } + } + } +} + +/** +* Draw Bridge parapets and background for a crossing +* +* \param d The drawing object +* \param path1 The first path +* \param path2 The second path +*/ +static void DrawXingBridge( + drawCmd_p d, + int path1, + int path2 +) +{ + DIST_T trackGauge = GetTrkGauge(dtod.trk); + wDrawWidth width2 = (wDrawWidth)round((2.0 * d->dpi)/BASE_DPI); + if (d->options&DC_PRINT) + width2 = (wDrawWidth)round(d->dpi / BASE_DPI); + + coOrd b0, b1, b2, b3, b4, b5, b6; + int i, j, i1, i2; + i1 = dtod.strPath; + i2 = dtod.str2Path; + + // Bridge fill both straight sections + wDrawWidth width3 = (wDrawWidth)round(trackGauge * 3 * d->dpi/d->scale); + b1 = dto[i1].pts[0]; + b2 = dto[i1].pts[dto[i1].n-1]; + DrawLine(d,b1,b2,width3,wDrawColorGrey90); + b1 = dto[i2].pts[0]; + b2 = dto[i2].pts[dto[i1].n-1]; + DrawLine(d,b1,b2,width3,wDrawColorGrey90); + + i1 = path1; + i2 = path2; + if(dto[i1].base[dto[i1].n - 1].y < dto[i2].base[dto[i2].n - 1].y) { + i1 = path2; + i2 = path1; + } + + // Handle curved sections for slips + BOOL_T hasLeft = 0, hasRgt = 0; + ANGLE_T angle = dtod.xx->angle, a = 0.0; + for(i = i1; 1; i = i2,a = 180.0) { + DIST_T dy = fabs(dto[i].dy[0]) + trackGauge * 1.5; + b1 = dto[i].pts[0]; + Translate(&b3,b1,(angle + a),dy); + Translate(&b5,b1,(angle + a),-(dy * 0.75)); + if(dto[i].type != 'S') { + if(dto[i].type == 'L') + hasLeft = 1; + else if(dto[i].type == 'R') + hasRgt = 1; + for(j = 1; j < dto[i].n; j++) { + dy = fabs(dto[i].dy[j]) + trackGauge * 1.5; + b2 = dto[i].pts[j]; + Translate(&b4,b2,(angle + a),dy); + Translate(&b6,b2,(angle + a),-(dy * 0.75)); + + // Draw the bridge background + DrawBridgeFill(d,b3,b4,b5,b6); + + // Draw the bridge edge + DrawLine(d,b3,b4,width2,drawColorBlack); + b1 = b2; + b3 = b4; + b5 = b6; + } + } + if(i == i2) + break; + } + + if(dtod.strPath >= 0 && dtod.str2Path >= 0) { + i1 = dtod.strPath; + i2 = dtod.str2Path; + if(!hasRgt) { + DIST_T dy = trackGauge * 1.5; + ANGLE_T a1, a2; + b1 = dto[i1].pts[0]; + a1 = dto[i1].angle + 90; + Translate(&b3,b1,a1,dy); + + b2 = dto[i2].pts[dto[i2].n - 1]; + a2 = dto[i2].angle + 90; + Translate(&b4,b2,a2,dy); + + FindIntersection(&b0, b3, a1-90.0, b4, a2-90.0); + + // Draw the bridge edge + DrawLine(d,b3,b0,width2,drawColorBlack); + DrawLine(d,b0,b4,width2,drawColorBlack); + } + + if(!hasLeft) { + DIST_T dy = trackGauge * 1.5; + ANGLE_T a1, a2; + b1 = dto[i2].pts[0]; + a1 = dto[i2].angle - 90; + Translate(&b3,b1,a1,dy); + + b2 = dto[i1].pts[dto[i1].n - 1]; + a2 = dto[i1].angle - 90; + Translate(&b4,b2,a2,dy); + + FindIntersection(&b0, b3, a1+90.0, b4, a2+90.0); + + // Draw the bridge edge + DrawLine(d,b3,b0,width2,drawColorBlack); + DrawLine(d,b0,b4,width2,drawColorBlack); + } + + if(dtod.toType == DTO_XNG9) { + DIST_T dy = trackGauge * 1.5; + ANGLE_T a1, a2; + b1 = dto[i1].pts[dto[i1].n - 1]; + a1 = dto[i1].angle + 90; + Translate(&b3,b1,a1,dy); + + b2 = dto[i2].pts[dto[i2].n - 1]; + a2 = dto[i2].angle - 90; + Translate(&b4,b2,a2,dy); + + FindIntersection(&b0, b3, a1-90.0, b4, a2+90.0); + + // Draw the bridge edge + DrawLine(d,b3,b0,width2,drawColorBlack); + DrawLine(d,b0,b4,width2,drawColorBlack); + + b1 = dto[i1].pts[0]; + a1 = dto[i1].angle - 90; + Translate(&b3,b1,a1,dy); + + b2 = dto[i2].pts[0]; + a2 = dto[i2].angle + 90; + Translate(&b4,b2,a2,dy); + + FindIntersection(&b0, b3, a1+90.0, b4, a2-90.0); + + // Draw the bridge edge + DrawLine(d,b3,b0,width2,drawColorBlack); + DrawLine(d,b0,b4,width2,drawColorBlack); + } + } + + // Bridge wings + EPINX_T ep; + coOrd p; + track_p trk1; + coOrd p0,p1; + + for(ep = 0; ep < 4; ep++) { + trk1 = GetTrkEndTrk(dtod.trk,ep); + + if((trk1) && (!GetTrkBridge(trk1))) { + p = GetTrkEndPos(dtod.trk,ep); + a = GetTrkEndAngle(dtod.trk,ep) + 90.0; + + if((dtod.toType == DTO_XNG9) || (ep == 2) || (ep == 3)) { + Translate(&p0,p,a,trackGauge * 1.5); + Translate(&p1,p0,a - 45.0,trackGauge * 1.5); + DrawLine(d,p0,p1,width2,drawColorBlack); + } + if((dtod.toType == DTO_XNG9) || (ep == 0) || (ep == 1)) { + Translate(&p0,p,a,-trackGauge * 1.5); + Translate(&p1,p0,a + 45.0,-trackGauge * 1.5); + DrawLine(d,p0,p1,width2,drawColorBlack); + } + } + } +} + +/** + * Init Normal Turnout data structure + * Calculates the dy value of each segment + * Sets pts values REORIGIN base to actual position and angle + * Save often used last base and last point coOrd + */ +static void DrawDtoInit() +{ + struct extraDataCompound_t* xx = dtod.xx; + coOrd p1; + int i, j; + + for(i = 0; i < DTO_DIM; i++) { + int n = dto[i].n; + for(j = 0; j < n; j++) { + REORIGIN(p1,dto[i].base[j],xx->angle,xx->orig); + dto[i].pts[j] = p1; + if(j < n - 1) + dto[i].dy[j] = (dto[i].base[j + 1].y - dto[i].base[j].y) / (dto[i].base[j + 1].x - dto[i].base[j].x); + } + dto[i].ptsLast = dto[i].pts[n - 1]; + dto[i].baseLast = dto[i].base[n - 1]; + } +} + +/** + * Draw Normal (Single Origin) Turnout Bridge and Ties. Uses the static dto and dtod structures. + * + * \param d The drawing object + * \param scaleInx The layout/track scale index + * \param color The tie color. If black the color is read from the global tieColor. + */ +static void DrawNormalTurnout( + drawCmd_p d, + SCALEINX_T scaleInx, + BOOL_T omitTies, + wDrawColor color) +{ + tieData_p td; + DIST_T len; + coOrd pos; + int cnt; + ANGLE_T angle; + coOrd s1, s2, p1, p2, q1, q2; + int s0, p0, q0; + ANGLE_T a0; + + if (color == wDrawColorBlack) + color = tieColor; + + DIST_T trackGauge = GetTrkGauge(dtod.trk); + + DrawDtoInit(); + + // draw the points +#ifdef DTO_DEBUG + if (DTO_DEBUG == DTO_NORMAL) DrawDtoLayout(d, scaleInx); +#endif + + int strPath = dtod.strPath, othPath = 0, secPath = 1; + int toType = dtod.toType; + int first = 1; + + switch (toType) { + case DTO_NORMAL: + othPath = 1 - strPath; + secPath = strPath; + break; + case DTO_WYE: + // strPath = 2; + othPath = 0; secPath = 1; + break; + case DTO_THREE: + switch (strPath) { + case 0: + othPath = 1; secPath = 2; + break; + case 1: + othPath = 0; secPath = 2; + break; + case 2: + othPath = 0; secPath = 1; + break; + } + break; + } + + if(dtod.bridge) { + DrawTurnoutBridge(d,othPath,secPath); + } + if (omitTies) + return; + + // Straight vector for tie angle + if (toType == DTO_WYE) { + s1 = dto[othPath].pts[0]; + s2 = MidPtCoOrd(dto[othPath].ptsLast, dto[secPath].ptsLast); + } + else { + s1 = dto[strPath].pts[0]; + s2 = dto[strPath].ptsLast; + } + // Diverging vector(s) + p1 = dto[othPath].pts[0]; + p2 = dto[othPath].ptsLast; + q1 = dto[secPath].pts[0]; + q2 = dto[secPath].ptsLast; + + td = GetScaleTieData(scaleInx); + len = FindDistance(s1, s2); + angle = FindAngle(s1, s2); // The straight segment + + cnt = (int)floor(len / td->spacing + 0.5); + if (cnt > 0) { + int pn = dto[othPath].n; + int qn = dto[secPath].n; + DIST_T dx = len / cnt; + s0 = p0 = q0 = 0; + DIST_T tdlen = td->length; + DIST_T tdmax = (toType == DTO_WYE) ? 2.0 * tdlen : 2.5 * tdlen; + DIST_T px = len, dlenx = dx / 2; + + cnt = cnt > 1 ? cnt - 1 : 1; + for (px = dlenx; cnt; cnt--, px += dx) { + if (px >= dto[othPath].base[p0 + 1].x) p0++; + if (px >= dto[secPath].base[q0 + 1].x) q0++; + if (p0 >= pn || q0 >= qn) + break; + + if ((px + dx >= dto[othPath].baseLast.x) || (px + dx >= dto[secPath].baseLast.x)) { + break; + } + + DIST_T dy1 = dto[othPath].base[p0].y + (px - dto[othPath].base[p0].x) * dto[othPath].dy[p0]; + DIST_T dy2 = dto[secPath].base[q0].y + (px - dto[secPath].base[q0].x) * dto[secPath].dy[q0]; + tdlen = td->length + fabs(dy1) + fabs(dy2); + if (tdlen > tdmax) + break; + + DIST_T dy = dy1 + dy2; + Translate(&pos, s1, angle, px); + Translate(&pos, pos, (angle - 90.0), dy / 2); + + DrawTie(d, pos, angle, tdlen, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } + + // Asymmetric? Use longer ties for remaining two tracks (strPath, othPath) + DIST_T sx = px; // Save these values for second code block + int s0 = p0; + if((dtod.toType == DTO_THREE) && (px + dx >= dto[secPath].baseLast.x)){ + for ( ; cnt; cnt--, px += dx) { + if (px >= dto[othPath].base[p0 + 1].x) p0++; + // if (px >= dto[secPath].base[q0 + 1].x) q0++; + if (p0 >= pn) + break; + + if (px + dx >= dto[othPath].baseLast.x) { + break; + } + + DIST_T dy1 = dto[othPath].base[p0].y + (px - dto[othPath].base[p0].x) * dto[othPath].dy[p0]; + tdlen = td->length + fabs(dy1); + if (tdlen > tdmax) + break; + + DIST_T dy = dy1; + Translate(&pos, s1, angle, px); + Translate(&pos, pos, (angle - 90.0), dy / 2); + + DrawTie(d, pos, angle, tdlen, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } + } + + // Draw remaining ties, if any + if (px + dx < dto[othPath].baseLast.x){ + p1 = dto[othPath].pts[p0]; + p2 = dto[othPath].ptsLast; + angle = FindAngle(p1, p2); + a0 = FindAngle(dto[othPath].base[p0], dto[othPath].baseLast); + DIST_T lenr = (dto[othPath].baseLast.x - px + dlenx) / cos(D2R(90.0 - a0)); + Translate(&p1, p2, angle, -lenr); + DrawStraightTies(d, scaleInx, p1, p2, color); + } + else { + p1 = dto[othPath].pts[pn - 2]; + a0 = FindAngle(p1, p2); + Translate(&pos, p2, a0, -dx / 2); + DrawTie(d, pos, a0, td->length, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } + // Restore saved values + if(dtod.toType == DTO_THREE){ + px = sx; + p0 = s0; + } + + // Asymmetric? Use longer ties for remaining two tracks (strPath, secPath) + if((dtod.toType == DTO_THREE) && (px + dx >= dto[othPath].baseLast.x)){ + for ( ; cnt; cnt--, px += dx) { + // if (px >= dto[othPath].base[p0 + 1].x) p0++; + if (px >= dto[secPath].base[q0 + 1].x) q0++; + if (q0 >= qn) + break; + + if (px + dx >= dto[secPath].baseLast.x) { + break; + } + + DIST_T dy1 = dto[secPath].base[q0].y + (px - dto[secPath].base[q0].x) * dto[secPath].dy[q0]; + tdlen = td->length + fabs(dy1); + if (tdlen > tdmax) + break; + + DIST_T dy = dy1; + Translate(&pos, s1, angle, px); + Translate(&pos, pos, (angle - 90.0), dy / 2); + + DrawTie(d, pos, angle, tdlen, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } + } + if (px + dx < dto[secPath].baseLast.x) { + q1 = dto[secPath].pts[q0]; + q2 = dto[secPath].ptsLast; + angle = FindAngle(q1, q2); + a0 = FindAngle(dto[secPath].base[q0], dto[secPath].baseLast); + DIST_T lenr = (dto[secPath].baseLast.x - px + dlenx) / cos(D2R(90.0 - a0)); + Translate(&q1, q2, angle, -lenr); + DrawStraightTies(d, scaleInx, q1, q2, color); + } + else { + q1 = dto[secPath].pts[qn - 2]; + a0 = FindAngle(q1, q2); + Translate(&pos, q2, a0, -dx / 2); + DrawTie(d, pos, a0, td->length, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } + + // Final ties at end + if (dtod.toType == DTO_THREE) { + + int n = (int)(dto[strPath].baseLast.x); + if (px + dx < len) { + angle = FindAngle(s1, s2); + DIST_T lenr = len - px + dlenx; + Translate(&s1, s2, angle, -lenr); + DrawStraightTies(d, scaleInx, s1, s2, color); + } + else { + n = dto[strPath].n; + s1 = dto[strPath].pts[n - 2]; + a0 = FindAngle(s1, s2); + Translate(&pos, s2, a0, -dx / 2); + DrawTie(d, pos, a0, td->length, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } + } + } +} + +/** + * Draw Curved (Single Origin) Turnout Bridge and Ties. Uses the static dto and dtod structures. + * + * \param d The drawing object + * \param scaleInx The layout/track scale index + * \param color The tie color. If black the color is read from the global tieColor. + */ +static void DrawCurvedTurnout( + drawCmd_p d, + SCALEINX_T scaleInx, + BOOL_T omitTies, + wDrawColor color) +{ + tieData_p td; + DIST_T len, r; + coOrd pos; + int cnt; + ANGLE_T angle, dang; + coOrd center; + coOrd p1, p2, q1, q2; + ANGLE_T a0, a1, a2; + struct extraDataCompound_t* xx = dtod.xx; + + if (color == wDrawColorBlack) + color = tieColor; + + DrawDtoInit(); + + // draw the points +#ifdef DTO_DEBUG + if (DTO_DEBUG == DTO_CURVED) DrawDtoLayout(d, scaleInx); +#endif + + int othPath = 0, secPath = 1; + int toType = dtod.toType; + + if(dtod.bridge) { + DrawTurnoutBridge(d,othPath,secPath); + } + if (omitTies) + return; + + td = GetScaleTieData(scaleInx); + + // Save the ending coordinates + coOrd othEnd = zero, secEnd = zero; + + trkSeg_p trk; + DIST_T tdlen = td->length, tdmax = tdlen * 2.5; + DIST_T tdspc = td->spacing, tdspc2 = tdspc / 2.0; + double rdot = td->width / 2; + + int pn = dto[othPath].n; + int qn = dto[secPath].n; + int p0 = 0, q0 = 0; + DIST_T px = 0, qx = 0, dy = 0, dy1 = 0, dy2 = 0; + + double cosAdj = 1.0; + + angle = 0; + px = tdspc2; + qx = tdspc2; + int segs = max(dto[othPath].n, dto[secPath].n); + for (; segs > 0; segs--) { + + if (px >= dto[othPath].base[p0 + 1].x) + p0++; + if (qx >= dto[secPath].base[q0 + 1].x) + q0++; + if ((p0 >= pn - 1) || (q0 >= qn - 1)) { + break; + } + + trk = dto[othPath].trkSeg[p0]; + if (trk->type == SEG_CRVTRK) { + + center = trk->u.c.center; + r = fabs(trk->u.c.radius); + a0 = NormalizeAngle(trk->u.c.a0 + dtod.xx->angle); + a1 = trk->u.c.a1; + + pos = center; + REORIGIN(center, pos, xx->angle, xx->orig); + + len = r * D2R(a1); + cnt = (int)floor(len / tdspc + 0.5); + if (len - tdspc * cnt >= tdspc2) { + cnt++; + } + DIST_T tdlen = td->length; + DIST_T dx = len / cnt, dx2 = dx / 2; + + if (cnt != 0) { + dang = (len / cnt) * 360 / (2 * M_PI * r); + DIST_T dx = len / cnt, dx2 = dx / 2; + + if (dto[othPath].type == 'R') { + a2 = a0 + dang / 2; + } + else { + a2 = a0 + a1 - dang / 2; + dang = -dang; + } + angle += fabs(dang / 2); + + cosAdj = fabs(cos(D2R(angle))); + px += dx2 * cosAdj; + qx += dx2 * cosAdj; + + for (; cnt; cnt--, a2 += dang, angle += dang) { + if (px >= dto[othPath].base[p0 + 1].x) + p0++; + if (qx >= dto[secPath].base[q0 + 1].x) + q0++; + if ((p0 >= pn - 1) || (q0 >= qn - 1)) { + break; + } + + coOrd e1, e2; + PointOnCircle(&e1, center, r, a2); + + q1 = dto[secPath].pts[q0]; + q2 = dto[secPath].pts[q0 + 1]; + FindIntersection(&e2, e1, a2, q1, FindAngle(q1, q2)); + + dy = FindDistance(e1, e2); + DIST_T tlen = tdlen + dy; + + if (tlen > tdmax) { + break; + } + + Translate(&pos, e1, a2, -dy / 2); + DrawTie(d, pos, angle + xx->angle + 90, tlen, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + + // Assures that these ends are the last point drawn before break + othEnd = e1; + secEnd = e2; + + cosAdj = fabs(cos(D2R(angle))); + if (cnt > 1) { + px += dx * cosAdj; + qx += dx * cosAdj; + } + else { + px += dx2 * cosAdj; + qx += dx2 * cosAdj; + } + } + } + } + else { + cosAdj = fabs(cos(D2R(angle))); + + p1 = dto[othPath].base[p0]; + p2 = dto[othPath].base[p0 + 1]; + len = FindDistance(p1, p2); + cnt = (int)floor(len / tdspc + 0.6); + if (cnt > 0) { + DIST_T dx = len / cnt, dx2 = dx / 2; + + for (; cnt; cnt--) { + if (px >= dto[othPath].base[p0 + 1].x) + p0++; + if (qx >= dto[secPath].base[q0 + 1].x) + q0++; + if ((p0 >= pn - 1) || (q0 >= qn - 1)) { + break; + } + + p1 = dto[othPath].base[p0]; + p2 = dto[othPath].base[p0 + 1]; + + if ((px >= dto[othPath].baseLast.x) + || (qx >= dto[secPath].baseLast.x)) { + break; + } + + dy1 = dto[secPath].base[q0].y + (qx - dto[secPath].base[q0].x) * dto[secPath].dy[q0]; + dy2 = dto[othPath].base[p0].y + (px - dto[othPath].base[p0].x) * dto[othPath].dy[p0]; + dy = dy1 - dy2; + DIST_T tlen = tdlen + fabs(cosAdj * dy); + if (tlen > tdmax) { + break; + } + + q1 = dto[secPath].pts[q0]; + q2 = dto[secPath].pts[q0 + 1]; + a1 = FindAngle(q1, q2); + DIST_T xlen = qx - dto[secPath].base[q0].x; + Translate(&pos, q1, a1, xlen); + secEnd = pos; + + q1 = dto[othPath].pts[p0]; + q2 = dto[othPath].pts[p0 + 1]; + a1 = FindAngle(q1, q2); + xlen = px - dto[othPath].base[p0].x; + Translate(&pos, q1, a1, xlen); + othEnd = pos; + + Translate(&pos, pos, (a1 - 90.0), dy / 2); + DrawTie(d, pos, a1, tlen, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + + cosAdj = fabs(cos(D2R(angle))); + px += dx * cosAdj; + qx += dx * cosAdj; + } + } + else { + break; + } + } + } + +#ifdef DTO_DEBUG + if (DTO_DEBUG == DTO_CURVED) { + DrawFillCircle(d, othEnd, rdot, drawColorGreen); + DrawFillCircle(d, secEnd, rdot, drawColorGreen); + + DrawFillCircle(d, dto[othPath].pts[p0], rdot, drawColorBlue); + DrawFillCircle(d, dto[secPath].pts[q0], rdot, drawColorBlue); + } +#endif + + // Draw remaining ties, if any + p1 = othEnd; + p2 = dto[othPath].ptsLast; + a0 = FindAngle(p1, p2); + len = FindDistance(p1, p2); + if (len >= 2 * tdspc) { + Translate(&p1, p1, a0, tdspc2); + DrawStraightTies(d, scaleInx, p1, p2, color); + } + else if (len > tdspc2) { + Translate(&p2, p2, a0, -tdspc2); + DrawTie(d, p2, a0, td->length, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } + + q1 = secEnd; + q2 = dto[secPath].ptsLast; + a0 = FindAngle(q1, q2); + len = FindDistance(q1, q2); + if (len >= 2 * tdspc) { + Translate(&q1, q1, a0, tdspc2); + DrawStraightTies(d, scaleInx, q1, q2, color); + } + else if (len > tdspc2) { + Translate(&q2, q2, a0, -tdspc2); + DrawTie(d, q2, a0, td->length, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } +} + +/** + * Draw Crossing and Slip Turnout Bridge and Ties - Uses the static dto and dtod structures. + * + * \param d The drawing object + * \param scaleInx The layout/track scale index + * \param color The tie color. If black the color is read from the global tieColor. + */ +static void DrawXingTurnout( + drawCmd_p d, + SCALEINX_T scaleInx, + BOOL_T omitTies, + wDrawColor color) +{ + tieData_p td; + DIST_T len; + coOrd pos; + int cnt; + ANGLE_T cAngle; + + if (color == wDrawColorBlack) + color = tieColor; + + coOrd c1, c2, s1, s2, p1, p2, q1; + int p0, q0; + ANGLE_T a0, a1, a2; + int strPath = dtod.strPath, str2Path = dtod.str2Path; + + struct extraDataCompound_t* xx = dtod.xx; + + DrawDtoInit(); + + dto[strPath].angle = FindAngle(dto[strPath].pts[0], dto[strPath].ptsLast); + dto[str2Path].angle = FindAngle(dto[str2Path].pts[0], dto[str2Path].ptsLast); + + int othPath = strPath, secPath = str2Path; + int toType = dtod.toType; + + int i, j; + switch (toType) { + case DTO_XING: + case DTO_XNG9: + break; + case DTO_SSLIP: + for (i = 0; i < dtod.pathCnt; i++) { + if (dto[i].type == 'L' || dto[i].type == 'R') { + secPath = i; + break; + } + } + break; + case DTO_DSLIP: + for (i = 0; i < dtod.pathCnt; i++) { + if (dto[i].type == 'L') { + othPath = i; + } + else if (dto[i].type == 'R') { + secPath = i; + } + } + break; + } + + if(dtod.bridge) { + DrawXingBridge(d,othPath,secPath); + } + // draw the points +#ifdef DTO_DEBUG + if (DTO_DEBUG == DTO_XING) DrawDtoLayout(d, scaleInx); +#endif + + if (omitTies) + return; + + td = GetScaleTieData(scaleInx); + DIST_T tdlen = td->length, tdmax = 2.0 * tdlen; + DIST_T tdspc = td->spacing, tdspc2 = tdspc / 2; + + // Midpoint + p1 = dto[strPath].pts[0]; + a1 = dto[strPath].angle; + + q1 = dto[str2Path].pts[0]; + a2 = dto[str2Path].angle; + + FindIntersection(&pos, p1, a1, q1, a2); + dtod.midPt = pos; + +#ifdef DTO_DEBUG + if(DTO_DEBUG == DTO_XING) + { + double r = td->width / 2; + DrawFillCircle(d,p1,r,drawColorPurple); + DrawFillCircle(d,q1,r,drawColorPurple); + DrawFillCircle(d,dtod.midPt,r,drawColorPurple); + } +#endif + + // Tie length adjust + double dAngle = fabs(DifferenceBetweenAngles(a1, a2)); + double magic = 1.0; + + // Short circuit the complex code for this simple case + if (toType == DTO_XNG9) { + p1 = dto[strPath].pts[0]; + p2 = dto[strPath].ptsLast; + DrawStraightTies(d, scaleInx, p1, p2, color); + + p1 = dto[str2Path].pts[0]; + p2 = dto[str2Path].ptsLast; + + // Omit the center ties + magic = 1 / cos(D2R(90 - dAngle)); + DIST_T tdadj = (tdlen / 2) * magic; + DIST_T tdadj2 = tdspc2 * magic; + + dAngle = (dAngle - 90) / 2; + Translate(&pos, dtod.midPt, a2, -tdadj - tdadj2); + DrawTie(d, pos, a2 - dAngle, tdlen, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + + Translate(&pos, dtod.midPt, a2, -tdadj - tdspc); + DrawStraightTies(d, scaleInx, p1, pos, color); + + Translate(&pos, dtod.midPt, a2, tdadj + tdadj2); + DrawTie(d, pos, a2 - dAngle, tdlen, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + + Translate(&pos, dtod.midPt, a2, tdadj + tdspc); + DrawStraightTies(d, scaleInx, pos, p2, color); + return; + } + + // Straight vector for tie angle + s1 = MidPtCoOrd(dto[strPath].base[0], dto[str2Path].base[0]); + s2 = MidPtCoOrd(dto[strPath].baseLast, dto[str2Path].baseLast); + + // Rotate base coordinates so that the tie line is aligned with x-axis and origin is at zero + cAngle = FindAngle(s1, s2); + for (i = 0; i < DTO_DIM; i++) + for (j = 0; j < dto[i].n; j++) { + dto[i].base[j].x -= s1.x; + dto[i].base[j].y -= s1.y; + Rotate(&dto[i].base[j], zero, (90.0 - cAngle)); + } + + for (i = 0; i < DTO_DIM; i++) { + for (j = 0; j < dto[i].n - 1; j++) { + dto[i].dy[j] = (dto[i].base[j + 1].y - dto[i].base[j].y) / (dto[i].base[j + 1].x - dto[i].base[j].x); + } + if (dto[i].type == 'S') + dto[i].angle = FindAngle(dto[i].pts[0], dto[i].ptsLast); + } + + // Tie center line in drawing coordinates + REORIGIN(c1, s1, xx->angle, xx->orig); + REORIGIN(c2, s2, xx->angle, xx->orig); + cAngle = FindAngle(c1, c2); + + int pn = dto[othPath].n; + int qn = dto[secPath].n; + + // Tie length adjust + magic = 1 / cos(0.5 * D2R(dAngle)); + // Extra ties length adjust + double magic2 = 1.0 / cos(0.5 * D2R(dAngle)); + + // Draw right half + len = FindDistance(dtod.midPt, c2); + cnt = (int)floor(len / td->spacing + 0.5); + if (cnt <= 0) + return; + + DIST_T dx = len / cnt; + p0 = q0 = 0; + DIST_T dx2 = dx / 2; + DIST_T px = len + dx2; + DIST_T lenx = 0; + + while (p0 < pn && px > dto[othPath].base[p0 + 1].x) p0++; + while (q0 < qn && px > dto[secPath].base[q0 + 1].x) q0++; + while (p0 < pn && q0 < qn) { + if (px > dto[othPath].base[p0 + 1].x) p0++; + if (px > dto[secPath].base[q0 + 1].x) q0++; + if (p0 >= pn || q0 >= qn) + break; + // Dont use baseLast, as base coOrds have been rotated + if ((px + dx >= dto[othPath].base[pn - 1].x) + || (px + dx >= dto[secPath].base[qn - 1].x)) { + break; + } + + DIST_T dy1 = dto[othPath].base[p0].y + (px - dto[othPath].base[p0].x) * dto[othPath].dy[p0]; + DIST_T dy2 = dto[secPath].base[q0].y + (px - dto[secPath].base[q0].x) * dto[secPath].dy[q0]; + tdlen = (td->length + fabs(dy1) + fabs(dy2)) * magic; + if(tdlen > tdmax) + { + if(dAngle >= 30) + { + DIST_T dy = (dy1 + dy2) / 2; + Translate(&pos,dtod.midPt,cAngle,px - len); + Translate(&pos,pos,(cAngle - 90.0),dy); + DrawTie(d,pos,cAngle,tdlen - td->length * magic,td->width,color,tieDrawMode == TIEDRAWMODE_SOLID); + lenx += dx2 * magic2; + } + break; + } + + DIST_T dy = (dy1 + dy2) / 2; + Translate(&pos, dtod.midPt, cAngle, px - len); + Translate(&pos, pos, (cAngle - 90.0), dy); + DrawTie(d, pos, cAngle, tdlen, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + + px += dx; + lenx += dx; + } + + p1 = dtod.midPt; + p2 = dto[strPath].ptsLast; + DIST_T lenr = FindDistance(p1, p2) - lenx * magic2; + a0 = dto[strPath].angle; + if (lenr > dx) { + Translate(&pos, p2, a0, -lenr); + DrawStraightTies(d, scaleInx, pos, p2, color); + } + else { + Translate(&pos, p2, a0, -dx2); + DrawTie(d, pos, a0, td->length, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } + + // p1 = dtod.midPt; + p2 = dto[str2Path].ptsLast; + lenr = FindDistance(p1, p2) - lenx * magic2; + a0 = dto[str2Path].angle; + if (lenr > dx) { + Translate(&pos, p2, a0, -lenr); + DrawStraightTies(d, scaleInx, pos, p2, color); + } + else { + Translate(&pos, p2, a0, -dx2); + DrawTie(d, pos, a0, td->length, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } + + // Draw left half + // Change the straight path used + if (dtod.toType == DTO_SSLIP) { + othPath = str2Path; + } + + len = FindDistance(c1, dtod.midPt); + cnt = (int)floor(len / td->spacing + 0.5); + if (cnt <= 0) + return; + + p0 = q0 = 0; + tdlen = td->length; + + dx = len / cnt; + dx2 = dx / 2; + px = len - dx2; + lenx = 0; + + while (p0 < pn && px > dto[othPath].base[p0 + 1].x) p0++; + while (q0 < qn && px > dto[secPath].base[q0 + 1].x) q0++; + while (p0 >= 0 && q0 >= 0) { + if (px < dto[othPath].base[p0].x) p0--; + if (px < dto[secPath].base[q0].x) q0--; + if (p0 < 0 || q0 < 0) + break; + + if ((px - dx < dto[othPath].base[0].x) + || (px - dx < dto[secPath].base[0].x)) { + break; + } + + DIST_T dy1 = dto[othPath].base[p0].y + (px - dto[othPath].base[p0].x) * dto[othPath].dy[p0]; + DIST_T dy2 = dto[secPath].base[q0].y + (px - dto[secPath].base[q0].x) * dto[secPath].dy[q0]; + tdlen = (td->length + fabs(dy1) + fabs(dy2)) * magic; + if(tdlen > tdmax) + { + if(dAngle >= 30) + { + DIST_T dy = (dy1 + dy2) / 2; + Translate(&pos,dtod.midPt,cAngle,px - len); + Translate(&pos,pos,(cAngle - 90.0),dy); + DrawTie(d,pos,cAngle,tdlen - td->length * magic,td->width,color,tieDrawMode == TIEDRAWMODE_SOLID); + lenx += dx2 * magic2; + } + break; + } + + DIST_T dy = (dy1 + dy2) / 2; + Translate(&pos, dtod.midPt, cAngle, px - len); + Translate(&pos, pos, (cAngle - 90.0), dy); + DrawTie(d, pos, cAngle, tdlen, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + + px -= dx; + lenx += dx; + } + + p1 = dto[strPath].pts[0]; + p2 = dtod.midPt; + a0 = dto[strPath].angle; + lenr = FindDistance(p1, p2) - lenx * magic2; + if (lenr > dx) { + Translate(&pos, p1, a0, lenr); + DrawStraightTies(d, scaleInx, p1, pos, color); + } + else { + Translate(&pos, p1, a0, dx2); + DrawTie(d, pos, a0, td->length, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } + p1 = dto[str2Path].pts[0]; + // p2 = dtod.midPt; + a0 = dto[str2Path].angle; + lenr = FindDistance(p1, p2) - lenx * magic2; + if (lenr > dx) { + Translate(&pos, p1, a0, lenr); + DrawStraightTies(d, scaleInx, p1, pos, color); + } + else { + Translate(&pos, p1, a0, dx2); + DrawTie(d, pos, a0, td->length, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } +} + +/** + * Draw Crossover (Two Origin) Turnout Bridge and Ties. Uses the static dto and dtod structures. + * + * \param d The drawing object + * \param scaleInx The layout/track scale index + * \param color The tie color. If black the color is read from the global tieColor. + */ +static void DrawCrossTurnout( + drawCmd_p d, + SCALEINX_T scaleInx, + BOOL_T omitTies, + wDrawColor color) +{ + tieData_p td; + DIST_T len, dx; + coOrd pos; + int cnt; + ANGLE_T angle; + + if (color == wDrawColorBlack) + color = tieColor; + + struct extraDataCompound_t* xx = dtod.xx; + + DrawDtoInit(); + + // draw the points +#ifdef DTO_DEBUG + if (DTO_DEBUG == DTO_LCROSS) DrawDtoLayout(d, scaleInx); +#endif + + int strPath = dtod.strPath, str2Path = dtod.str2Path; + // Bad assumption + int othPath = 2, secPath = 2; + if (dtod.pathCnt == 4) secPath = 3; + + dto[strPath].angle = FindAngle(dto[strPath].pts[0], dto[strPath].ptsLast); + dto[str2Path].angle = FindAngle(dto[str2Path].pts[0], dto[str2Path].ptsLast); + + if(dtod.bridge) { + DrawCrossBridge(d,strPath,str2Path); + } + if (omitTies) + return; + + td = GetScaleTieData(scaleInx); + + coOrd s1, s2, t1, t2, p1, p2, q1, q2; + int s0, t0, p0, q0; + + int sn = dto[strPath].n; + int tn = dto[str2Path].n; + int pn = dto[othPath].n; + int qn = dto[secPath].n; + + s1 = dto[strPath].pts[0]; + s2 = dto[strPath].ptsLast; + t1 = dto[str2Path].pts[0]; + t2 = dto[str2Path].ptsLast; + angle = dto[strPath].angle; + + p1 = dto[othPath].base[0]; + p2 = dto[othPath].baseLast; + q1 = dto[secPath].base[0]; + q2 = dto[secPath].baseLast; + + td = GetScaleTieData(scaleInx); + len = FindDistance(s1, s2); + angle = dto[strPath].angle; + + cnt = (int)floor(len / td->spacing + 0.5); + if (cnt > 0) { + DIST_T px = 0; + DIST_T dy, dy1, dy2; + int cflag = 0; + dy = dto[str2Path].base[0].y - dto[strPath].base[0].y; + + dx = len / cnt; + s0 = t0 = p0 = q0 = 0; + DIST_T tdlen = td->length; + DIST_T dlenx = dx / 2; + + DIST_T px1 = len / 2 - dlenx * 5, + px2 = len / 2 + dlenx * 4; + + for (px = dlenx; cnt; cnt--, px += dx) { + if (px >= dto[strPath].base[s0 + 1].x) s0++; + if (px >= dto[str2Path].base[t0 + 1].x) t0++; + if (px >= dto[othPath].base[p0 + 1].x) p0++; + if (px >= dto[secPath].base[q0 + 1].x) q0++; + if (s0 >= sn || t0 >= tn || p0 >= pn || q0 >= qn) + break; + + if ((px >= dto[strPath].baseLast.x) + || (px >= dto[str2Path].baseLast.x)) { + break; + } + + dy1 = dy2 = 0; + cflag = 0; + if (px < px1) { + switch (dtod.toType) { + case DTO_DCROSS: + dy1 = dto[othPath].base[p0].y + (px - dto[othPath].base[p0].x) * dto[othPath].dy[p0]; + dy2 = dy - dto[secPath].base[q0].y - (px - dto[secPath].base[q0].x) * dto[secPath].dy[q0]; + break; + case DTO_LCROSS: + dy1 = dto[othPath].base[p0].y + (px - dto[othPath].base[p0].x) * dto[othPath].dy[p0]; + dy2 = 0; + break; + case DTO_RCROSS: + dy1 = 0; + dy2 = dy - dto[secPath].base[q0].y - (px - dto[secPath].base[q0].x) * dto[secPath].dy[q0]; + break; + default: + break; + } + } + else if (px < px2) { + dy1 = (dto[str2Path].base[s0].y - dto[strPath].base[t0].y); + dy2 = 0; + cflag = 1; + } + else { + switch (dtod.toType) { + case DTO_DCROSS: + dy1 = dto[secPath].base[q0].y + (px - dto[secPath].base[q0].x) * dto[secPath].dy[q0]; + dy2 = dy - dto[othPath].base[p0].y - (px - dto[othPath].base[p0].x) * dto[othPath].dy[p0]; + break; + case DTO_LCROSS: + dy1 = 0; + dy2 = dy - dto[secPath].base[q0].y - (px - dto[secPath].base[q0].x) * dto[secPath].dy[q0]; + break; + case DTO_RCROSS: + dy1 = dto[othPath].base[p0].y + (px - dto[othPath].base[p0].x) * dto[othPath].dy[p0]; + dy2 = 0; + break; + default: + break; + } + } + + if (fabs(dy1) + fabs(dy2) >= dy) { + dy1 = (dto[str2Path].base[s0].y - dto[strPath].base[t0].y); + dy2 = 0; + cflag = 1; + } + + tdlen = td->length + fabs(dy1); + Translate(&pos, s1, angle, px); + Translate(&pos, pos, (angle - 90.0), dy1 / 2); + DrawTie(d, pos, angle, tdlen, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + + if (!cflag) { + tdlen = td->length + fabs(dy2); + Translate(&pos, t1, angle, px); + Translate(&pos, pos, (angle - 90.0), -dy2 / 2); + DrawTie(d, pos, angle, tdlen, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } + } + return; + + // Draw remaining ties, if any + // Currently by definition, there won't be any + /* + if (px + dx < dto[strPath].baseLast.x) { + p1 = dto[strPath].pts[p0]; + p2 = dto[strPath].ptsLast; + angle = FindAngle(p1, p2); + a0 = FindAngle(dto[strPath].base[p0], dto[strPath].baseLast); + DIST_T lenr = (dto[strPath].baseLast.x - px + dlenx) / cos(D2R(90.0 - a0)); + Translate(&p1, p2, angle, -lenr); + DrawStraightTies(d, scaleInx, p1, p2, color); + } + else { + p1 = dto[strPath].pts[pn - 2]; + a0 = FindAngle(p1, p2); + Translate(&pos, p2, a0, -dx / 2); + DrawTie(d, pos, a0, td->length, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } + + if (px + dx < dto[str2Path].baseLast.x) { + q1 = dto[str2Path].pts[q0]; + q2 = dto[str2Path].ptsLast; + angle = FindAngle(q1, q2); + a0 = FindAngle(dto[str2Path].base[q0], dto[str2Path].baseLast); + DIST_T lenr = (dto[str2Path].baseLast.x - px + dlenx) / cos(D2R(90.0 - a0)); + Translate(&q1, q2, angle, -lenr); + DrawStraightTies(d, scaleInx, q1, q2, color); + } + else { + q1 = dto[str2Path].pts[qn - 2]; + a0 = FindAngle(q1, q2); + Translate(&pos, q2, a0, -dx / 2); + DrawTie(d, pos, a0, td->length, td->width, color, tieDrawMode == TIEDRAWMODE_SOLID); + } + */ + } +} + +/** + * Draw all turnout components: ties, rail, roadbed, etc. The turnout is checked + * to see if the enhanced methods can be used. If so the ties are drawn and the + * TB_NOTIES bit is set so that the rails and such are drawn on top of the ties. + * That bit is restored to its previous state before return. + * + * \param trk Pointer to the track object + * \param d The drawing object + * \param color The turnout color. + */ static void DrawTurnout( - track_p trk, - drawCmd_p d, - wDrawColor color ) + track_p trk, + drawCmd_p d, + wDrawColor color) { - struct extraData *xx = GetTrkExtraData(trk); + struct extraDataCompound_t* xx = GET_EXTRA_DATA(trk, T_TURNOUT, extraDataCompound_t); wIndex_t i; long widthOptions = 0; - DIST_T scale2rail; + SCALEINX_T scaleInx = GetTrkScale(trk); + DIST_T scale2rail = (d->options & DC_PRINT) ? (twoRailScale * 2 + 1) : twoRailScale; + BOOL_T omitTies = !DoDrawTies(d, trk) || (d->scale > scale2rail) || ((d->options & DC_SIMPLE) != 0); // || (scaleInx == 0); + + widthOptions = DTS_LEFT | DTS_RIGHT; + + int noTies = GetTrkNoTies(trk); + int bridge = GetTrkBridge(trk); + + long skip = 0; + /** @prefs [Preference] NormalTurnoutDraw=1 to skip enhanced drawing methods */ + wPrefGetInteger("Preference", "NormalTurnoutDraw", (long *) &skip, 0); + + int pathCnt = (skip == 0 ? GetTurnoutPaths(trk, xx) : 0); + + if ( (pathCnt > 1) && (pathCnt <= DTO_DIM) + && (trk->endCnt <= 4) + && (xx->special == TOnormal) ) + { + + dtod.bridge = bridge; + + int strPath = -1; + GetTurnoutType(); + + if (dtod.toType != DTO_INVALID) { + + switch (dtod.toType) + { + case DTO_NORMAL: + case DTO_THREE: + case DTO_WYE: + DrawNormalTurnout(d, scaleInx, omitTies, color); + break; + case DTO_CURVED: + DrawCurvedTurnout(d, scaleInx, omitTies, color); + break; + case DTO_XING: + case DTO_XNG9: + case DTO_SSLIP: + case DTO_DSLIP: + DrawXingTurnout(d, scaleInx, omitTies, color); + break; + case DTO_LCROSS: + case DTO_RCROSS: + case DTO_DCROSS: + DrawCrossTurnout(d, scaleInx, omitTies, color); + break; + default: + break; + } + SetTrkNoTies(trk, 1); + ClrTrkBits(trk, TB_BRIDGE); + } + } - widthOptions = DTS_LEFT|DTS_RIGHT; - - scale2rail = (d->options&DC_PRINT)?(twoRailScale*2+1):twoRailScale; - DrawSegsO( d, trk, xx->orig, xx->angle, xx->segs, xx->segCnt, GetTrkGauge(trk), color, widthOptions | DTS_NOCENTER ); // no curve center for turnouts + // Begin standard DrawTurnout code to draw rails or centerline + DrawSegsO(d, trk, xx->orig, xx->angle, xx->segs, xx->segCnt, GetTrkGauge(trk), color, widthOptions | DTS_NOCENTER); // no curve center for turnouts - for (i=0; i<GetTrkEndPtCnt(trk); i++) { - DrawEndPt( d, trk, i, color ); + for (i = 0; i < GetTrkEndPtCnt(trk); i++) { + DrawEndPt(d, trk, i, color); } - if ( (d->options & DC_SIMPLE) == 0 && - (labelWhen == 2 || (labelWhen == 1 && (d->options&DC_PRINT))) && - labelScale >= d->scale && - ( GetTrkBits( trk ) & TB_HIDEDESC ) == 0 ) { - DrawCompoundDescription( trk, d, color ); + if ((d->options & DC_SIMPLE) == 0 && + (labelWhen == 2 || (labelWhen == 1 && (d->options & DC_PRINT))) && + labelScale >= d->scale && + (GetTrkBits(trk) & TB_HIDEDESC) == 0) { + DrawCompoundDescription(trk, d, color); if (!xx->handlaid) - LabelLengths( d, trk, color ); + LabelLengths(d, trk, color); } - if ( roadbedWidth > GetTrkGauge(trk) && - ( ((d->options&DC_PRINT) && d->scale <= (twoRailScale*2+1)/2.0) || - (roadbedOnScreen && d->scale <= twoRailScale) ) ) - DrawTurnoutRoadbed( d, color, xx->orig, xx->angle, xx->segs, xx->segCnt ); - + if (roadbedWidth > GetTrkGauge(trk) && + (((d->options & DC_PRINT) && d->scale <= (twoRailScale * 2 + 1) / 2.0) || + (roadbedOnScreen && d->scale <= twoRailScale))) + DrawTurnoutRoadbed(d, color, xx->orig, xx->angle, xx->segs, xx->segCnt); + + // Restore these settings + if (noTies == 0) ClrTrkBits(trk, TB_NOTIES); + if (bridge) SetTrkBits(trk, TB_BRIDGE); } static BOOL_T ReadTurnout( - char * line ) + char* line) { - if ( !ReadCompound( line+8, T_TURNOUT ) ) + if (!ReadCompound(line + 8, T_TURNOUT)) return FALSE; return TRUE; } static ANGLE_T GetAngleTurnout( - track_p trk, - coOrd pos, - EPINX_T *ep0, - EPINX_T *ep1 ) + track_p trk, + coOrd pos, + EPINX_T* ep0, + EPINX_T* ep1) { - struct extraData * xx = GetTrkExtraData(trk); + struct extraDataCompound_t* xx = GET_EXTRA_DATA(trk, T_TURNOUT, extraDataCompound_t); wIndex_t segCnt, segInx; ANGLE_T angle; - if ( ep0 && ep1 ) - *ep0 = *ep1 = PickEndPoint( pos, trk ); - coOrd pos0=pos; - double dd = 10000.0; + if (ep0 && ep1) + *ep0 = *ep1 = PickEndPoint(pos, trk); + coOrd pos0 = pos; + double dd = DIST_INF; int found = -1; //Cope with tracks not being first - for (segCnt =0; segCnt<xx->segCnt ; segCnt++ ) { + for (segCnt = 0; segCnt < xx->segCnt; segCnt++) { if (IsSegTrack(&xx->segs[segCnt])) { - double d = DistanceSegs( xx->orig, xx->angle, 1, &xx->segs[segCnt], &pos0, NULL ); - if (d<dd) { + double d = DistanceSegs(xx->orig, xx->angle, 1, &xx->segs[segCnt], &pos0, NULL); + if (d < dd) { dd = d; found = segCnt; } } pos0 = pos; } - if (found>=0) { + if (found >= 0) { pos.x -= xx->orig.x; pos.y -= xx->orig.y; - Rotate( &pos, zero, -xx->angle ); - angle = GetAngleSegs( 1, &xx->segs[found], &pos, &segInx, NULL, NULL, NULL, NULL ); - return NormalizeAngle( angle+xx->angle ); - } else return 0.0; + Rotate(&pos, zero, -xx->angle); + angle = GetAngleSegs(1, &xx->segs[found], &pos, &segInx, NULL, NULL, NULL, NULL); + return NormalizeAngle(angle + xx->angle); + } + else return 0.0; } static BOOL_T SplitTurnoutCheckPath( - wIndex_t segInxEnd, - PATHPTR_T pp1, - int dir1, - PATHPTR_T pp2, - int dir2, - trkSeg_p segs, - coOrd epPos ) + wIndex_t segInxEnd, + PATHPTR_T pp1, + int dir1, + PATHPTR_T pp2, + int dir2, + trkSeg_p segs, + coOrd epPos) { wIndex_t segInx1, segInx2; EPINX_T segEP; coOrd pos; DIST_T dist; - GetSegInxEP( pp2[0], &segInx2, &segEP ); - if ( dir2 < 0 ) segEP = 1-segEP; - pos = GetSegEndPt( &segs[segInx2], segEP, FALSE, NULL ); - dist = FindDistance( pos, epPos ); - if ( dist>connectDistance ) + GetSegInxEP(pp2[0], &segInx2, &segEP); + if (dir2 < 0) segEP = 1 - segEP; + pos = GetSegEndPt(&segs[segInx2], segEP, FALSE, NULL); + dist = FindDistance(pos, epPos); + if (dist > connectDistance) return TRUE; - while ( pp2[0] ) { - GetSegInxEP( pp1[0], &segInx1, &segEP ); - GetSegInxEP( pp2[0], &segInx2, &segEP ); - if ( segInx1 != segInx2 ) + while (pp2[0]) { + GetSegInxEP(pp1[0], &segInx1, &segEP); + GetSegInxEP(pp2[0], &segInx2, &segEP); + if (segInx1 != segInx2) break; - if ( segInxEnd == segInx2 ) + if (segInxEnd == segInx2) return TRUE; pp1 += dir1; pp2 += dir2; @@ -882,21 +2763,21 @@ static BOOL_T SplitTurnoutCheckPath( static BOOL_T SplitTurnoutCheckEP( - wIndex_t segInx0, - coOrd epPos, - PATHPTR_T pp1, - int dir1, - PATHPTR_T pp, - trkSeg_p segs ) -{ - while ( pp[0] ) { - pp += strlen((char *)pp)+1; - while ( pp[0] ) { - if (!SplitTurnoutCheckPath( segInx0, pp1, dir1, pp, 1, segs, epPos )) + wIndex_t segInx0, + coOrd epPos, + PATHPTR_T pp1, + int dir1, + PATHPTR_T pp, + trkSeg_p segs) +{ + while (pp[0]) { + pp += strlen((char*)pp) + 1; + while (pp[0]) { + if (!SplitTurnoutCheckPath(segInx0, pp1, dir1, pp, 1, segs, epPos)) return FALSE; - while ( pp[0] ) + while (pp[0]) pp++; - if (!SplitTurnoutCheckPath( segInx0, pp1, dir1, pp-1, -1, segs, epPos )) + if (!SplitTurnoutCheckPath(segInx0, pp1, dir1, pp - 1, -1, segs, epPos)) return FALSE; pp++; } @@ -907,11 +2788,11 @@ static BOOL_T SplitTurnoutCheckEP( EXPORT EPINX_T TurnoutPickEndPt( - coOrd epPos, - track_p trk ) + coOrd epPos, + track_p trk) { - struct extraData * xx = GetTrkExtraData(trk); - wIndex_t segCnt, segInx, segInx0; + struct extraDataCompound_t* xx = GET_EXTRA_DATA(trk, T_TURNOUT, extraDataCompound_t); + wIndex_t segInx, segInx0; EPINX_T segEP; PATHPTR_T cp, cq, pps[2]; coOrd pos; @@ -920,38 +2801,37 @@ EXPORT EPINX_T TurnoutPickEndPt( EPINX_T ep, epCnt, eps[2]; BOOL_T unique_eps[2]; - for ( segCnt=0; segCnt<xx->segCnt && IsSegTrack(&xx->segs[segCnt]); segCnt++ ); - DistanceSegs( xx->orig, xx->angle, segCnt, xx->segs, &epPos, &segInx0 ); - Rotate( &epPos, xx->orig, xx->angle ); + DistanceSegs(xx->orig, xx->angle, xx->segCnt, xx->segs, &epPos, &segInx0); + Rotate(&epPos, xx->orig, xx->angle); epPos.x -= xx->orig.x; epPos.y -= xx->orig.y; epCnt = GetTrkEndPtCnt(trk); - cp = xx->paths; + cp = GetPaths(trk); eps[0] = eps[1] = -1; unique_eps[0] = unique_eps[1] = TRUE; - while ( cp[0] ) { - cp += strlen((char *)cp)+1; - while ( cp[0] ) { - while ( cp[0] ) { - GetSegInxEP( cp[0], &segInx, &segEP ); - if ( segInx == segInx0 ) { - for ( dir=0; dir<2; dir++ ) { - for ( cq=cp; cq[dir?-1:1]; cq += (dir?-1:1) ); - GetSegInxEP( cq[0], &segInx, &segEP ); - if ( dir==0 ) segEP = 1-segEP; - pos = GetSegEndPt( &xx->segs[segInx], segEP, FALSE, NULL ); - dist = FindDistance( pos, epPos ); - if ( eps[dir] < 0 || dist < dists[dir] ) { + while (cp[0]) { + cp += strlen((char*)cp) + 1; + while (cp[0]) { + while (cp[0]) { + GetSegInxEP(cp[0], &segInx, &segEP); + if (segInx == segInx0) { + for (dir = 0; dir < 2; dir++) { + for (cq = cp; cq[dir ? -1 : 1]; cq += (dir ? -1 : 1)); + GetSegInxEP(cq[0], &segInx, &segEP); + if (dir == 0) segEP = 1 - segEP; + pos = GetSegEndPt(&xx->segs[segInx], segEP, FALSE, NULL); + dist = FindDistance(pos, epPos); + if (eps[dir] < 0 || dist < dists[dir]) { dists[dir] = dist; pos.x += xx->orig.x; pos.y += xx->orig.y; - Rotate( &pos, xx->orig, xx->angle ); - for ( ep=0; ep<epCnt; ep++ ) { - if ( FindDistance( pos, GetTrkEndPos(trk,ep) ) < connectDistance ) + Rotate(&pos, xx->orig, xx->angle); + for (ep = 0; ep < epCnt; ep++) { + if (FindDistance(pos, GetTrkEndPos(trk, ep)) < connectDistance) break; } - if ( ep<epCnt ) { - if ( eps[dir] >= 0 && eps[dir] != ep ) + if (ep < epCnt) { + if (eps[dir] >= 0 && eps[dir] != ep) unique_eps[dir] = FALSE; eps[dir] = ep; dists[dir] = dist; @@ -967,27 +2847,27 @@ EXPORT EPINX_T TurnoutPickEndPt( cp++; } - for ( dir=0; dir<2; dir++ ) { - if ( unique_eps[dir] && eps[dir] >= 0 ) { - GetSegInxEP( pps[dir][0], &segInx, &segEP ); - if ( dir == 0 ) segEP = 1-segEP; - epPos = GetSegEndPt( &xx->segs[segInx], segEP, FALSE, NULL ); - if ( ! SplitTurnoutCheckEP( segInx0, epPos, pps[dir], dir?1:-1, xx->paths, xx->segs ) ) - unique_eps[dir] = FALSE; + for (dir = 0; dir < 2; dir++) { + if (unique_eps[dir] && eps[dir] >= 0) { + GetSegInxEP(pps[dir][0], &segInx, &segEP); + if (dir == 0) segEP = 1 - segEP; + epPos = GetSegEndPt(&xx->segs[segInx], segEP, FALSE, NULL); + if (!SplitTurnoutCheckEP(segInx0, epPos, pps[dir], dir ? 1 : -1, GetPaths(trk), xx->segs)) + unique_eps[dir] = FALSE; } } - if ( unique_eps[0] == unique_eps[1] ) { - if ( eps[0] >= 0 && eps[1] >= 0 ) - return ( dists[0] < dists[1] ) ? eps[0] : eps[1] ; + if (unique_eps[0] == unique_eps[1]) { + if (eps[0] >= 0 && eps[1] >= 0) + return (dists[0] < dists[1]) ? eps[0] : eps[1]; } - if ( unique_eps[0] && eps[0] >= 0 ) + if (unique_eps[0] && eps[0] >= 0) return eps[0]; - if ( unique_eps[1] && eps[1] >= 0 ) + if (unique_eps[1] && eps[1] >= 0) return eps[1]; - if ( eps[0] >= 0 && eps[1] >= 0 ) - return ( dists[0] < dists[1] ) ? eps[0] : eps[1] ; - return eps[0] >= 0 ? eps[0] : eps[1] ; + if (eps[0] >= 0 && eps[1] >= 0) + return (dists[0] < dists[1]) ? eps[0] : eps[1]; + return eps[0] >= 0 ? eps[0] : eps[1]; } @@ -996,11 +2876,11 @@ static PATHPTR_T splitTurnoutRoot; static int splitTurnoutDir; static void SplitTurnoutCheckEndPt( - PATHPTR_T path, - int dir, - trkSeg_p segs, - coOrd epPos, - coOrd splitPos ) + PATHPTR_T path, + int dir, + trkSeg_p segs, + coOrd epPos, + coOrd splitPos) { PATHPTR_T path0; wIndex_t segInx; @@ -1009,21 +2889,21 @@ static void SplitTurnoutCheckEndPt( DIST_T dist, minDist; path0 = path; - GetSegInxEP( path[0], &segInx, &segEP ); - if ( dir < 0 ) segEP = 1-segEP; - pos = GetSegEndPt( &segs[segInx], segEP, FALSE, NULL ); - dist = FindDistance( pos, epPos ); - LOG( log_splitturnout, 1, ( " SPTChkEp P%d DIR:%d SegInx:%d SegEP:%d POS[%0.3f %0.3f] DIST:%0.3f\n", *path, dir, segInx, segEP, pos.x, pos.y, dist ) ); - if ( dist>connectDistance ) + GetSegInxEP(path[0], &segInx, &segEP); + if (dir < 0) segEP = 1 - segEP; + pos = GetSegEndPt(&segs[segInx], segEP, FALSE, NULL); + dist = FindDistance(pos, epPos); + LOG(log_splitturnout, 1, (" SPTChkEp P%d DIR:%d SegInx:%d SegEP:%d POS[%0.3f %0.3f] DIST:%0.3f\n", *path, dir, segInx, segEP, pos.x, pos.y, dist)); + if (dist > connectDistance) return; minDist = trackGauge; - while ( path[0] ) { - GetSegInxEP( path[0], &segInx, &segEP ); - if ( dir < 0 ) segEP = 1-segEP; + while (path[0]) { + GetSegInxEP(path[0], &segInx, &segEP); + if (dir < 0) segEP = 1 - segEP; pos = splitPos; - dist = DistanceSegs( zero, 0.0, 1, &segs[segInx], &pos, NULL ); - LOG( log_splitturnout, 1, ( " - P:%d SegInx:%d SegEP:%d DIST:%0.3f\n", path[0], segInx, segEP, dist ) ); - if ( dist < minDist ) { + dist = DistanceSegs(zero, 0.0, 1, &segs[segInx], &pos, NULL); + LOG(log_splitturnout, 1, (" - P:%d SegInx:%d SegEP:%d DIST:%0.3f\n", path[0], segInx, segEP, dist)); + if (dist < minDist) { minDist = dist; splitTurnoutPath = path; splitTurnoutDir = -dir; @@ -1034,26 +2914,26 @@ static void SplitTurnoutCheckEndPt( } EXPORT BOOL_T SplitTurnoutCheck( - track_p trk, - coOrd pos, - EPINX_T ep, - track_p *leftover, - EPINX_T * ep0, - EPINX_T * ep1, - BOOL_T check, - coOrd * outPos, - ANGLE_T * outAngle ) - { - struct extraData * xx = GetTrkExtraData( trk ); + track_p trk, + coOrd pos, + EPINX_T ep, + track_p* leftover, + EPINX_T* ep0, + EPINX_T* ep1, + BOOL_T check, + coOrd* outPos, + ANGLE_T* outAngle) +{ + struct extraDataCompound_t* xx = GET_EXTRA_DATA(trk, T_TURNOUT, extraDataCompound_t); wIndex_t segInx0, segInx, segCnt; - EPINX_T segEP, epCnt, ep2=0, epN; + EPINX_T segEP, epCnt, ep2 = 0, epN; PATHPTR_T pp, pp1, pp2; unsigned char c; - char * cp; + char* cp; int negCnt, posCnt, pathCnt, dir; segProcData_t segProcDataSplit; segProcData_t segProcDataNewTrack; - track_p trk2=NULL; + track_p trk2 = NULL; static dynArr_t segIndexMap_da; #define segIndexMap(N) DYNARR_N( int, segIndexMap_da, N ) static dynArr_t newPath_da; @@ -1064,9 +2944,9 @@ EXPORT BOOL_T SplitTurnoutCheck( int s0, s1; trkSeg_t newSeg; - if ( (MyGetKeyState()&WKEY_SHIFT) == 0 ) { + if ((MyGetKeyState() & WKEY_SHIFT) == 0) { if (!check) - ErrorMessage( MSG_CANT_SPLIT_TRK, _("Turnout") ); + ErrorMessage(MSG_CANT_SPLIT_TRK, _("Turnout")); return FALSE; } @@ -1074,62 +2954,62 @@ EXPORT BOOL_T SplitTurnoutCheck( * 1. Find segment on path that ends at 'ep' */ epCnt = GetTrkEndPtCnt(trk); - epPos = GetTrkEndPos( trk, ep ); - for ( segCnt=0; segCnt<xx->segCnt && IsSegTrack(&xx->segs[segCnt]); segCnt++ ); - Rotate( &pos, xx->orig, -xx->angle ); + epPos = GetTrkEndPos(trk, ep); + for (segCnt = 0; segCnt < xx->segCnt && IsSegTrack(&xx->segs[segCnt]); segCnt++); + Rotate(&pos, xx->orig, -xx->angle); pos.x -= xx->orig.x; pos.y -= xx->orig.y; - Rotate( &epPos, xx->orig, -xx->angle ); + Rotate(&epPos, xx->orig, -xx->angle); epPos.x -= xx->orig.x; epPos.y -= xx->orig.y; splitTurnoutPath = NULL; - pp = xx->paths; - LOG( log_splitturnout, 1, ( "SplitTurnoutCheck T%d POS[%0.3f %0.3f] EP:%d CHK:%d EPPOS[%0.3f %0.3f]\n", trk?trk->index:0, pos.x, pos.y, ep, check, epPos.x, epPos.y ) ); - while ( pp[0] ) { - pp += strlen((char *)pp)+1; - while ( pp[0] ) { - SplitTurnoutCheckEndPt( pp, 1, xx->segs, epPos, pos ); - if ( splitTurnoutPath != NULL ) + pp = GetPaths(trk); + LOG(log_splitturnout, 1, ("SplitTurnoutCheck T%d POS[%0.3f %0.3f] EP:%d CHK:%d EPPOS[%0.3f %0.3f]\n", trk ? trk->index : 0, pos.x, pos.y, ep, check, epPos.x, epPos.y)); + while (pp[0]) { + pp += strlen((char*)pp) + 1; + while (pp[0]) { + SplitTurnoutCheckEndPt(pp, 1, xx->segs, epPos, pos); + if (splitTurnoutPath != NULL) goto foundSeg; - while ( pp[0] ) + while (pp[0]) pp++; - SplitTurnoutCheckEndPt( pp-1, -1, xx->segs, epPos, pos ); - if ( splitTurnoutPath != NULL ) + SplitTurnoutCheckEndPt(pp - 1, -1, xx->segs, epPos, pos); + if (splitTurnoutPath != NULL) goto foundSeg; pp++; } pp++; } if (!check) - ErrorMessage( _("splitTurnout: can't find segment") ); + ErrorMessage(_("splitTurnout: can't find segment")); return FALSE; foundSeg: /* * 2a. Check that all other paths thru found segment are the same */ - GetSegInxEP( splitTurnoutPath[0], &segInx0, &segEP ); - LOG( log_splitturnout, 1, (" Found Seg: %d SEG:%d EP:%d\n", *splitTurnoutPath, segInx0, segEP ) ); - pp = xx->paths; + GetSegInxEP(splitTurnoutPath[0], &segInx0, &segEP); + LOG(log_splitturnout, 1, (" Found Seg: %d SEG:%d EP:%d\n", *splitTurnoutPath, segInx0, segEP)); + pp = GetPaths(trk); pathCnt = 0; - while ( pp[0] ) { - pp += strlen((char *)pp)+1; - while ( pp[0] ) { - while ( pp[0] ) { - GetSegInxEP( pp[0], &segInx, &segEP ); - if ( segInx == segInx0 ) { + while (pp[0]) { + pp += strlen((char*)pp) + 1; + while (pp[0]) { + while (pp[0]) { + GetSegInxEP(pp[0], &segInx, &segEP); + if (segInx == segInx0) { pp1 = splitTurnoutPath; pp2 = pp; - dir = (pp2[0]>0?1:-1) * splitTurnoutDir; - while ( pp1[0] && pp2[0] ) { - if ( splitTurnoutDir * pp1[0] != dir * pp2[0] ) + dir = (pp2[0] > 0 ? 1 : -1) * splitTurnoutDir; + while (pp1[0] && pp2[0]) { + if (splitTurnoutDir * pp1[0] != dir * pp2[0]) break; pp1 += splitTurnoutDir; pp2 += dir; } - if ( pp1[0]!='\0' || pp2[0]!='\0' ) { + if (pp1[0] != '\0' || pp2[0] != '\0') { if (!check) - ErrorMessage( MSG_SPLIT_POS_BTW_MERGEPTS ); + ErrorMessage(MSG_SPLIT_POS_BTW_MERGEPTS); return FALSE; } } @@ -1143,20 +3023,20 @@ foundSeg: /* * 2b. Check that all paths from ep pass thru segInx0 */ - if ( !SplitTurnoutCheckEP( segInx0, epPos, splitTurnoutRoot, -splitTurnoutDir, xx->paths, xx->segs ) ) { + if (!SplitTurnoutCheckEP(segInx0, epPos, splitTurnoutRoot, -splitTurnoutDir, GetPaths(trk), xx->segs)) { if (!check) - ErrorMessage( MSG_SPLIT_PATH_NOT_UNIQUE ); + ErrorMessage(MSG_SPLIT_PATH_NOT_UNIQUE); return FALSE; } if (check) { segProcDataSplit.getAngle.pos = pos; - SegProc( SEGPROC_GETANGLE, xx->segs+segInx0, &segProcDataSplit ); - *outAngle = NormalizeAngle(segProcDataSplit.getAngle.angle+xx->angle); + SegProc(SEGPROC_GETANGLE, xx->segs + segInx0, &segProcDataSplit); + *outAngle = NormalizeAngle(segProcDataSplit.getAngle.angle + xx->angle); *outPos = segProcDataSplit.getAngle.pos; (*outPos).x += xx->orig.x; (*outPos).y += xx->orig.y; - Rotate( outPos, xx->orig, xx->angle ); + Rotate(outPos, xx->orig, xx->angle); return TRUE; } @@ -1165,53 +3045,56 @@ foundSeg: */ segProcDataSplit.split.pos = pos; s0 = (splitTurnoutPath[0] > 0) != (splitTurnoutDir > 0); - s1 = 1-s0; - SegProc( SEGPROC_SPLIT, xx->segs+segInx0, &segProcDataSplit ); - if ( segProcDataSplit.split.length[s1] <= minLength ) { - if ( splitTurnoutPath[splitTurnoutDir] == '\0' ) + s1 = 1 - s0; + SegProc(SEGPROC_SPLIT, xx->segs + segInx0, &segProcDataSplit); + if (segProcDataSplit.split.length[s1] <= minLength) { + if (splitTurnoutPath[splitTurnoutDir] == '\0') return FALSE; segProcDataSplit.split.length[s0] += segProcDataSplit.split.length[s1]; segProcDataSplit.split.length[s1] = 0; segProcDataSplit.split.newSeg[s0] = xx->segs[segInx0]; - epPos = GetSegEndPt( &segProcDataSplit.split.newSeg[s0], s1, FALSE, &epAngle ); - } else if ( segProcDataSplit.split.length[s0] <= minLength ) { + epPos = GetSegEndPt(&segProcDataSplit.split.newSeg[s0], s1, FALSE, &epAngle); + } + else if (segProcDataSplit.split.length[s0] <= minLength) { segProcDataSplit.split.length[s1] += segProcDataSplit.split.length[s0]; segProcDataSplit.split.length[s0] = 0; segProcDataSplit.split.newSeg[s1] = xx->segs[segInx0]; - epPos = GetSegEndPt( &segProcDataSplit.split.newSeg[s1], s0, FALSE, &epAngle ); + epPos = GetSegEndPt(&segProcDataSplit.split.newSeg[s1], s0, FALSE, &epAngle); epAngle += 180.0; - } else { - epPos = GetSegEndPt( &segProcDataSplit.split.newSeg[s1], s0, FALSE, &epAngle ); + } + else { + epPos = GetSegEndPt(&segProcDataSplit.split.newSeg[s1], s0, FALSE, &epAngle); epAngle += 180.0; } /* * 4. Map the old segments to new */ - DYNARR_SET( int, segIndexMap_da, xx->segCnt ); - for ( segInx=0; segInx<xx->segCnt; segInx++ ) - segIndexMap(segInx) = segInx+1; + DYNARR_SET(int, segIndexMap_da, xx->segCnt); + for (segInx = 0; segInx < xx->segCnt; segInx++) + segIndexMap(segInx) = segInx + 1; pp = splitTurnoutPath; - if ( segProcDataSplit.split.length[s0] > minLength ) + if (segProcDataSplit.split.length[s0] > minLength) pp += splitTurnoutDir; negCnt = 0; - while ( *pp ) { - GetSegInxEP( *pp, &segInx, &segEP ); - segIndexMap(segInx) = - segIndexMap(segInx); + while (*pp) { + GetSegInxEP(*pp, &segInx, &segEP); + segIndexMap(segInx) = -segIndexMap(segInx); negCnt++; pp += splitTurnoutDir; } - for ( segInx=posCnt=0; segInx<xx->segCnt; segInx++ ) { - if ( segIndexMap(segInx) > 0 ) + for (segInx = posCnt = 0; segInx < xx->segCnt; segInx++) { + if (segIndexMap(segInx) > 0) segIndexMap(segInx) = ++posCnt; } - DYNARR_SET( trkSeg_t, tempSegs_da, posCnt ); - for ( segInx=posCnt=0; segInx<xx->segCnt; segInx++ ) { - if ( segIndexMap(segInx) > 0 ) { - if ( segInx == segInx0 ) { - tempSegs(segIndexMap(segInx)-1) = segProcDataSplit.split.newSeg[s0]; - } else { - tempSegs(segIndexMap(segInx)-1) = xx->segs[segInx]; + DYNARR_SET(trkSeg_t, tempSegs_da, posCnt); + for (segInx = posCnt = 0; segInx < xx->segCnt; segInx++) { + if (segIndexMap(segInx) > 0) { + if (segInx == segInx0) { + tempSegs(segIndexMap(segInx) - 1) = segProcDataSplit.split.newSeg[s0]; + } + else { + tempSegs(segIndexMap(segInx) - 1) = xx->segs[segInx]; } posCnt++; } @@ -1220,19 +3103,19 @@ foundSeg: /* * 5. Remap paths by removing trailing segments */ - DYNARR_SET( char, newPath_da, xx->pathLen ); - pp = xx->paths; + pp = GetPaths(trk); + DYNARR_SET(char, newPath_da, GetPathsLength(pp)); pp1 = (PATHPTR_T)&newPath(0); - while ( *pp ) { - strcpy( (char *)pp1, (char *)pp ); - pp += strlen( (char *)pp )+1; - pp1 += strlen( (char *)pp1 )+1; - while ( *pp ) { - while ( *pp ) { - GetSegInxEP( *pp, &segInx, &segEP ); - if ( segIndexMap(segInx) > 0 ) { + while (*pp) { + strcpy((char*)pp1, (char*)pp); + pp += strlen((char*)pp) + 1; + pp1 += strlen((char*)pp1) + 1; + while (*pp) { + while (*pp) { + GetSegInxEP(*pp, &segInx, &segEP); + if (segIndexMap(segInx) > 0) { c = segIndexMap(segInx); - if ( *pp<0 ) + if (*pp < 0) c = -c; *pp1++ = c; } @@ -1249,23 +3132,25 @@ foundSeg: /* * 6. Reorigin segments */ - GetSegBounds( zero, 0, tempSegs_da.cnt, &tempSegs(0), &orig, &size ); + GetSegBounds(zero, 0, tempSegs_da.cnt, &tempSegs(0), &orig, &size); orig.x = -orig.x; orig.y = -orig.y; - MoveSegs( tempSegs_da.cnt, &tempSegs(0), orig ); + MoveSegs(tempSegs_da.cnt, &tempSegs(0), orig); epPos.x += orig.x; epPos.y += orig.y; - cp = strchr( xx->title, '\t' ); - if ( cp ) { - if ( strncmp( cp+1, "Split ", 6 ) != 0 ) { - memcpy( message, xx->title, cp-xx->title+1 ); - strcpy( message+(cp-xx->title+1), "Split " ); - strcat( message, cp+1 ); - } else { - strcpy( message, xx->title ); + cp = strchr(xx->title, '\t'); + if (cp) { + if (strncmp(cp + 1, "Split ", 6) != 0) { + memcpy(message, xx->title, cp - xx->title + 1); + strcpy(message + (cp - xx->title + 1), "Split "); + strcat(message, cp + 1); + } + else { + strcpy(message, xx->title); } - } else { - sprintf( message, "Split %s", xx->title ); + } + else { + sprintf(message, "Split %s", xx->title); } /* @@ -1273,28 +3158,30 @@ foundSeg: */ int trks = 0; path = splitTurnoutPath; - if ( segProcDataSplit.split.length[s1] < minLength ) + if (segProcDataSplit.split.length[s1] < minLength) path += splitTurnoutDir; - while ( path[0] ) { - GetSegInxEP( path[0], &segInx, &segEP ); + while (path[0]) { + GetSegInxEP(path[0], &segInx, &segEP); s0 = (path[0] > 0) != (splitTurnoutDir > 0); - if ( segInx0 != segInx ) { + if (segInx0 != segInx) { newSeg = xx->segs[segInx]; - } else { + } + else { newSeg = segProcDataSplit.split.newSeg[s1]; } - MoveSegs( 1, &newSeg, xx->orig ); - RotateSegs( 1, &newSeg, xx->orig, xx->angle ); - SegProc( SEGPROC_NEWTRACK, &newSeg, &segProcDataNewTrack ); - if ( *leftover == NULL ) { + MoveSegs(1, &newSeg, xx->orig); + RotateSegs(1, &newSeg, xx->orig, xx->angle); + SegProc(SEGPROC_NEWTRACK, &newSeg, &segProcDataNewTrack); + if (*leftover == NULL) { *ep0 = segProcDataNewTrack.newTrack.ep[s0]; *leftover = trk2 = segProcDataNewTrack.newTrack.trk; - ep2 = 1-*ep0; - } else { + ep2 = 1 - *ep0; + } + else { epN = segProcDataNewTrack.newTrack.ep[s0]; - ConnectTracks( trk2, ep2, segProcDataNewTrack.newTrack.trk, epN ); + ConnectTracks(trk2, ep2, segProcDataNewTrack.newTrack.trk, epN); trk2 = segProcDataNewTrack.newTrack.trk; - ep2 = 1-epN; + ep2 = 1 - epN; } ++trks; path += splitTurnoutDir; @@ -1304,40 +3191,39 @@ foundSeg: * 8. Replace segments, paths, and endPt in original turnout */ xx->split = TRUE; - Rotate( &orig, zero, xx->angle ); + Rotate(&orig, zero, xx->angle); xx->orig.x -= orig.x; xx->orig.y -= orig.y; xx->segCnt = tempSegs_da.cnt; - xx->segs = (trkSeg_p)memdup( &tempSegs(0), tempSegs_da.cnt * sizeof tempSegs(0) ); - CloneFilledDraw( xx->segCnt, xx->segs, TRUE ); - xx->pathLen = pp1-(PATHPTR_T)&newPath(0); - xx->pathCurr = xx->paths = memdup( &newPath(0), xx->pathLen ); - epAngle = NormalizeAngle( xx->angle+epAngle ); + xx->segs = (trkSeg_p)memdup(&tempSegs(0), tempSegs_da.cnt * sizeof tempSegs(0)); + CloneFilledDraw(xx->segCnt, xx->segs, TRUE); + SetPaths(trk, (PATHPTR_T)&newPath(0)); + epAngle = NormalizeAngle(xx->angle + epAngle); epPos.x += xx->orig.x; epPos.y += xx->orig.y; - Rotate( &epPos, xx->orig, xx->angle ); - SetTrkEndPoint( trk, ep, epPos, epAngle ); - ComputeCompoundBoundingBox( trk ); + Rotate(&epPos, xx->orig, xx->angle); + SetTrkEndPoint(trk, ep, epPos, epAngle); + ComputeCompoundBoundingBox(trk); return TRUE; } static BOOL_T SplitTurnout( - track_p trk, - coOrd pos, - EPINX_T ep, - track_p *leftover, - EPINX_T * ep0, - EPINX_T * ep1 ) + track_p trk, + coOrd pos, + EPINX_T ep, + track_p* leftover, + EPINX_T* ep0, + EPINX_T* ep1) { - return SplitTurnoutCheck(trk,pos,ep,leftover,ep0,ep1,FALSE,NULL,NULL); + return SplitTurnoutCheck(trk, pos, ep, leftover, ep0, ep1, FALSE, NULL, NULL); } static BOOL_T CheckTraverseTurnout( - track_p trk, - coOrd pos ) + track_p trk, + coOrd pos) { - struct extraData * xx = GetTrkExtraData(trk); + struct extraDataCompound_t* xx = GET_EXTRA_DATA(trk, T_TURNOUT, extraDataCompound_t); coOrd pos1; #ifdef LATER int inx, foundInx = 0; @@ -1348,65 +3234,67 @@ static BOOL_T CheckTraverseTurnout( int segInx; EPINX_T segEP; -LOG( log_traverseTurnout, 1, ( "CheckTraverseTurnout( T%d, [%0.3f %0.3f])\n", GetTrkIndex(trk), pos.x, pos.y ) ) - Rotate( &pos, xx->orig, -xx->angle ); + LOG(log_traverseTurnout, 1, ("CheckTraverseTurnout( T%d, [%0.3f %0.3f])\n", GetTrkIndex(trk), pos.x, pos.y)) + Rotate(&pos, xx->orig, -xx->angle); pos.x -= xx->orig.x; pos.y -= xx->orig.y; -LOG( log_traverseTurnout, 1, ( "After rotation = [%0.3f %0.3f])\n", pos.x, pos.y ) ) - + LOG(log_traverseTurnout, 1, ("After rotation = [%0.3f %0.3f])\n", pos.x, pos.y)) + #ifdef LATER - for ( inx=0; inx<xx->segCnt; inx++ ) { - switch ( xx->segs[inx].type ) { - case SEG_STRTRK: - case SEG_CRVTRK: - pos1 = GetSegEndPt( &xx->segs[inx], 0, FALSE, NULL ); - d = FindDistance( pos, pos1 ); - if ( foundInx == 0 || d < foundD ) { - foundInx = inx+1; - foundD = d; - } - pos1 = GetSegEndPt( &xx->segs[inx], 1, FALSE, NULL ); - d = FindDistance( pos, pos1 ); - if ( foundInx == 0 || d < foundD ) { - foundInx = -(inx+1); - foundD = d; + for (inx = 0; inx < xx->segCnt; inx++) { + switch (xx->segs[inx].type) { + case SEG_STRTRK: + case SEG_CRVTRK: + pos1 = GetSegEndPt(&xx->segs[inx], 0, FALSE, NULL); + d = FindDistance(pos, pos1); + if (foundInx == 0 || d < foundD) { + foundInx = inx + 1; + foundD = d; + } + pos1 = GetSegEndPt(&xx->segs[inx], 1, FALSE, NULL); + d = FindDistance(pos, pos1); + if (foundInx == 0 || d < foundD) { + foundInx = -(inx + 1); + foundD = d; + } + break; } - break; } - } - if ( foundInx == 0 ) + if (foundInx == 0) return FALSE; #endif - for ( pathCurr = xx->pathCurr+strlen((char*)xx->pathCurr)+1; pathCurr[0] || pathCurr[1]; pathCurr++ ) { -LOG( log_traverseTurnout, 1, ( "P[%d] = %d ", pathCurr-xx->paths, pathCurr[0] ) ) - if ( pathCurr[-1] == 0 ) { - GetSegInxEP( pathCurr[0], &segInx, &segEP ); - pos1 = GetSegEndPt( &xx->segs[segInx], segEP, FALSE, NULL ); - d = FindDistance( pos, pos1 ); -LOG( log_traverseTurnout, 1, ( "d=%0.3f\n", d ) ) - if ( d < connectDistance ) - return TRUE; - } - if ( pathCurr[1] == 0 ) { - GetSegInxEP( pathCurr[0], &segInx, &segEP ); - pos1 = GetSegEndPt( &xx->segs[segInx], 1-segEP, FALSE, NULL ); - d = FindDistance( pos, pos1 ); -LOG( log_traverseTurnout, 1, ( "d=%0.3f\n", d ) ) - if ( d < connectDistance ) - return TRUE; - } - } -LOG( log_traverseTurnout, 1, ( " not found\n" ) ) - return FALSE; + PATHPTR_T pathName = GetCurrPath(trk); + for (pathCurr = pathName + strlen((char*)pathName) + 1; + pathCurr[0] || pathCurr[1]; pathCurr++) { + LOG(log_traverseTurnout, 1, ("P[%d] = %d ", pathCurr - GetPaths(trk), pathCurr[0])) + if (pathCurr[-1] == 0) { + GetSegInxEP(pathCurr[0], &segInx, &segEP); + pos1 = GetSegEndPt(&xx->segs[segInx], segEP, FALSE, NULL); + d = FindDistance(pos, pos1); + LOG(log_traverseTurnout, 1, ("d=%0.3f\n", d)) + if (d < connectDistance) + return TRUE; + } + if (pathCurr[1] == 0) { + GetSegInxEP(pathCurr[0], &segInx, &segEP); + pos1 = GetSegEndPt(&xx->segs[segInx], 1 - segEP, FALSE, NULL); + d = FindDistance(pos, pos1); + LOG(log_traverseTurnout, 1, ("d=%0.3f\n", d)) + if (d < connectDistance) + return TRUE; + } + } + LOG(log_traverseTurnout, 1, (" not found\n")) + return FALSE; } static BOOL_T TraverseTurnout( - traverseTrack_p trvTrk, - DIST_T * distR ) + traverseTrack_p trvTrk, + DIST_T* distR) { track_p trk = trvTrk->trk; - struct extraData * xx = GetTrkExtraData(trk); + struct extraDataCompound_t* xx = GET_EXTRA_DATA(trk, T_TURNOUT, extraDataCompound_t); coOrd pos0, pos1, pos2; DIST_T d, dist; PATHPTR_T path, pathCurr; @@ -1416,37 +3304,38 @@ static BOOL_T TraverseTurnout( EPINX_T segEP; segProcData_t segProcData; - d = 10000; + d = DIST_INF; pos0 = trvTrk->pos; - Rotate( &pos0, xx->orig, -xx->angle ); + Rotate(&pos0, xx->orig, -xx->angle); pos0.x -= xx->orig.x; pos0.y -= xx->orig.y; dist = *distR; -LOG( log_traverseTurnout, 1, ( "TraverseTurnout( T%d, [%0.3f %0.3f] [%0.3f %0.3f], A%0.3f, D%0.3f\n", GetTrkIndex(trk), trvTrk->pos.x, trvTrk->pos.y, pos0.x, pos0.y, trvTrk->angle, *distR ) ) - pathCurr = 0; - for ( path = xx->pathCurr+strlen((char*)xx->pathCurr)+1; path[0] || path[1]; path++ ) { - if ( path[0] == 0 ) + LOG(log_traverseTurnout, 1, ("TraverseTurnout( T%d, [%0.3f %0.3f] [%0.3f %0.3f], A%0.3f, D%0.3f\n", GetTrkIndex(trk), trvTrk->pos.x, trvTrk->pos.y, pos0.x, pos0.y, trvTrk->angle, *distR)) + pathCurr = 0; + path = GetCurrPath(trk); + for (path += strlen((char*)path) + 1; path[0] || path[1]; path++) { + if (path[0] == 0) continue; - GetSegInxEP( path[0], &segInx, &segEP ); - segPtr = xx->segs+segInx; + GetSegInxEP(path[0], &segInx, &segEP); + segPtr = xx->segs + segInx; segProcData.distance.pos1 = pos0; - SegProc( SEGPROC_DISTANCE, segPtr, &segProcData ); - if ( segProcData.distance.dd < d ) { + SegProc(SEGPROC_DISTANCE, segPtr, &segProcData); + if (segProcData.distance.dd < d) { d = segProcData.distance.dd; pos2 = segProcData.distance.pos1; pathCurr = path; } } - if ( d > 10 || pathCurr == 0 ) { - ErrorMessage( "traverseTurnout: Not near: %0.3f", d ); + if (d > 10 || pathCurr == 0) { + ErrorMessage("traverseTurnout: Not near: %0.3f", d); return FALSE; } -LOG( log_traverseTurnout, 1, ( " PC=%d ", pathCurr[0] ) ) - GetSegInxEP( pathCurr[0], &segInx, &segEP ); - segPtr = xx->segs+segInx; + LOG(log_traverseTurnout, 1, (" PC=%d ", pathCurr[0])) + GetSegInxEP(pathCurr[0], &segInx, &segEP); + segPtr = xx->segs + segInx; segProcData.traverse1.pos = pos2; - segProcData.traverse1.angle = -xx->angle+trvTrk->angle; - SegProc( SEGPROC_TRAVERSE1, segPtr, &segProcData ); + segProcData.traverse1.angle = -xx->angle + trvTrk->angle; + SegProc(SEGPROC_TRAVERSE1, segPtr, &segProcData); dist += segProcData.traverse1.dist; //Get ready for Traverse2 - copy all Traverse1 first BOOL_T backwards = segProcData.traverse1.backwards; @@ -1461,111 +3350,112 @@ LOG( log_traverseTurnout, 1, ( " PC=%d ", pathCurr[0] ) ) BOOL_T turnout_backwards = backwards; if (segEP) turnout_backwards = !turnout_backwards; //direction modified if path reversed -LOG( log_traverseTurnout, 2, ( " SI%d TB%d SP%d B%d SB%d N%d BSI%d D%0.3f\n", segInx, turnout_backwards, segEP, backwards, segs_backwards, neg, BezSegInx, dist ) ) - while ( *pathCurr ) { - //Set up Traverse2 - GetSegInxEP( pathCurr[0], &segInx, &segEP ); - segPtr = xx->segs+segInx; - segProcData.traverse2.segDir = backwards; - segProcData.traverse2.dist = dist; - segProcData.traverse2.BezSegInx = BezSegInx; - segProcData.traverse2.segs_backwards = segs_backwards; - SegProc( SEGPROC_TRAVERSE2, segPtr, &segProcData ); - if ( segProcData.traverse2.dist <= 0 ) { - *distR = 0; - REORIGIN( trvTrk->pos, segProcData.traverse2.pos, xx->angle, xx->orig ); - trvTrk->angle = NormalizeAngle( xx->angle+segProcData.traverse2.angle ); -LOG( log_traverseTurnout, 2, ( " -> [%0.3f %0.3f] A%0.3f D%0.3f\n", trvTrk->pos.x, trvTrk->pos.y, trvTrk->angle, *distR )) - return TRUE; + LOG(log_traverseTurnout, 2, (" SI%d TB%d SP%d B%d SB%d N%d BSI%d D%0.3f\n", segInx, turnout_backwards, segEP, backwards, segs_backwards, neg, BezSegInx, dist)) + while (*pathCurr) { + //Set up Traverse2 + GetSegInxEP(pathCurr[0], &segInx, &segEP); + segPtr = xx->segs + segInx; + segProcData.traverse2.segDir = backwards; + segProcData.traverse2.dist = dist; + segProcData.traverse2.BezSegInx = BezSegInx; + segProcData.traverse2.segs_backwards = segs_backwards; + SegProc(SEGPROC_TRAVERSE2, segPtr, &segProcData); + if (segProcData.traverse2.dist <= 0) { + *distR = 0; + REORIGIN(trvTrk->pos, segProcData.traverse2.pos, xx->angle, xx->orig); + trvTrk->angle = NormalizeAngle(xx->angle + segProcData.traverse2.angle); + LOG(log_traverseTurnout, 2, (" -> [%0.3f %0.3f] A%0.3f D%0.3f\n", trvTrk->pos.x, trvTrk->pos.y, trvTrk->angle, *distR)) + return TRUE; + } + dist = segProcData.traverse2.dist; //Remainder after segment + pathCurr += (turnout_backwards ? -1 : 1); //Use master direction for turnout + //Redrive Traverse 1 for each segment for Bezier - to pick up backwards elements + if (pathCurr[0] == '\0') continue; // + //Set up Traverse1 - copy all of Traverse2 values first + GetSegInxEP(pathCurr[0], &segInx, &segEP); + segPtr = xx->segs + segInx; + ANGLE_T angle = segProcData.traverse2.angle; + coOrd pos = segProcData.traverse2.pos; + LOG(log_traverseTurnout, 1, (" Loop2-1 SI%d SP%d [%0.3f %0.3f] A%0.3f D%0.3f\n", segInx, segEP, pos.x, pos.y, angle, dist)) + segProcData.traverse1.pos = pos; + segProcData.traverse1.angle = angle; + SegProc(SEGPROC_TRAVERSE1, segPtr, &segProcData); + // dist += segProcData.traverse1.dist; //Add distance from end to pos (could be zero or whole length if backwards) + backwards = segProcData.traverse1.backwards; + segs_backwards = segProcData.traverse1.segs_backwards; + neg = segProcData.traverse1.negative; + BezSegInx = segProcData.traverse1.BezSegInx; + LOG(log_traverseTurnout, 1, (" Loop1-2 B%d SB%d N%d BSI%d D%0.3f\n", backwards, segs_backwards, neg, BezSegInx, dist)) } - dist = segProcData.traverse2.dist; //Remainder after segment - pathCurr += (turnout_backwards?-1:1); //Use master direction for turnout - //Redrive Traverse 1 for each segment for Bezier - to pick up backwards elements - if (pathCurr[0] == '\0') continue; // - //Set up Traverse1 - copy all of Traverse2 values first - GetSegInxEP( pathCurr[0], &segInx, &segEP ); - segPtr = xx->segs+segInx; - ANGLE_T angle = segProcData.traverse2.angle; - coOrd pos = segProcData.traverse2.pos; -LOG( log_traverseTurnout, 1, ( " Loop2-1 SI%d SP%d [%0.3f %0.3f] A%0.3f D%0.3f\n", segInx, segEP, pos.x, pos.y, angle, dist ) ) - segProcData.traverse1.pos = pos; - segProcData.traverse1.angle = angle; - SegProc( SEGPROC_TRAVERSE1, segPtr, &segProcData ); - // dist += segProcData.traverse1.dist; //Add distance from end to pos (could be zero or whole length if backwards) - backwards = segProcData.traverse1.backwards; - segs_backwards = segProcData.traverse1.segs_backwards; - neg = segProcData.traverse1.negative; - BezSegInx = segProcData.traverse1.BezSegInx; -LOG( log_traverseTurnout, 1, ( " Loop1-2 B%d SB%d N%d BSI%d D%0.3f\n", backwards, segs_backwards, neg, BezSegInx, dist ) ) - } - - pathCurr += (turnout_backwards?1:-1); - pos1 = MapPathPos( xx, pathCurr[0], (turnout_backwards?0:1) ); + + pathCurr += (turnout_backwards ? 1 : -1); + pos1 = MapPathPos(xx, pathCurr[0], (turnout_backwards ? 0 : 1)); *distR = dist; epCnt = GetTrkEndPtCnt(trk); ep = 0; - dist = FindDistance( pos1, GetTrkEndPos(trk,0) ); - for ( ep2=1; ep2<epCnt; ep2++ ) { - d = FindDistance( pos1, GetTrkEndPos(trk,ep2) ); - if ( d < dist ) { + dist = FindDistance(pos1, GetTrkEndPos(trk, 0)); + for (ep2 = 1; ep2 < epCnt; ep2++) { + d = FindDistance(pos1, GetTrkEndPos(trk, ep2)); + if (d < dist) { dist = d; ep = ep2; } } - if ( dist > connectDistance ) { + if (dist > connectDistance) { trk = NULL; trvTrk->pos = pos1; - } else { - trvTrk->pos = GetTrkEndPos( trk, ep ); - trvTrk->angle = GetTrkEndAngle( trk, ep ); - trk = GetTrkEndTrk( trk, ep ); - } - dist = FindDistance( trvTrk->pos, pos1 ); -LOG( log_traverseTurnout, 1, ( " -> [%0.3f %0.3f] A%0.3f D%0.3f\n", trvTrk->pos.x, trvTrk->pos.y, trvTrk->angle, *distR ) ) - trvTrk->trk = trk; + } + else { + trvTrk->pos = GetTrkEndPos(trk, ep); + trvTrk->angle = GetTrkEndAngle(trk, ep); + trk = GetTrkEndTrk(trk, ep); + } + dist = FindDistance(trvTrk->pos, pos1); + LOG(log_traverseTurnout, 1, (" -> [%0.3f %0.3f] A%0.3f D%0.3f\n", trvTrk->pos.x, trvTrk->pos.y, trvTrk->angle, *distR)) + trvTrk->trk = trk; return TRUE; } -static STATUS_T ModifyTurnout( track_p trk, wAction_t action, coOrd pos ) +static STATUS_T ModifyTurnout(track_p trk, wAction_t action, coOrd pos) { - struct extraData *xx; + struct extraDataCompound_t* xx; static EPINX_T ep; static wBool_t curved; DIST_T d; - xx = GetTrkExtraData(trk); - if ( xx->special == TOadjustable ) { - switch ( action ) { + xx = GET_EXTRA_DATA(trk, T_TURNOUT, extraDataCompound_t); + if (xx->special == TOadjustable) { + switch (action) { case C_START: ep = -1; curved = FALSE; return C_CONTINUE; case C_DOWN: - ep = PickUnconnectedEndPoint( pos, trk ); + ep = PickUnconnectedEndPoint(pos, trk); if (ep == -1) return C_ERROR; - UndrawNewTrack( trk ); + UndrawNewTrack(trk); tempSegs(0).type = SEG_STRTRK; tempSegs(0).width = 0; - tempSegs(0).u.l.pos[0] = GetTrkEndPos( trk, 1-ep ); + tempSegs(0).u.l.pos[0] = GetTrkEndPos(trk, 1 - ep); tempSegs_da.cnt = 1; - InfoMessage( _("Drag to change track length") ); + InfoMessage(_("Drag to change track length")); return C_CONTINUE; case C_MOVE: - d = FindDistance( tempSegs(0).u.l.pos[0], pos ); - if ( d < xx->u.adjustable.minD ) + d = FindDistance(tempSegs(0).u.l.pos[0], pos); + if (d < xx->u.adjustable.minD) d = xx->u.adjustable.minD; - else if ( d > xx->u.adjustable.maxD ) + else if (d > xx->u.adjustable.maxD) d = xx->u.adjustable.maxD; - Translate( &tempSegs(0).u.l.pos[1], tempSegs(0).u.l.pos[0], GetTrkEndAngle( trk, ep ), d ); + Translate(&tempSegs(0).u.l.pos[1], tempSegs(0).u.l.pos[0], GetTrkEndAngle(trk, ep), d); tempSegs_da.cnt = 1; if (action == C_MOVE) - InfoMessage( _("Length=%s"), FormatDistance( d ) ); + InfoMessage(_("Length=%s"), FormatDistance(d)); return C_CONTINUE; case C_UP: - d = FindDistance( tempSegs(0).u.l.pos[0],tempSegs(0).u.l.pos[1] ); - ChangeAdjustableEndPt( trk, ep, d ); + d = FindDistance(tempSegs(0).u.l.pos[0], tempSegs(0).u.l.pos[1]); + ChangeAdjustableEndPt(trk, ep, d); return C_TERMINATE; default: return C_CONTINUE; @@ -1576,141 +3466,130 @@ static STATUS_T ModifyTurnout( track_p trk, wAction_t action, coOrd pos ) } -static BOOL_T GetParamsTurnout( int inx, track_p trk, coOrd pos, trackParams_t * params ) +static BOOL_T GetParamsTurnout(int inx, track_p trk, coOrd pos, trackParams_t* params) { - struct extraData *xx; - xx = GetTrkExtraData(trk); + struct extraDataCompound_t* xx; + xx = GET_EXTRA_DATA(trk, T_TURNOUT, extraDataCompound_t); params->type = curveTypeStraight; - if (inx == PARAMS_TURNOUT) { - params->len = 0.0; - int epCnt = GetTrkEndPtCnt(trk); - if (epCnt < 3) { - double d = 10000.0; - params->centroid = zero; - //calculate path length from endPt (either to end or to other end) - segProcData_t segProcData; - trkSeg_p seg; - int segInx; - int segEP; - trkSeg_p segPtr; - PATHPTR_T path,pathCurr; - //Find starting seg on path (nearest to end Pt) - for ( path = xx->pathCurr+strlen((char*)xx->pathCurr)+1; path[0] || path[1]; path++ ) { - if ( path[0] == 0 ) - continue; - GetSegInxEP( path[0], &segInx, &segEP ); - segPtr = xx->segs+segInx; - segProcData.distance.pos1 = pos; - SegProc( SEGPROC_DISTANCE, segPtr, &segProcData ); - if ( segProcData.distance.dd < d ) { - d = segProcData.distance.dd; - pathCurr = path; - } - } - GetSegInxEP( pathCurr[0], &segInx, &segEP ); - seg = xx->segs+segInx; - d = 0.0; - //Loop through segs on path from endPt adding - while (pathCurr[0]) { - GetSegInxEP( pathCurr[0], &segInx, &segEP ); - seg = xx->segs+segInx; - SegProc(SEGPROC_LENGTH, seg, &segProcData ); - d += segProcData.length.length; - pathCurr += segEP?1:-1; - } - params->len = d; - } else { - double x, y; - x = 0; y = 0; - for (int i=0;i<epCnt; i++) { - coOrd cpos = GetTrkEndPos(trk,i); - x += cpos.x; - y += cpos.y; - } - params->centroid.x = x/epCnt; - params->centroid.y = y/epCnt; - params->len = FindDistance(params->centroid,pos)*2; //Times two because it will be halved by track.c - } - return TRUE; - } - if ((inx == PARAMS_CORNU) || (inx == PARAMS_EXTEND)) { + if (inx == PARAMS_TURNOUT) { + params->len = 0.0; + int epCnt = GetTrkEndPtCnt(trk); + if (epCnt < 3) { + double d = DIST_INF; + params->centroid = zero; + //calculate path length from endPt (either to end or to other end) + segProcData_t segProcData; + trkSeg_p seg; + int segInx; + int segEP; + trkSeg_p segPtr; + PATHPTR_T path, pathCurr; + //Find starting seg on path (nearest to end Pt) + path = GetCurrPath(trk); + pathCurr = path; + for (path += strlen((char*)path) + 1; path[0] || path[1]; path++) { + if (path[0] == 0) + continue; + GetSegInxEP(path[0], &segInx, &segEP); + segPtr = xx->segs + segInx; + segProcData.distance.pos1 = pos; + SegProc(SEGPROC_DISTANCE, segPtr, &segProcData); + if (segProcData.distance.dd < d) { + d = segProcData.distance.dd; + pathCurr = path; + } + } + GetSegInxEP(pathCurr[0], &segInx, &segEP); + seg = xx->segs + segInx; + d = 0.0; + //Loop through segs on path from endPt adding + while (pathCurr[0]) { + GetSegInxEP(pathCurr[0], &segInx, &segEP); + seg = xx->segs + segInx; + SegProc(SEGPROC_LENGTH, seg, &segProcData); + d += segProcData.length.length; + pathCurr += segEP ? 1 : -1; + } + params->len = d; + } + else { + // Centroid is middle of bounding box + params->centroid.x = (trk->lo.x + trk->hi.x) / 2.0; + params->centroid.y = (trk->lo.y + trk->hi.y) / 2.0; + params->len = FindDistance(params->centroid, pos) * 2; //Times two because it will be halved by track.c + } + return TRUE; + } + if ((inx == PARAMS_CORNU) || (inx == PARAMS_EXTEND)) { params->type = curveTypeStraight; params->arcR = 0.0; params->arcP = zero; - params->ep = PickEndPoint(pos, trk); + params->ep = PickEndPoint(pos, trk); params->circleOrHelix = FALSE; - if (params->ep>=0) { - params->angle = GetTrkEndAngle(trk,params->ep); - params->track_angle = params->angle + params->ep?0:180; - } else { - params->angle = params-> track_angle = 0; + if (params->ep >= 0) { + params->angle = GetTrkEndAngle(trk, params->ep); + params->track_angle = params->angle + params->ep ? 0 : 180; + } + else { + params->angle = params->track_angle = 0; return FALSE; } - /* Use end radii if we have them */ - //if (xx->special == TOcurved) { - // params->type = curveTypeCurve; - // params->arcR = fabs(DYNARR_N(DIST_T,xx->u.curved.radii,params->ep)); - // if (params->arcR != 0.0) - // Translate(¶ms->arcP,pos,params->track_angle-90.0,params->arcR); - // else - // params->type = curveTypeStraight; - // return TRUE; - //} /* Find the path we are closest to */ PATHPTR_T pathCurr = 0; int segInx, subSegInx; trkSeg_p segPtr; - double d = 10000; - struct extraData * xx = GetTrkExtraData(trk); + DIST_T d = DIST_INF; + struct extraDataCompound_t* xx = GET_EXTRA_DATA(trk, T_TURNOUT, extraDataCompound_t); /* Get parms from that seg */ - wBool_t back,negative; + wBool_t back, negative; coOrd segPos = pos; - Rotate(&segPos,xx->orig,-xx->angle); + Rotate(&segPos, xx->orig, -xx->angle); segPos.x -= xx->orig.x; segPos.y -= xx->orig.y; params->track_angle = GetAngleSegs( //Find correct subSegment - xx->segCnt,xx->segs, - &segPos, &segInx, &d , &back, &subSegInx, &negative ); - if (segInx ==- 1) return FALSE; - segPtr = xx->segs+segInx; + xx->segCnt, xx->segs, + &segPos, &segInx, &d, &back, &subSegInx, &negative); + if (segInx == -1) return FALSE; + segPtr = xx->segs + segInx; switch (segPtr->type) { - case SEG_BEZTRK: - if ( negative != back ) params->track_angle = NormalizeAngle(params->track_angle+180); //Bezier is in reverse - segPtr = xx->segs + segInx; - trkSeg_p subSegPtr = (trkSeg_p)segPtr->bezSegs.ptr+subSegInx; - if (subSegPtr->type == SEG_CRVTRK) { - params->type = curveTypeCurve; - params->arcR = fabs(subSegPtr->u.c.radius); - params->arcP = subSegPtr->u.c.center; - params->arcP.x += xx->orig.x; - params->arcP.y += xx->orig.y; - Rotate(¶ms->arcP,xx->orig,xx->angle); - params->arcA0 = subSegPtr->u.c.a0; - params->arcA1 = subSegPtr->u.c.a1; - } - return TRUE; - break; - case SEG_CRVTRK: + case SEG_BEZTRK: + if (negative != back) params->track_angle = NormalizeAngle(params->track_angle + 180); //Bezier is in reverse + segPtr = xx->segs + segInx; + trkSeg_p subSegPtr = (trkSeg_p)segPtr->bezSegs.ptr + subSegInx; + if (subSegPtr->type == SEG_CRVTRK) { params->type = curveTypeCurve; - params->arcR = fabs(segPtr->u.c.radius); - params->arcP = segPtr->u.c.center; + params->arcR = fabs(subSegPtr->u.c.radius); + params->arcP = subSegPtr->u.c.center; params->arcP.x += xx->orig.x; params->arcP.y += xx->orig.y; - Rotate(¶ms->arcP,xx->orig,xx->angle); - params->arcA0 = segPtr->u.c.a0; - params->arcA1 = segPtr->u.c.a1; - return TRUE; - break; - } - params->arcR = 0.0; + Rotate(¶ms->arcP, xx->orig, xx->angle); + params->arcA0 = subSegPtr->u.c.a0; + params->arcA1 = subSegPtr->u.c.a1; + } + return TRUE; + break; + case SEG_CRVTRK: + params->type = curveTypeCurve; + params->arcR = fabs(segPtr->u.c.radius); + params->arcP = segPtr->u.c.center; + params->arcP.x += xx->orig.x; + params->arcP.y += xx->orig.y; + Rotate(¶ms->arcP, xx->orig, xx->angle); + params->arcA0 = segPtr->u.c.a0; + params->arcA1 = segPtr->u.c.a1; + return TRUE; + break; + } + params->arcR = 0.0; params->arcP = zero; - params->ep = PickEndPoint(pos,trk); //Nearest - if (params->ep>=0) { - params->angle = GetTrkEndAngle(trk,params->ep); - params->track_angle = params->angle + params->ep?0:180; - } else { - params->angle = params-> track_angle = 0; + params->ep = PickEndPoint(pos, trk); //Nearest + if (params->ep >= 0) { + params->angle = GetTrkEndAngle(trk, params->ep); + params->track_angle = params->angle + params->ep ? 0 : 180; + } + else { + params->angle = params->track_angle = 0; return FALSE; } return TRUE; @@ -1718,49 +3597,49 @@ static BOOL_T GetParamsTurnout( int inx, track_p trk, coOrd pos, trackParams_t * if ((inx == PARAMS_1ST_JOIN) || (inx == PARAMS_2ND_JOIN)) params->ep = PickEndPoint(pos, trk); else - params->ep = PickUnconnectedEndPointSilent( pos, trk ); + params->ep = PickUnconnectedEndPointSilent(pos, trk); if (params->ep == -1) - return FALSE; - params->lineOrig = GetTrkEndPos(trk,params->ep); + return FALSE; + params->lineOrig = GetTrkEndPos(trk, params->ep); params->lineEnd = params->lineOrig; params->len = 0.0; - params->angle = GetTrkEndAngle(trk,params->ep); + params->angle = GetTrkEndAngle(trk, params->ep); params->arcR = 0.0; return TRUE; } -static BOOL_T MoveEndPtTurnout( track_p *trk, EPINX_T *ep, coOrd pos, DIST_T d0 ) +static BOOL_T MoveEndPtTurnout(track_p* trk, EPINX_T* ep, coOrd pos, DIST_T d0) { ANGLE_T angle0; DIST_T d; track_p trk1; - angle0 = GetTrkEndAngle(*trk,*ep); - d = FindDistance( GetTrkEndPos(*trk,*ep), pos); + angle0 = GetTrkEndAngle(*trk, *ep); + d = FindDistance(GetTrkEndPos(*trk, *ep), pos); if (d0 > 0.0) { d -= d0; if (d < 0.0) { - ErrorMessage( MSG_MOVED_BEFORE_END_TURNOUT ); + ErrorMessage(MSG_MOVED_BEFORE_END_TURNOUT); return FALSE; } - Translate( &pos, pos, angle0+180, d0 ); + Translate(&pos, pos, angle0 + 180, d0); } if (d > minLength) { - trk1 = NewStraightTrack( GetTrkEndPos(*trk,*ep), pos ); - CopyAttributes( *trk, trk1 ); - ConnectTracks( *trk, *ep, trk1, 0 ); + trk1 = NewStraightTrack(GetTrkEndPos(*trk, *ep), pos); + CopyAttributes(*trk, trk1); + ConnectTracks(*trk, *ep, trk1, 0); *trk = trk1; *ep = 1; - DrawNewTrack( *trk ); + DrawNewTrack(*trk); } return TRUE; } -static BOOL_T QueryTurnout( track_p trk, int query ) +static BOOL_T QueryTurnout(track_p trk, int query) { - switch ( query ) { + switch (query) { case Q_IGNORE_EASEMENT_ON_EXTEND: case Q_DRAWENDPTV_1: case Q_CAN_GROUP: @@ -1774,12 +3653,16 @@ static BOOL_T QueryTurnout( track_p trk, int query ) case Q_IS_TURNOUT: return TRUE; case Q_CAN_PARALLEL: - if( GetTrkEndPtCnt( trk ) == 2 && fabs( GetTrkEndAngle( trk, 0 ) - GetTrkEndAngle( trk, 1 )) == 180.0 ) + if (GetTrkEndPtCnt(trk) == 2 && fabs(GetTrkEndAngle(trk, 0) - GetTrkEndAngle(trk, 1)) == 180.0) return TRUE; else return FALSE; case Q_CAN_NEXT_POSITION: - return ( GetTrkEndPtCnt(trk) > 2 ); + { + PATHPTR_T path = GetPaths( trk ); // QueryTurnout + for ( path += strlen((char*)path) + 1; path[0] || path[1]; path++ ); + return ( path[2] != 0 ); + } case Q_CORNU_CAN_MODIFY: return FALSE; default: @@ -1789,54 +3672,70 @@ static BOOL_T QueryTurnout( track_p trk, int query ) EXPORT int doDrawTurnoutPosition = 1; -static wIndex_t drawTurnoutPositionWidth=3; +static wIndex_t drawTurnoutPositionWidth = 3; static void DrawTurnoutPositionIndicator( - track_p trk, - wDrawColor color ) + track_p trk, + wDrawColor color) { - struct extraData * xx = GetTrkExtraData(trk); - PATHPTR_T path = xx->pathCurr; - coOrd pos0, pos1; + struct extraDataCompound_t* xx = GET_EXTRA_DATA(trk, T_TURNOUT, extraDataCompound_t); + PATHPTR_T path, path1; + coOrd pos0 = zero, pos1; + trkSeg_p seg; + BOOL_T multiPart = FALSE; - if ( xx->pathCurr == xx->paths ) { - for ( path=xx->pathCurr+strlen((char *)xx->pathCurr); path[0] || path[1]; path++ ); - if ( path[2] == 0 ) - return; - } - for ( path=xx->pathCurr+strlen((char *)xx->pathCurr); path[0] || path[1]; path++ ) { - if ( path[0] == 0 ) { - pos0 = MapPathPos( xx, path[1], 0 ); - } else if ( path[1] == 0 ) { - pos1 = MapPathPos( xx, path[0], 1 ); - DrawLine( &tempD, pos0, pos1, drawTurnoutPositionWidth, color ); + // Only 1 path? Don't draw + if ( ! QueryTurnout( trk, Q_CAN_NEXT_POSITION ) ) + return; + + path = GetCurrPath(trk); + + //Is this a multi-part path? + path1 = path; + for (path1 += strlen((char*)path1) + 1; path1[0]; path1++); + if (path1[1] != 0) multiPart = TRUE; + + + for (path += strlen((char*)path); path[0] || path[1]; path++) { + + if (path[0] == 0) { + pos0 = MapPathPos(xx, path[1], 0); + if ((tempD.scale <= 10) || !multiPart) { + seg = MapPathSeg(xx, path[1]); + DrawSegsO(&tempD, trk, xx->orig, xx->angle, seg, 1, GetTrkGauge(trk), color, DTS_CENTERONLY); + } + } + else if (path[1] == 0) { + pos1 = MapPathPos(xx, path[0], 1); + if ((tempD.scale > 10) && multiPart) + DrawLine(&tempD, pos0, pos1, drawTurnoutPositionWidth, color); + else { + seg = MapPathSeg(xx, path[0]); + DrawSegsO(&tempD, trk, xx->orig, xx->angle, seg, 1, GetTrkGauge(trk), color, DTS_CENTERONLY); + } + } + else if ((tempD.scale <= 10) || !multiPart) { + seg = MapPathSeg(xx, path[0]); + DrawSegsO(&tempD, trk, xx->orig, xx->angle, seg, 1, GetTrkGauge(trk), color, DTS_CENTERONLY); } } } EXPORT void AdvanceTurnoutPositionIndicator( - track_p trk, - coOrd pos, - coOrd *posR, - ANGLE_T *angleR ) + track_p trk, + coOrd pos, + coOrd* posR, + ANGLE_T* angleR) { - struct extraData * xx = GetTrkExtraData(trk); - PATHPTR_T path; traverseTrack_t trvtrk; DIST_T dist; - if ( GetTrkType(trk) != T_TURNOUT ) - AbortProg( "nextTurnoutPosition" ); - - path = xx->pathCurr; - path += strlen((char *)path)+1; - while ( path[0] || path[1] ) - path++; - path += 2; - if ( *path == 0 ) - path = xx->paths; - xx->pathCurr = path; - if ( angleR == NULL || posR == NULL ) + if (GetTrkType(trk) != T_TURNOUT) + AbortProg("nextTurnoutPosition"); + + SetCurrPathIndex(trk, GetCurrPathIndex(trk) + 1); + InfoMessage(_("Turnout %d Path: %s"), GetTrkIndex(trk), GetCurrPath(trk)); + if (angleR == NULL || posR == NULL) return; trvtrk.trk = trk; trvtrk.length = 0; @@ -1844,17 +3743,17 @@ EXPORT void AdvanceTurnoutPositionIndicator( trvtrk.pos = *posR; trvtrk.angle = *angleR; dist = 0; - if ( !TraverseTurnout( &trvtrk, &dist ) ) + if (!TraverseTurnout(&trvtrk, &dist)) return; - if ( NormalizeAngle( trvtrk.angle-*angleR+90.0 ) > 180 ) - trvtrk.angle = NormalizeAngle( trvtrk.angle+180.0 ); + if (NormalizeAngle(trvtrk.angle - *angleR + 90.0) > 180) + trvtrk.angle = NormalizeAngle(trvtrk.angle + 180.0); *posR = trvtrk.pos; *angleR = trvtrk.angle; } /** * Create a parallel track for a turnout. - * + * * * \param trk IN existing track * \param pos IN ?? @@ -1866,60 +3765,56 @@ EXPORT void AdvanceTurnoutPositionIndicator( */ static BOOL_T MakeParallelTurnout( - track_p trk, - coOrd pos, - DIST_T sep, - DIST_T factor, - track_p * newTrk, - coOrd * p0R, - coOrd * p1R, - BOOL_T track) -{ - ANGLE_T angle = GetTrkEndAngle(trk,1); - struct extraData *xx, *yy; - coOrd *endPts; + track_p trk, + coOrd pos, + DIST_T sep, + DIST_T factor, + track_p* newTrk, + coOrd* p0R, + coOrd* p1R, + BOOL_T track) +{ + ANGLE_T angle = GetTrkEndAngle(trk, 1); + struct extraDataCompound_t* xx, * yy; + coOrd* endPts; trkEndPt_p endPt; int i; int option; DIST_T d; - if ( NormalizeAngle( FindAngle( GetTrkEndPos(trk,0), pos ) - GetTrkEndAngle(trk,1) ) < 180.0 ) + if (NormalizeAngle(FindAngle(GetTrkEndPos(trk, 0), pos) - GetTrkEndAngle(trk, 1)) < 180.0) angle += 90; else - angle -= 90; + angle -= 90; /* * get all endpoints of current piece and translate them for the new piece */ - endPts = MyMalloc( GetTrkEndPtCnt( trk ) * sizeof( coOrd )); - for( i = 0; i < GetTrkEndPtCnt( trk ); i++) { - Translate( &(endPts[ i ]), GetTrkEndPos( trk, i ), angle, sep ); + endPts = MyMalloc(GetTrkEndPtCnt(trk) * sizeof(coOrd)); + for (i = 0; i < GetTrkEndPtCnt(trk); i++) { + Translate(&(endPts[i]), GetTrkEndPos(trk, i), angle, sep); } /* - * get information about the current piece and copy data + * get information about the current piece and copy data */ - if( newTrk ) { + if (newTrk) { if (track) { - endPt = MyMalloc( GetTrkEndPtCnt( trk ) * sizeof( trkEndPt_t )); - endPt[ 0 ].pos = endPts[ 0 ]; - endPt[ 0 ].angle = GetTrkEndAngle( trk, 0 ); - endPt[ 1 ].pos = endPts[ 1 ]; - endPt[ 1 ].angle = GetTrkEndAngle( trk, 1 ); - - yy = GetTrkExtraData(trk); - - DIST_T * radii = NULL; - if (yy->special == TOcurved) { - radii = MyMalloc(GetTrkEndPtCnt(trk) * sizeof(DIST_T)); - for (int i=0;i<GetTrkEndPtCnt( trk );i++) { - radii[i] = DYNARR_N(DIST_T,yy->u.curved.radii,i); - } - } + endPt = MyMalloc(GetTrkEndPtCnt(trk) * sizeof(trkEndPt_t)); + endPt[0].pos = endPts[0]; + endPt[0].angle = GetTrkEndAngle(trk, 0); + endPt[1].pos = endPts[1]; + endPt[1].angle = GetTrkEndAngle(trk, 1); - *newTrk = NewCompound( T_TURNOUT, 0, endPt[ 0 ].pos, endPt[ 0 ].angle + 90.0, yy->title, 2, endPt, radii, yy->pathLen, (char *)yy->paths, yy->segCnt, yy->segs ); - xx = GetTrkExtraData(*newTrk); + yy = GET_EXTRA_DATA(trk, T_TURNOUT, extraDataCompound_t); + + + PATHPTR_T paths = GetPaths(trk); // MakeParallelTurnout + *newTrk = NewCompound(T_TURNOUT, 0, endPt[0].pos, endPt[0].angle + 90.0, + yy->title, 2, endPt, paths, + yy->segCnt, yy->segs); + xx = GET_EXTRA_DATA(*newTrk, T_TURNOUT, extraDataCompound_t); xx->customInfo = yy->customInfo; /* if (connection((int)curTurnoutEp).trk) { @@ -1927,62 +3822,66 @@ static BOOL_T MakeParallelTurnout( SetTrkScale( newTrk, curScaleInx ); } */ xx->special = yy->special; + xx->pathOverRide = yy->pathOverRide; + xx->pathNoCombine = yy->pathNoCombine; xx->u = yy->u; - SetDescriptionOrig( *newTrk ); + SetDescriptionOrig(*newTrk); xx->descriptionOff = zero; xx->descriptionSize = zero; SetTrkElev(*newTrk, GetTrkElevMode(trk), GetTrkElev(trk)); - GetTrkEndElev( trk, 0, &option, &d ); - SetTrkEndElev( *newTrk, 0, option, d, NULL ); - GetTrkEndElev( trk, 1, &option, &d ); - SetTrkEndElev( *newTrk, 1, option, d, NULL ); + GetTrkEndElev(trk, 0, &option, &d); + SetTrkEndElev(*newTrk, 0, option, d, NULL); + GetTrkEndElev(trk, 1, &option, &d); + SetTrkEndElev(*newTrk, 1, option, d, NULL); - MyFree( endPt ); - } else { + MyFree(endPt); + } + else { tempSegs(0).color = wDrawColorBlack; tempSegs(0).width = 0; tempSegs_da.cnt = 1; - tempSegs(0).type = track?SEG_STRTRK:SEG_STRLIN; - tempSegs(0).u.l.pos[0] = endPts[ 0 ]; - tempSegs(0).u.l.pos[1] = endPts[ 1 ]; - *newTrk = MakeDrawFromSeg( zero, 0.0, &tempSegs(0) ); + tempSegs(0).type = track ? SEG_STRTRK : SEG_STRLIN; + tempSegs(0).u.l.pos[0] = endPts[0]; + tempSegs(0).u.l.pos[1] = endPts[1]; + *newTrk = MakeDrawFromSeg(zero, 0.0, &tempSegs(0)); } - } else { + } + else { /* draw some temporary track while command is in process */ tempSegs(0).color = wDrawColorBlack; tempSegs(0).width = 0; tempSegs_da.cnt = 1; - tempSegs(0).type = track?SEG_STRTRK:SEG_STRLIN; - tempSegs(0).u.l.pos[0] = endPts[ 0 ]; - tempSegs(0).u.l.pos[1] = endPts[ 1 ]; + tempSegs(0).type = track ? SEG_STRTRK : SEG_STRLIN; + tempSegs(0).u.l.pos[0] = endPts[0]; + tempSegs(0).u.l.pos[1] = endPts[1]; } - if ( p0R ) *p0R = endPts[ 0 ]; - if ( p1R ) *p1R = endPts[ 1 ]; + if (p0R) *p0R = endPts[0]; + if (p1R) *p1R = endPts[1]; - MyFree( endPts ); + MyFree(endPts); return TRUE; } -static wBool_t CompareTurnout( track_cp trk1, track_cp trk2 ) +static wBool_t CompareTurnout(track_cp trk1, track_cp trk2) { - struct extraData *xx1 = GetTrkExtraData( trk1 ); - struct extraData *xx2 = GetTrkExtraData( trk2 ); - char * cp = message + strlen(message); - REGRESS_CHECK_POS( "Orig", xx1, xx2, orig ) - REGRESS_CHECK_ANGLE( "Angle", xx1, xx2, angle ) - REGRESS_CHECK_INT( "Handlaid", xx1, xx2, handlaid ) - REGRESS_CHECK_INT( "Flipped", xx1, xx2, flipped ) - REGRESS_CHECK_INT( "Ungrouped", xx1, xx2, ungrouped ) - REGRESS_CHECK_INT( "Split", xx1, xx2, split ) - /* desc orig is not stable - REGRESS_CHECK_POS( "DescOrig", xx1, xx2, descriptionOrig ) */ - REGRESS_CHECK_POS( "DescOff", xx1, xx2, descriptionOff ) - REGRESS_CHECK_POS( "DescSize", xx1, xx2, descriptionSize ) - return CompareSegs( xx1->segs, xx1->segCnt, xx1->segs, xx1->segCnt ); + struct extraDataCompound_t* xx1 = GET_EXTRA_DATA(trk1, T_TURNOUT, extraDataCompound_t); + struct extraDataCompound_t* xx2 = GET_EXTRA_DATA(trk2, T_TURNOUT, extraDataCompound_t); + char* cp = message + strlen(message); + REGRESS_CHECK_POS("Orig", xx1, xx2, orig) + REGRESS_CHECK_ANGLE("Angle", xx1, xx2, angle) + REGRESS_CHECK_INT("Handlaid", xx1, xx2, handlaid) + REGRESS_CHECK_INT("Flipped", xx1, xx2, flipped) + REGRESS_CHECK_INT("Ungrouped", xx1, xx2, ungrouped) + REGRESS_CHECK_INT("Split", xx1, xx2, split) + /* desc orig is not stable + REGRESS_CHECK_POS( "DescOrig", xx1, xx2, descriptionOrig ) */ + REGRESS_CHECK_POS("DescOff", xx1, xx2, descriptionOff) + REGRESS_CHECK_POS("DescSize", xx1, xx2, descriptionSize) + return CompareSegs(xx1->segs, xx1->segCnt, xx1->segs, xx1->segCnt); } static trackCmd_t turnoutCmds = { @@ -2022,7 +3921,7 @@ static trackCmd_t turnoutCmds = { NULL, CompareTurnout }; - + #ifdef TURNOUTCMD /***************************************** * @@ -2032,84 +3931,84 @@ static trackCmd_t turnoutCmds = { static coOrd maxTurnoutDim; -static void AddTurnout( void ); +static void AddTurnout(void); static wWin_p turnoutW; -static void RescaleTurnout( void ) +static void RescaleTurnout(void) { DIST_T xscale, yscale; - wPos_t ww, hh; + wWinPix_t ww, hh; DIST_T w, h; - wDrawGetSize( turnoutD.d, &ww, &hh ); - w = ww/turnoutD.dpi; - h = hh/turnoutD.dpi; - xscale = maxTurnoutDim.x/w; - yscale = maxTurnoutDim.y/h; - turnoutD.scale = max(xscale,yscale); + wDrawGetSize(turnoutD.d, &ww, &hh); + w = ww / turnoutD.dpi; + h = hh / turnoutD.dpi; + xscale = maxTurnoutDim.x / w; + yscale = maxTurnoutDim.y / h; + turnoutD.scale = max(xscale, yscale); if (turnoutD.scale == 0.0) turnoutD.scale = 1.0; - turnoutD.size.x = w*turnoutD.scale; - turnoutD.size.y = h*turnoutD.scale; + turnoutD.size.x = w * turnoutD.scale; + turnoutD.size.y = h * turnoutD.scale; return; } -static void TurnoutChange( long changes ) +static void TurnoutChange(long changes) { - static char * lastScaleName = NULL; + static char* lastScaleName = NULL; if (turnoutW == NULL) return; - wListSetIndex( turnoutListL, 0 ); - if ( (!wWinIsVisible(turnoutW)) || - ( ((changes&CHANGE_SCALE) == 0 || lastScaleName == curScaleName) && - (changes&CHANGE_PARAMS) == 0 ) ) + wListSetIndex(turnoutListL, 0); + if ((!wWinIsVisible(turnoutW)) || + (((changes & CHANGE_SCALE) == 0 || lastScaleName == curScaleName) && + (changes & CHANGE_PARAMS) == 0)) return; lastScaleName = curScaleName; //curTurnout = NULL; curTurnoutEp = 0; - wControlShow( (wControl_p)turnoutListL, FALSE ); - wListClear( turnoutListL ); + wControlShow((wControl_p)turnoutListL, FALSE); + wListClear(turnoutListL); maxTurnoutDim.x = maxTurnoutDim.y = 0.0; if (turnoutInfo_da.cnt <= 0) return; - curTurnout = TurnoutAdd( LABEL_TABBED|LABEL_MANUF|LABEL_PARTNO|LABEL_DESCR, GetLayoutCurScale(), turnoutListL, &maxTurnoutDim, -1 ); - wListSetIndex( turnoutListL, turnoutInx ); - wControlShow( (wControl_p)turnoutListL, TRUE ); + curTurnout = TurnoutAdd(LABEL_TABBED | LABEL_MANUF | LABEL_PARTNO | LABEL_DESCR, GetLayoutCurScale(), turnoutListL, &maxTurnoutDim, -1); + wListSetIndex(turnoutListL, turnoutInx); + wControlShow((wControl_p)turnoutListL, TRUE); if (curTurnout == NULL) { - wDrawClear( turnoutD.d ); + wDrawClear(turnoutD.d); return; } turnoutD.orig.x = -trackGauge; turnoutD.orig.y = -trackGauge; - maxTurnoutDim.x += 2*trackGauge; - maxTurnoutDim.y += 2*trackGauge; + maxTurnoutDim.x += 2 * trackGauge; + maxTurnoutDim.y += 2 * trackGauge; /*RescaleTurnout();*/ - RedrawTurnout(); + RedrawTurnout( turnoutD.d, NULL, 0, 0 ); return; } -static void RedrawTurnout() +static void RedrawTurnout( wDraw_p d, void * context, wWinPix_t x, wWinPix_t y ) { RescaleTurnout(); -LOG( log_turnout, 2, ( "SelTurnout(%s)\n", (curTurnout?curTurnout->title:"<NULL>") ) ) + LOG(log_turnout, 2, ("SelTurnout(%s)\n", (curTurnout ? curTurnout->title : "<NULL>"))) - wDrawClear( turnoutD.d ); + wDrawClear(turnoutD.d); if (curTurnout == NULL) { return; } turnoutD.orig.x = curTurnout->orig.x - trackGauge; turnoutD.orig.y = (curTurnout->size.y + curTurnout->orig.y) - turnoutD.size.y + trackGauge; - DrawSegs( &turnoutD, zero, 0.0, curTurnout->segs, curTurnout->segCnt, - trackGauge, wDrawColorBlack ); + DrawSegs(&turnoutD, zero, 0.0, curTurnout->segs, curTurnout->segCnt, + trackGauge, wDrawColorBlack); curTurnoutEp = 0; HilightEndPt(); } -static void TurnoutOk( void ) +static void TurnoutOk(void) { AddTurnout(); Reset(); @@ -2117,33 +4016,33 @@ static void TurnoutOk( void ) static void TurnoutDlgUpdate( - paramGroup_p pg, - int inx, - void * valueP ) + paramGroup_p pg, + int inx, + void* valueP) { - turnoutInfo_t * to; - if ( inx != I_LIST ) return; - to = (turnoutInfo_t*)wListGetItemContext( (wList_p)pg->paramPtr[inx].control, (wIndex_t)*(long*)valueP ); + turnoutInfo_t* to; + if (inx != I_LIST) return; + to = (turnoutInfo_t*)wListGetItemContext((wList_p)pg->paramPtr[inx].control, (wIndex_t) * (long*)valueP); AddTurnout(); curTurnout = to; - RedrawTurnout(); -/* ParamDialogOkActive( &turnoutPG, FALSE ); */ + RedrawTurnout( turnoutD.d, NULL, 0, 0 ); + /* ParamDialogOkActive( &turnoutPG, FALSE ); */ } static wIndex_t TOpickEndPoint( - coOrd p, - turnoutInfo_t *to ) + coOrd p, + turnoutInfo_t* to) { wIndex_t inx, i; DIST_T d, dd; coOrd posI; - d = FindDistance( p, to->endPt[0].pos ); + d = FindDistance(p, to->endPt[0].pos); inx = 0; - for ( i=1; i<to->endCnt; i++ ) { + for (i = 1; i < to->endCnt; i++) { posI = to->endPt[i].pos; - if ((dd=FindDistance(p, posI)) < d) { + if ((dd = FindDistance(p, posI)) < d) { d = dd; inx = i; } @@ -2152,57 +4051,55 @@ static wIndex_t TOpickEndPoint( } -static void HilightEndPt( void ) +static void HilightEndPt(void) { coOrd p, s; p.x = curTurnout->endPt[(int)curTurnoutEp].pos.x - trackGauge; p.y = curTurnout->endPt[(int)curTurnoutEp].pos.y - trackGauge; - s.x = s.y = trackGauge*2.0 /*+ turnoutD.minSize*/; - wDrawSetTempMode( turnoutD.d, TRUE ); - DrawHilight( &turnoutD, p, s, FALSE ); - wDrawSetTempMode( turnoutD.d, FALSE ); + s.x = s.y = trackGauge * 2.0 /*+ turnoutD.minSize*/; + DrawHilight(&turnoutD, p, s, FALSE); } static void SelTurnoutEndPt( - wIndex_t action, - coOrd pos ) + wIndex_t action, + coOrd pos) { if (action != C_DOWN) return; - curTurnoutEp = TOpickEndPoint( pos, curTurnout ); + curTurnoutEp = TOpickEndPoint(pos, curTurnout); HilightEndPt(); -LOG( log_turnout, 3, (" selected (action=%d) %ld\n", action, curTurnoutEp ) ) + LOG(log_turnout, 3, (" selected (action=%d) %ld\n", action, curTurnoutEp)) } #endif - + /**************************************** * * GRAPHICS COMMANDS * */ -/* - * STATE INFO - */ + /* + * STATE INFO + */ static struct { - int state; - coOrd pos; - coOrd place; - track_p trk; - ANGLE_T angle; - coOrd rot0, rot1; - } Dto; + int state; + coOrd pos; + coOrd place; + track_p trk; + ANGLE_T angle; + coOrd rot0, rot1; +} Dto; static dynArr_t vector_da; #define vector(N) DYNARR_N( vector_t, vector_da, N ) typedef struct { - DIST_T off; - ANGLE_T angle; - EPINX_T ep; - track_p trk; - } vector_t; + DIST_T off; + ANGLE_T angle; + EPINX_T ep; + track_p trk; +} vector_t; /* * PlaceTurnoutTrial @@ -2216,13 +4113,13 @@ typedef struct { * OUT Vector - An array of end points positions and offsets */ static void PlaceTurnoutTrial( - track_p *trkR, - coOrd *posR, - ANGLE_T *angle1R, - ANGLE_T *angle2R, - int *connCntR, - DIST_T *maxDR, - vector_t *v ) + track_p* trkR, + coOrd* posR, + ANGLE_T* angle1R, + ANGLE_T* angle2R, + int* connCntR, + DIST_T* maxDR, + vector_t* v) { coOrd pos = *posR; ANGLE_T aa; @@ -2235,82 +4132,86 @@ static void PlaceTurnoutTrial( DIST_T d, maxD = 0; coOrd testP = pos; - if (*trkR && (GetTrkDistance(*trkR,&testP)<trackGauge)) { //Have Track, stick with it unless outside bounds + if (*trkR && (GetTrkDistance(*trkR, &testP) < trackGauge)) { //Have Track, stick with it unless outside bounds trk = *trkR; pos = testP; - } else *trkR = trk = OnTrack( &pos, FALSE, TRUE ); - if ( (trk) != NULL && - !QueryTrack(trk,Q_CANNOT_PLACE_TURNOUT) && - (ep0 = PickEndPoint( pos, trk )) >= 0 && - ! ( GetTrkType(trk) == T_TURNOUT && - (trk1=GetTrkEndTrk(trk,ep0)) && - GetTrkType(trk1) == T_TURNOUT) && - ! GetLayerFrozen(GetTrkLayer(trk)) && - ! GetLayerModule(GetTrkLayer(trk))) { - epPos = GetTrkEndPos( trk, ep0 ); - d = FindDistance( pos, epPos ); + } + else *trkR = trk = OnTrack(&pos, FALSE, TRUE); + if ((trk) != NULL && + !QueryTrack(trk, Q_CANNOT_PLACE_TURNOUT) && + (ep0 = PickEndPoint(pos, trk)) >= 0 && + !(GetTrkType(trk) == T_TURNOUT && + (trk1 = GetTrkEndTrk(trk, ep0)) && + GetTrkType(trk1) == T_TURNOUT) && + !GetLayerFrozen(GetTrkLayer(trk)) && + !GetLayerModule(GetTrkLayer(trk))) { + epPos = GetTrkEndPos(trk, ep0); + d = FindDistance(pos, epPos); if (d <= minLength) pos = epPos; - if ( GetTrkType(trk) == T_TURNOUT ) { //Only on the end - ep0 = ep1 = PickEndPoint( pos, trk ); - angle = GetTrkEndAngle( trk, ep0 ); - } else { - angle = GetAngleAtPoint( trk, pos, &ep0, &ep1 ); - if (ep0==1) angle = NormalizeAngle(angle+180); //Reverse if curve backwards - } - angle = NormalizeAngle( angle + 180.0 ); - if ( NormalizeAngle( FindAngle( pos, *posR ) - angle ) < 180.0 && ep0 != ep1 ) - angle = NormalizeAngle( angle + 180 ); + if (GetTrkType(trk) == T_TURNOUT) { //Only on the end + ep0 = ep1 = PickEndPoint(pos, trk); + angle = GetTrkEndAngle(trk, ep0); + } + else { + angle = GetAngleAtPoint(trk, pos, &ep0, &ep1); + if (ep0 == 1) angle = NormalizeAngle(angle + 180); //Reverse if curve backwards + } + angle = NormalizeAngle(angle + 180.0); + if (NormalizeAngle(FindAngle(pos, *posR) - angle) < 180.0 && ep0 != ep1) + angle = NormalizeAngle(angle + 180); *angle2R = angle; epPos = curTurnout->endPt[(int)curTurnoutEp].pos; - *angle1R = angle = NormalizeAngle( angle - curTurnout->endPt[(int)curTurnoutEp].angle ); - Rotate( &epPos, zero, angle ); + *angle1R = angle = NormalizeAngle(angle - curTurnout->endPt[(int)curTurnoutEp].angle); + Rotate(&epPos, zero, angle); pos.x -= epPos.x; pos.y -= epPos.y; *posR = pos; //The place the Turnout end sits -LOG( log_turnout, 3, ( "placeTurnout T%d (%0.3f %0.3f) A%0.3f\n", - GetTrkIndex(trk), pos.x, pos.y, angle ) ) - /*InfoMessage( "Turnout(%d): Angle=%0.3f", GetTrkIndex(trk), angle );*/ - track_p ctrk = NULL; + LOG(log_turnout, 3, ("placeTurnout T%d (%0.3f %0.3f) A%0.3f\n", + GetTrkIndex(trk), pos.x, pos.y, angle)) + /*InfoMessage( "Turnout(%d): Angle=%0.3f", GetTrkIndex(trk), angle );*/ + track_p ctrk = NULL; int ccnt = 0; - DIST_T clarge = 100000; - for (i=0;i<curTurnout->endCnt;i++) { + DIST_T clarge = DIST_INF; + for (i = 0; i < curTurnout->endCnt; i++) { posI = curTurnout->endPt[i].pos; - epPos = AddCoOrd( pos, posI, angle ); - epAngle = NormalizeAngle( curTurnout->endPt[i].angle + angle ); + epPos = AddCoOrd(pos, posI, angle); + epAngle = NormalizeAngle(curTurnout->endPt[i].angle + angle); conPos = epPos; if ((trk = OnTrack(&conPos, FALSE, TRUE)) != NULL && !GetLayerFrozen(GetTrkLayer(trk)) && !GetLayerModule(GetTrkLayer(trk))) { - v->off = FindDistance( epPos, conPos ); - v->angle = FindAngle( epPos, conPos ); - if ( GetTrkType(trk) == T_TURNOUT ) { - ep0 = ep1 = PickEndPoint( conPos, trk ); - aa = GetTrkEndAngle( trk, ep0 ); - } else { - aa = GetAngleAtPoint( trk, conPos, &ep0, &ep1 ); + v->off = FindDistance(epPos, conPos); + v->angle = FindAngle(epPos, conPos); + if (GetTrkType(trk) == T_TURNOUT) { + ep0 = ep1 = PickEndPoint(conPos, trk); + aa = GetTrkEndAngle(trk, ep0); + } + else { + aa = GetAngleAtPoint(trk, conPos, &ep0, &ep1); if (ep0) //Backwards - so reverse - aa = NormalizeAngle(aa+180); + aa = NormalizeAngle(aa + 180); } v->ep = i; - aa = fabs(DifferenceBetweenAngles( aa, epAngle )); - if (QueryTrack(trk,Q_IS_CORNU) ) { //Make sure only two conns to each Cornu - int k=0; + aa = fabs(DifferenceBetweenAngles(aa, epAngle)); + if (QueryTrack(trk, Q_IS_CORNU)) { //Make sure only two conns to each Cornu + int k = 0; v->trk = trk; - for (int j=0; j<i;j++) { + for (int j = 0; j < i; j++) { if (vector(j).trk == trk) k++; } - if (k<2) { //Already two conns to this track + if (k < 2) { //Already two conns to this track connCnt++; if (v->off > maxD) maxD = v->off; v++; } - } else if (( IsClose(v->off) && (aa<connectAngle || aa>180-connectAngle) && - !( GetTrkType(trk) == T_TURNOUT && - (trk1=GetTrkEndTrk(trk,ep0)) && - GetTrkType(trk1) == T_TURNOUT )) ) { + } + else if ((IsClose(v->off) && (aa < connectAngle || aa>180 - connectAngle) && + !(GetTrkType(trk) == T_TURNOUT && + (trk1 = GetTrkEndTrk(trk, ep0)) && + GetTrkType(trk1) == T_TURNOUT))) { if (v->off > maxD) maxD = v->off; connCnt++; @@ -2318,7 +4219,8 @@ LOG( log_turnout, 3, ( "placeTurnout T%d (%0.3f %0.3f) A%0.3f\n", } } } - } else { + } + else { trk = NULL; *trkR = NULL; } @@ -2328,51 +4230,51 @@ LOG( log_turnout, 3, ( "placeTurnout T%d (%0.3f %0.3f) A%0.3f\n", static void PlaceTurnout( - coOrd pos, track_p trk ) + coOrd pos, track_p trk) { coOrd p, pos1, pos2; track_p trk1, trk2; ANGLE_T a, a1, a2, a3; int i, connCnt1, connCnt2; DIST_T d, maxD1, maxD2, sina; - vector_t *V, * maxV; + vector_t* V, * maxV; + - pos1 = Dto.place = Dto.pos = pos; -LOG( log_turnout, 1, ( "Place Turnout @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y ) ); + LOG(log_turnout, 1, ("Place Turnout @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y)); if (curTurnoutEp >= (long)curTurnout->endCnt) curTurnoutEp = 0; - DYNARR_SET( vector_t, vector_da, curTurnout->endCnt ); + DYNARR_SET(vector_t, vector_da, curTurnout->endCnt); if (trk) trk1 = trk; else trk1 = NULL; - PlaceTurnoutTrial( &trk1, &pos1, &a1, &a2, &connCnt1, &maxD1, &vector(0) ); + PlaceTurnoutTrial(&trk1, &pos1, &a1, &a2, &connCnt1, &maxD1, &vector(0)); if (connCnt1 > 0) { Dto.pos = pos1; //First track pos -LOG( log_turnout, 1, ( " trial 1 @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y ) ); + LOG(log_turnout, 1, (" trial 1 @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y)); Dto.trk = trk1; //Track Dto.angle = a1; //Angle of track to put down - if ( ((MyGetKeyState()&WKEY_SHIFT)==0) && (connCnt1 > 1) && (maxD1 >= 0.001) ) { //Adjust if not Shift + if (((MyGetKeyState() & WKEY_SHIFT) == 0) && (connCnt1 > 1) && (maxD1 >= 0.001)) { //Adjust if not Shift maxV = &vector(0); - for ( i=1; i<connCnt1; i++ ) { //Ignore first point + for (i = 1; i < connCnt1; i++) { //Ignore first point V = &vector(i); - if ( V->off > maxV->off ) { + if (V->off > maxV->off) { maxV = V; } } - a3 = NormalizeAngle( Dto.angle + curTurnout->endPt[maxV->ep].angle ); - a = NormalizeAngle( a2 - a3 ); + a3 = NormalizeAngle(Dto.angle + curTurnout->endPt[maxV->ep].angle); + a = NormalizeAngle(a2 - a3); sina = sin(D2R(a)); if (fabs(sina) > 0.01) { - d = maxV->off/sina; - if (NormalizeAngle( maxV->angle - a3) > 180) + d = maxV->off / sina; + if (NormalizeAngle(maxV->angle - a3) > 180) d = -d; - Translate( &pos2, pos, a2, d ); + Translate(&pos2, pos, a2, d); trk2 = trk1; - PlaceTurnoutTrial( &trk2, &pos2, &a2, &a, &connCnt2, &maxD2, &vector(0) ); - if ( connCnt2 >= connCnt1 && maxD2 < maxD1 ) { + PlaceTurnoutTrial(&trk2, &pos2, &a2, &a, &connCnt2, &maxD2, &vector(0)); + if (connCnt2 >= connCnt1 && maxD2 < maxD1) { Dto.pos = pos2; -LOG( log_turnout, 1, ( " trial 2 @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y ) ); + LOG(log_turnout, 1, (" trial 2 @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y)); Dto.trk = trk2; Dto.angle = a2; maxD1 = maxD2; @@ -2381,37 +4283,37 @@ LOG( log_turnout, 1, ( " trial 2 @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y ) ); } } } - if ( connCnt1 > 0 ) { - FormatCompoundTitle( listLabels, curTurnout->title ); - InfoMessage( _("%d connections, max distance %0.3f (%s)"), - connCnt1, PutDim(maxD1), message ); - } else { + if (connCnt1 > 0) { + FormatCompoundTitle(listLabels, curTurnout->title); + InfoMessage(_("%d connections, max distance %0.3f (%s)"), + connCnt1, PutDim(maxD1), message); + } + else { Dto.trk = NULL; - FormatCompoundTitle( listLabels, curTurnout->title ); - InfoMessage( _("0 connections (%s)"), message ); + FormatCompoundTitle(listLabels, curTurnout->title); + InfoMessage(_("0 connections (%s)"), message); p = curTurnout->endPt[(int)curTurnoutEp].pos; - Rotate( &p, zero, Dto.angle ); + Rotate(&p, zero, Dto.angle); Dto.pos.x = pos.x - p.x; Dto.pos.y = pos.y - p.y; -LOG( log_turnout, 1, ( " final @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y ) ); + LOG(log_turnout, 1, (" final @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y)); } } -static void AddTurnout( void ) +static void AddTurnout(void) { track_p newTrk; track_p trk, trk1; - struct extraData *xx; + struct extraDataCompound_t* xx; coOrd epPos; DIST_T d; ANGLE_T a, aa; EPINX_T ep0, ep1, epx, epy; - wIndex_t i,j; - wIndex_t titleLen; + wIndex_t i, j; typedef struct { track_p trk; EPINX_T ep; - } junk_t; + } junk_t; static dynArr_t connection_da; static dynArr_t leftover_da; #define connection(N) DYNARR_N( junk_t, connection_da, N ) @@ -2425,27 +4327,26 @@ static void AddTurnout( void ) return; if (curTurnout->segCnt < 1 || curTurnout->endCnt < 1) { - AbortProg( "addTurnout: bad cnt" ); + AbortProg("addTurnout: bad cnt"); } - UndoStart( _("Place New Turnout"), "addTurnout" ); - titleLen = strlen( curTurnout->title ); + UndoStart(_("Place New Turnout"), "addTurnout"); - DYNARR_SET( trkEndPt_t, tempEndPts_da, curTurnout->endCnt ); - DYNARR_SET( junk_t, connection_da, curTurnout->endCnt ); - DYNARR_SET( junk_t, leftover_da, curTurnout->endCnt ); + DYNARR_SET(trkEndPt_t, tempEndPts_da, curTurnout->endCnt); + DYNARR_SET(junk_t, connection_da, curTurnout->endCnt); + DYNARR_SET(junk_t, leftover_da, curTurnout->endCnt); - for (i=0; i<curTurnout->endCnt; i++ ) { + for (i = 0; i < curTurnout->endCnt; i++) { coOrd posI; posI = curTurnout->endPt[i].pos; - tempEndPts(i).pos = AddCoOrd( Dto.pos, posI, Dto.angle ); - tempEndPts(i).angle = NormalizeAngle( curTurnout->endPt[i].angle + Dto.angle ); + tempEndPts(i).pos = AddCoOrd(Dto.pos, posI, Dto.angle); + tempEndPts(i).angle = NormalizeAngle(curTurnout->endPt[i].angle + Dto.angle); } - AuditTracks( "addTurnout begin" ); + AuditTracks("addTurnout begin"); - for (i=0;i<curTurnout->endCnt;i++) { - AuditTracks( "addTurnout [%d]", i ); + for (i = 0; i < curTurnout->endCnt; i++) { + AuditTracks("addTurnout [%d]", i); connection(i).trk = leftover(i).trk = NULL; connection(i).ep = -1; leftover(i).ep = -1; @@ -2453,70 +4354,72 @@ static void AddTurnout( void ) epPos = tempEndPts(i).pos; if ((trk = OnTrack(&epPos, FALSE, TRUE)) != NULL && //Adjust epPos onto existing track (!GetLayerFrozen(GetTrkLayer(trk))) && - (!GetLayerModule(GetTrkLayer(trk))) && - (!QueryTrack(trk,Q_CANNOT_PLACE_TURNOUT)) ) { -LOG( log_turnout, 1, ( "ep[%d] on T%d @(%0.3f %0.3f)\n", - i, GetTrkIndex(trk), epPos.x, epPos.y ) ) - DIST_T dd = 10000.0; + (!GetLayerModule(GetTrkLayer(trk))) && + (!QueryTrack(trk, Q_CANNOT_PLACE_TURNOUT))) { + LOG(log_turnout, 1, ("ep[%d] on T%d @(%0.3f %0.3f)\n", + i, GetTrkIndex(trk), epPos.x, epPos.y)) + DIST_T dd = DIST_INF; int nearest = -1; - for (int j=0;j<curTurnout->endCnt;j++) { - if (j<i && (connection(j).trk == trk)) { + for (int j = 0; j < curTurnout->endCnt; j++) { + if (j < i && (connection(j).trk == trk)) { nearest = -1; goto nextEnd; //Track already chosen in use } - if (dd>FindDistance(epPos,tempEndPts(j).pos)) { - dd = FindDistance(epPos,tempEndPts(j).pos); + if (dd > FindDistance(epPos, tempEndPts(j).pos)) { + dd = FindDistance(epPos, tempEndPts(j).pos); nearest = j; } } if (nearest != i) continue; //Not this one - d = FindDistance( tempEndPts(i).pos, epPos ); - if ( GetTrkType(trk) == T_TURNOUT ) { - ep0 = ep1 = PickEndPoint( epPos, trk ); - a = GetTrkEndAngle( trk, ep0 ); - } else { - a = GetAngleAtPoint( trk, epPos, &ep0, &ep1 ); - } - aa = fabs(DifferenceBetweenAngles( a , tempEndPts(i).angle)); - if ((QueryTrack(trk,Q_IS_CORNU) && (d<trackGauge*2)) || - (( IsClose(d) && ( ((ep0!=ep1) && (aa<=connectAngle)) || ((aa<=connectAngle) || (aa>180-connectAngle)) ) && - ! ( GetTrkType(trk) == T_TURNOUT && - (trk1=GetTrkEndTrk(trk,ep0)) && - GetTrkType(trk1) == T_TURNOUT )) ) ) { + d = FindDistance(tempEndPts(i).pos, epPos); + if (GetTrkType(trk) == T_TURNOUT) { + ep0 = ep1 = PickEndPoint(epPos, trk); + a = GetTrkEndAngle(trk, ep0); + } + else { + a = GetAngleAtPoint(trk, epPos, &ep0, &ep1); + } + aa = fabs(DifferenceBetweenAngles(a, tempEndPts(i).angle)); + if ((QueryTrack(trk, Q_IS_CORNU) && (d < trackGauge * 2)) || + ((IsClose(d) && (((ep0 != ep1) && (aa <= connectAngle)) || ((aa <= connectAngle) || (aa > 180 - connectAngle))) && + !(GetTrkType(trk) == T_TURNOUT && + (trk1 = GetTrkEndTrk(trk, ep0)) && + GetTrkType(trk1) == T_TURNOUT)))) { /* ... if they are close enough to a track and line up */ - if (aa<90) { - epx = ep1; - epy = ep0; - } else { - epx = ep0; - epy = ep1; + if (aa < 90) { + epx = ep1; + epy = ep0; } -LOG( log_turnout, 1, ( " Attach! epx=%d\n", epx ) ) - if ( (epx != epy) && - ((d=FindDistance(GetTrkEndPos(trk,epy), epPos)) < minLength) && - ((trk1=GetTrkEndTrk(trk,epy)) != NULL) ) { - epx = GetEndPtConnectedToMe( trk1, trk ); - trk = trk1; + else { + epx = ep0; + epy = ep1; } + LOG(log_turnout, 1, (" Attach! epx=%d\n", epx)) + if ((epx != epy) && + ((d = FindDistance(GetTrkEndPos(trk, epy), epPos)) < minLength) && + ((trk1 = GetTrkEndTrk(trk, epy)) != NULL)) { + epx = GetEndPtConnectedToMe(trk1, trk); + trk = trk1; + } /* split the track at the intersection point */ - AuditTracks( "addTurnout [%d] before splitTrack", i ); - if (SplitTrack( trk, epPos, epx, &leftover(i).trk, TRUE )) { - AuditTracks( "addTurnout [%d], after splitTrack", i ); + AuditTracks("addTurnout [%d] before splitTrack", i); + if (SplitTrack(trk, epPos, epx, &leftover(i).trk, TRUE)) { + AuditTracks("addTurnout [%d], after splitTrack", i); /* remember so we can fix up connection later */ connection(i).trk = trk; connection(i).ep = epx; if (leftover(i).trk != NULL) { - leftover(i).ep = 1-epx; + leftover(i).ep = 1 - epx; /* did we already split this track? */ - for (j=0;j<i;j++) { - if ( connection(i).trk == leftover(j).trk ) { + for (j = 0; j < i; j++) { + if (connection(i).trk == leftover(j).trk) { /* yes. Remove the latest leftover piece */ -LOG( log_turnout, 1, ( " deleting leftover T%d\n", - GetTrkIndex(leftover(i).trk) ) ) - AuditTracks( "addTurnout [%d] before delete", i ); - UndrawNewTrack( leftover(i).trk ); - DeleteTrack( leftover(i).trk, FALSE ); - AuditTracks( "addTurnout [%d] before delete", i ); + LOG(log_turnout, 1, (" deleting leftover T%d\n", + GetTrkIndex(leftover(i).trk))) + AuditTracks("addTurnout [%d] before delete", i); + UndrawNewTrack(leftover(i).trk); + DeleteTrack(leftover(i).trk, FALSE); + AuditTracks("addTurnout [%d] before delete", i); leftover(i).trk = NULL; leftover(i).ep = -1; leftover(j).trk = NULL; //Forget this leftover @@ -2528,112 +4431,110 @@ LOG( log_turnout, 1, ( " deleting leftover T%d\n", } } } -nextEnd:; + nextEnd:; } - AuditTracks( "addTurnout after loop" ); + AuditTracks("addTurnout after loop"); /* * copy data */ - newTrk = NewCompound( T_TURNOUT, 0, Dto.pos, Dto.angle, curTurnout->title, tempEndPts_da.cnt, &tempEndPts(0), NULL, curTurnout->pathLen, (char *)curTurnout->paths, curTurnout->segCnt, curTurnout->segs ); - xx = GetTrkExtraData(newTrk); + newTrk = NewCompound(T_TURNOUT, 0, Dto.pos, Dto.angle, curTurnout->title, tempEndPts_da.cnt, &tempEndPts(0), GetParamPaths(curTurnout), curTurnout->segCnt, curTurnout->segs); + xx = GET_EXTRA_DATA(newTrk, T_TURNOUT, extraDataCompound_t); xx->customInfo = curTurnout->customInfo; if (connection((int)curTurnoutEp).trk) { - CopyAttributes( connection((int)curTurnoutEp).trk, newTrk ); - SetTrkScale( newTrk, GetLayoutCurScale()); + CopyAttributes(connection((int)curTurnoutEp).trk, newTrk); + SetTrkScale(newTrk, GetLayoutCurScale()); } xx->special = curTurnout->special; - if (xx->special == TOcurved) { - DYNARR_SET(DIST_T,xx->u.curved.radii,curTurnout->endCnt); - for (int i=0;i<curTurnout->endCnt;i++) { - DYNARR_N(DIST_T,xx->u.curved.radii,i) = DYNARR_N(DIST_T,curTurnout->u.curved.radii,i); - } - } xx->u = curTurnout->u; + xx->pathOverRide = curTurnout->pathOverRide; + xx->pathNoCombine = curTurnout->pathNoCombine; /* Make the connections */ visible = FALSE; no_ties = FALSE; noConnections = TRUE; - AuditTracks( "addTurnout T%d before connection", GetTrkIndex(newTrk) ); - for (i=0;i<curTurnout->endCnt;i++) { - if ( connection(i).trk != NULL ) { - if (GetTrkEndTrk(connection(i).trk,connection(i).ep)) continue; - p0 = GetTrkEndPos( newTrk, i ); - p1 = GetTrkEndPos( connection(i).trk, connection(i).ep ); - ANGLE_T a0 = GetTrkEndAngle( newTrk, i); - ANGLE_T a1 = GetTrkEndAngle( connection(i).trk, connection(i).ep ); - ANGLE_T a = fabs(DifferenceBetweenAngles(a0+180,a1)); - d = FindDistance( p0, p1 ); - if (QueryTrack(connection(i).trk,Q_IS_CORNU)) { - ANGLE_T a = DifferenceBetweenAngles(FindAngle(p0,p1),a0); - if (IsClose(d) || fabs(a)<=90.0) { + AuditTracks("addTurnout T%d before connection", GetTrkIndex(newTrk)); + for (i = 0; i < curTurnout->endCnt; i++) { + if (connection(i).trk != NULL) { + if (GetTrkEndTrk(connection(i).trk, connection(i).ep)) continue; + p0 = GetTrkEndPos(newTrk, i); + p1 = GetTrkEndPos(connection(i).trk, connection(i).ep); + ANGLE_T a0 = GetTrkEndAngle(newTrk, i); + ANGLE_T a1 = GetTrkEndAngle(connection(i).trk, connection(i).ep); + ANGLE_T a = fabs(DifferenceBetweenAngles(a0 + 180, a1)); + d = FindDistance(p0, p1); + if (QueryTrack(connection(i).trk, Q_IS_CORNU)) { + ANGLE_T a = DifferenceBetweenAngles(FindAngle(p0, p1), a0); + if (IsClose(d) || fabs(a) <= 90.0) { trk1 = connection(i).trk; ep0 = connection(i).ep; - if (GetTrkEndTrk(trk1,ep0)) continue; - DrawEndPt( &mainD, trk1, ep0, wDrawColorWhite ); + if (GetTrkEndTrk(trk1, ep0)) continue; + DrawEndPt(&mainD, trk1, ep0, wDrawColorWhite); trackParams_t params; - GetTrackParams( PARAMS_EXTEND, newTrk, GetTrkEndPos(newTrk,i), ¶ms); - SetCornuEndPt(trk1, ep0, GetTrkEndPos(newTrk,i), params.arcP, NormalizeAngle(params.angle+180.0), params.arcR); - ConnectTracks(newTrk,i,trk1,ep0); - DrawEndPt( &mainD, trk1, ep0, wDrawColorBlack ); + GetTrackParams(PARAMS_EXTEND, newTrk, GetTrkEndPos(newTrk, i), ¶ms); + SetCornuEndPt(trk1, ep0, GetTrkEndPos(newTrk, i), params.arcP, NormalizeAngle(params.angle + 180.0), params.arcR); + ConnectTracks(newTrk, i, trk1, ep0); + DrawEndPt(&mainD, trk1, ep0, wDrawColorBlack); } - } else if ( d < connectDistance && (a<=connectAngle)) { + } + else if (d < connectDistance && (a <= connectAngle)) { noConnections = FALSE; trk1 = connection(i).trk; ep0 = connection(i).ep; - DrawEndPt( &mainD, trk1, ep0, wDrawColorWhite ); - ConnectTracks( newTrk, i, trk1, ep0 ); + DrawEndPt(&mainD, trk1, ep0, wDrawColorWhite); + ConnectTracks(newTrk, i, trk1, ep0); visible |= GetTrkVisible(trk1); no_ties |= GetTrkNoTies(trk1); - DrawEndPt( &mainD, trk1, ep0, wDrawColorBlack ); + DrawEndPt(&mainD, trk1, ep0, wDrawColorBlack); } } } if (noConnections) visible = TRUE; - SetTrkVisible( newTrk, visible); + SetTrkVisible(newTrk, visible); SetTrkNoTies(newTrk, no_ties); SetTrkBridge(newTrk, FALSE); - AuditTracks( "addTurnout T%d before dealing with leftovers", GetTrkIndex(newTrk) ); + AuditTracks("addTurnout T%d before dealing with leftovers", GetTrkIndex(newTrk)); /* deal with the leftovers */ - for (i=0;i<curTurnout->endCnt;i++) { - if ( (trk=leftover(i).trk) != NULL && !IsTrackDeleted(trk) ) { + for (i = 0; i < curTurnout->endCnt; i++) { + if ((trk = leftover(i).trk) != NULL) { + ASSERT( !IsTrackDeleted(trk) ); /* move endPt beyond the turnout */ /* it it is short then delete it */ coOrd off; DIST_T maxX; track_p lt = leftover(i).trk; - if (QueryTrack(lt,Q_IS_CORNU)) { + if (QueryTrack(lt, Q_IS_CORNU)) { UndrawNewTrack(lt); - DeleteTrack(lt,TRUE); + DeleteTrack(lt, TRUE); leftover(i).trk = NULL; continue; } - EPINX_T ep, le = leftover(i).ep, nearest_ep =-1; + EPINX_T ep, le = leftover(i).ep, nearest_ep = -1; coOrd pos, nearest_pos = zero; ANGLE_T nearest_angle = 0.0; DIST_T nearest_radius = 0.0; coOrd nearest_center = zero; trackParams_t params; maxX = 0.0; - DIST_T dd = 10000.0; - a = NormalizeAngle( GetTrkEndAngle(lt,le) + 180.0 ); - for (ep=0; ep<curTurnout->endCnt; ep++) { - FindPos( &off, NULL, GetTrkEndPos(newTrk,ep), GetTrkEndPos(lt,le), a, 100000.0 ); - pos = GetTrkEndPos(newTrk,ep); + DIST_T dd = DIST_INF; + a = NormalizeAngle(GetTrkEndAngle(lt, le) + 180.0); + for (ep = 0; ep < curTurnout->endCnt; ep++) { + FindPos(&off, NULL, GetTrkEndPos(newTrk, ep), GetTrkEndPos(lt, le), a, DIST_INF); + pos = GetTrkEndPos(newTrk, ep); DIST_T d = GetTrkDistance(lt, &pos); - if ((d<dd) && ( d<trackGauge/2)) { - ANGLE_T a = GetTrkEndAngle( lt, le ); - ANGLE_T a2 = fabs(DifferenceBetweenAngles(GetTrkEndAngle(newTrk,ep),a+180)); - if (GetTrkEndTrk(newTrk,ep)==NULL) { //Not if joined already - if (a2<90 && QueryTrack(lt,Q_IS_CORNU)) { //And Cornu in the right direction - GetTrackParams( PARAMS_EXTEND, newTrk, GetTrkEndPos(newTrk,ep), ¶ms); - nearest_pos = GetTrkEndPos(newTrk,ep); - nearest_angle = NormalizeAngle(params.angle+180.0); + if ((d < dd) && (d < trackGauge / 2)) { + ANGLE_T a = GetTrkEndAngle(lt, le); + ANGLE_T a2 = fabs(DifferenceBetweenAngles(GetTrkEndAngle(newTrk, ep), a + 180)); + if (GetTrkEndTrk(newTrk, ep) == NULL) { //Not if joined already + if (a2 < 90 && QueryTrack(lt, Q_IS_CORNU)) { //And Cornu in the right direction + GetTrackParams(PARAMS_EXTEND, newTrk, GetTrkEndPos(newTrk, ep), ¶ms); + nearest_pos = GetTrkEndPos(newTrk, ep); + nearest_angle = NormalizeAngle(params.angle + 180.0); nearest_radius = params.arcR; nearest_center = params.arcP; nearest_ep = ep; @@ -2646,30 +4547,33 @@ nextEnd:; } maxX += trackGauge; pos = Dto.pos; - if (QueryTrack(lt,Q_IS_CORNU)) { - if (nearest_ep >=0) { + if (QueryTrack(lt, Q_IS_CORNU)) { + if (nearest_ep >= 0) { SetCornuEndPt(lt, le, nearest_pos, nearest_center, nearest_angle, nearest_radius); - ConnectTracks(newTrk,nearest_ep,lt,le); - } else { + ConnectTracks(newTrk, nearest_ep, lt, le); + } + else { UndrawNewTrack(lt); - DeleteTrack(lt,TRUE); + DeleteTrack(lt, TRUE); + leftover(i).trk = NULL; } - } else { - AuditTracks( "addTurnout T%d[%d] before trimming L%d[%d]", GetTrkIndex(newTrk), i, GetTrkIndex(lt), le ); - wBool_t rc = TrimTrack( lt, le, maxX, nearest_pos, nearest_angle, nearest_radius, nearest_center ); - AuditTracks( "addTurnout T%d[%d] after trimming L%d[%d]", GetTrkIndex(newTrk), i, GetTrkIndex(lt), le ); + } + else { + AuditTracks("addTurnout T%d[%d] before trimming L%d[%d]", GetTrkIndex(newTrk), i, GetTrkIndex(lt), le); + wBool_t rc = TrimTrack(lt, le, maxX, nearest_pos, nearest_angle, nearest_radius, nearest_center); + AuditTracks("addTurnout T%d[%d] after trimming L%d[%d]", GetTrkIndex(newTrk), i, GetTrkIndex(lt), le); } } } - SetDescriptionOrig( newTrk ); + SetDescriptionOrig(newTrk); xx->descriptionOff = zero; xx->descriptionSize = zero; - DrawNewTrack( newTrk ); + DrawNewTrack(newTrk); - AuditTracks( "addTurnout T%d returns", GetTrkIndex(newTrk) ); + AuditTracks("addTurnout T%d returns", GetTrkIndex(newTrk)); UndoEnd(); Dto.state = 0; Dto.trk = NULL; @@ -2677,14 +4581,14 @@ nextEnd:; } -static void TurnoutRotate( void * pangle ) +static void TurnoutRotate(void* pangle) { if (Dto.state == 0) return; - ANGLE_T angle = (ANGLE_T)(long)pangle; + ANGLE_T angle = (ANGLE_T)VP2L(pangle); angle /= 1000.0; Dto.pos = cmdMenuPos; - Rotate( &Dto.pos, cmdMenuPos, angle ); + Rotate(&Dto.pos, cmdMenuPos, angle); Dto.angle += angle; TempRedraw(); // TurnoutRotate } @@ -2692,59 +4596,59 @@ static void TurnoutRotate( void * pangle ) static dynArr_t anchors_da; #define anchors(N) DYNARR_N(trkSeg_t,anchors_da,N) -void static CreateArrowAnchor(coOrd pos,ANGLE_T a,DIST_T len) { - DYNARR_APPEND(trkSeg_t,anchors_da,1); - int i = anchors_da.cnt-1; +void static CreateArrowAnchor(coOrd pos, ANGLE_T a, DIST_T len) { + DYNARR_APPEND(trkSeg_t, anchors_da, 1); + int i = anchors_da.cnt - 1; anchors(i).type = SEG_STRLIN; anchors(i).width = 0; anchors(i).u.l.pos[0] = pos; - Translate(&anchors(i).u.l.pos[1],pos,NormalizeAngle(a+135),len); + Translate(&anchors(i).u.l.pos[1], pos, NormalizeAngle(a + 135), len); anchors(i).color = wDrawColorBlue; - DYNARR_APPEND(trkSeg_t,anchors_da,1); - i = anchors_da.cnt-1; + DYNARR_APPEND(trkSeg_t, anchors_da, 1); + i = anchors_da.cnt - 1; anchors(i).type = SEG_STRLIN; anchors(i).width = 0; anchors(i).u.l.pos[0] = pos; - Translate(&anchors(i).u.l.pos[1],pos,NormalizeAngle(a-135),len); + Translate(&anchors(i).u.l.pos[1], pos, NormalizeAngle(a - 135), len); anchors(i).color = wDrawColorBlue; } void static CreateRotateAnchor(coOrd pos) { - DIST_T d = tempD.scale*0.15; - DYNARR_APPEND(trkSeg_t,anchors_da,1); - int i = anchors_da.cnt-1; + DIST_T d = tempD.scale * 0.15; + DYNARR_APPEND(trkSeg_t, anchors_da, 1); + int i = anchors_da.cnt - 1; anchors(i).type = SEG_CRVLIN; anchors(i).width = 0.5; anchors(i).u.c.center = pos; anchors(i).u.c.a0 = 180.0; anchors(i).u.c.a1 = 360.0; - anchors(i).u.c.radius = d*2; + anchors(i).u.c.radius = d * 2; anchors(i).color = wDrawColorAqua; coOrd head; //Arrows - for (int j=0;j<3;j++) { - Translate(&head,pos,j*120,d*2); - CreateArrowAnchor(head,NormalizeAngle((j*120)+90),d); + for (int j = 0; j < 3; j++) { + Translate(&head, pos, j * 120, d * 2); + CreateArrowAnchor(head, NormalizeAngle((j * 120) + 90), d); } } void static CreateMoveAnchor(coOrd pos) { - DYNARR_SET(trkSeg_t,anchors_da,anchors_da.cnt+5); - DrawArrowHeads(&DYNARR_N(trkSeg_t,anchors_da,anchors_da.cnt-5),pos,0,TRUE,wDrawColorBlue); - DYNARR_SET(trkSeg_t,anchors_da,anchors_da.cnt+5); - DrawArrowHeads(&DYNARR_N(trkSeg_t,anchors_da,anchors_da.cnt-5),pos,90,TRUE,wDrawColorBlue); + DYNARR_SET(trkSeg_t, anchors_da, anchors_da.cnt + 5); + DrawArrowHeads(&DYNARR_N(trkSeg_t, anchors_da, anchors_da.cnt - 5), pos, 0, TRUE, wDrawColorBlue); + DYNARR_SET(trkSeg_t, anchors_da, anchors_da.cnt + 5); + DrawArrowHeads(&DYNARR_N(trkSeg_t, anchors_da, anchors_da.cnt - 5), pos, 90, TRUE, wDrawColorBlue); } - + /** * Process the mouse events for laying track. * * \param action IN event type - * \param pos IN mouse position + * \param pos IN mouse position * \return next state */ EXPORT STATUS_T CmdTurnoutAction( - wAction_t action, - coOrd pos ) + wAction_t action, + coOrd pos) { ANGLE_T angle; static BOOL_T validAngle; @@ -2760,155 +4664,154 @@ EXPORT STATUS_T CmdTurnoutAction( Dto.state = 0; Dto.trk = NULL; Dto.angle = 0.0; - DYNARR_RESET(trkSeg_t,anchors_da); + DYNARR_RESET(trkSeg_t, anchors_da); + SetAllTrackSelect(FALSE); return C_CONTINUE; case wActionMove: - DYNARR_RESET(trkSeg_t,anchors_da); - if (Dto.state && (MyGetKeyState()&WKEY_CTRL)) { + DYNARR_RESET(trkSeg_t, anchors_da); + if (Dto.state && (MyGetKeyState() & WKEY_CTRL)) { CreateRotateAnchor(pos); - } else { + } + else { CreateMoveAnchor(pos); } return C_CONTINUE; break; case C_DOWN: - DYNARR_RESET(trkSeg_t,anchors_da); - if ( curTurnout == NULL ) return C_CONTINUE; - PlaceTurnout( pos, NULL ); + DYNARR_RESET(trkSeg_t, anchors_da); + if (curTurnout == NULL) return C_CONTINUE; + PlaceTurnout(pos, NULL); Dto.state = 1; - CreateMoveAnchor(pos); return C_CONTINUE; case C_MOVE: - DYNARR_RESET(trkSeg_t,anchors_da); - if ( curTurnout == NULL ) return C_CONTINUE; - if ( curTurnoutEp >= (long)curTurnout->endCnt ) + DYNARR_RESET(trkSeg_t, anchors_da); + if (curTurnout == NULL) return C_CONTINUE; + if (curTurnoutEp >= (long)curTurnout->endCnt) curTurnoutEp = 0; Dto.state = 1; - PlaceTurnout( pos, Dto.trk ); - CreateMoveAnchor(pos); + PlaceTurnout(pos, Dto.trk); return C_CONTINUE; case C_UP: - DYNARR_RESET(trkSeg_t,anchors_da); - CreateMoveAnchor(pos); - InfoMessage( _("Left-Drag to place, Ctrl+Left-Drag or Right-Drag to Rotate, Space or Enter to accept, Esc to Cancel") ); + DYNARR_RESET(trkSeg_t, anchors_da); + InfoMessage(_("Left-Drag to place, Ctrl+Left-Drag or Right-Drag to Rotate, Space or Enter to accept, Esc to Cancel")); return C_CONTINUE; case C_RDOWN: - DYNARR_RESET(trkSeg_t,anchors_da); - if ( curTurnout == NULL ) return C_CONTINUE; + DYNARR_RESET(trkSeg_t, anchors_da); + if (curTurnout == NULL) return C_CONTINUE; if (Dto.state == 0) { Dto.pos = pos; // If first, use pos, otherwise use current -LOG( log_turnout, 1, ( "RDOWN @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y ) ); + LOG(log_turnout, 1, ("RDOWN @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y)); } Dto.rot0 = Dto.rot1 = pos; - CreateRotateAnchor(pos); Dto.state = 2; origPos = Dto.pos; #ifdef NEWROTATE origAngle = Dto.angle; #else - Rotate( &origPos, Dto.rot0, -(Dto.angle + curTurnout->endPt[(int)curTurnoutEp].angle) ); + Rotate(&origPos, Dto.rot0, -(Dto.angle + curTurnout->endPt[(int)curTurnoutEp].angle)); #endif validAngle = FALSE; return C_CONTINUE; case C_RMOVE: - DYNARR_RESET(trkSeg_t,anchors_da); - if ( curTurnout == NULL ) return C_CONTINUE; + DYNARR_RESET(trkSeg_t, anchors_da); + if (curTurnout == NULL) return C_CONTINUE; Dto.rot1 = pos; - if ( FindDistance(Dto.rot0, Dto.rot1) > 0.1*mainD.scale ) { - angle = FindAngle( Dto.rot0, Dto.rot1 ); + if (FindDistance(Dto.rot0, Dto.rot1) > 0.1 * mainD.scale) { + angle = FindAngle(Dto.rot0, Dto.rot1); if (!validAngle) { baseAngle = angle/* - Dto.angle*/; validAngle = TRUE; } Dto.pos = origPos; -LOG( log_turnout, 1, ( "RMOVE pre @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y ) ); + LOG(log_turnout, 1, ("RMOVE pre @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y)); #ifdef NEWROTATE angle -= baseAngle; - Dto.angle = NormalizeAngle( origAngle + angle ); + Dto.angle = NormalizeAngle(origAngle + angle); #else angle += 180.0; Dto.angle = angle - curTurnout->endPt[(int)curTurnoutEp].angle; #endif - Rotate( &Dto.pos, Dto.rot0, angle ); -LOG( log_turnout, 1, ( "RMOVE post @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y ) ); + Rotate(&Dto.pos, Dto.rot0, angle); + LOG(log_turnout, 1, ("RMOVE post @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y)); } - FormatCompoundTitle( listLabels, curTurnout->title ); - InfoMessage( _("Angle = %0.3f (%s)"), PutAngle( NormalizeAngle(Dto.angle + 90.0) ), message ); + FormatCompoundTitle(listLabels, curTurnout->title); + InfoMessage(_("Angle = %0.3f (%s)"), PutAngle(NormalizeAngle(Dto.angle + 90.0)), message); Dto.state = 2; - CreateRotateAnchor(Dto.rot0); return C_CONTINUE; case C_RUP: - DYNARR_RESET(trkSeg_t,anchors_da); - if ( curTurnout == NULL ) return C_CONTINUE; + DYNARR_RESET(trkSeg_t, anchors_da); + if (curTurnout == NULL) return C_CONTINUE; Dto.state = 1; - CreateMoveAnchor(pos); - InfoMessage( _("Left-Drag to place, Ctrl+Left-Drag or Right-Drag to Rotate, Space or Enter to accept, Esc to Cancel") ); + InfoMessage(_("Left-Drag to place, Ctrl+Left-Drag or Right-Drag to Rotate, Space or Enter to accept, Esc to Cancel")); return C_CONTINUE; case C_LCLICK: - DYNARR_RESET(trkSeg_t,anchors_da); - if ( curTurnout == NULL ) return C_CONTINUE; - if ( MyGetKeyState() & WKEY_SHIFT ) { + DYNARR_RESET(trkSeg_t, anchors_da); + if (curTurnout == NULL) return C_CONTINUE; + if (MyGetKeyState() & WKEY_SHIFT) { angle = curTurnout->endPt[(int)curTurnoutEp].angle; curTurnoutEp++; if (curTurnoutEp >= (long)curTurnout->endCnt) curTurnoutEp = 0; if (Dto.trk == NULL) - Dto.angle = NormalizeAngle( Dto.angle + (angle - curTurnout->endPt[(int)curTurnoutEp].angle ) ); - PlaceTurnout( Dto.place, Dto.trk ); - } else { - CmdTurnoutAction( C_DOWN, pos ); - CmdTurnoutAction( C_UP, pos ); + Dto.angle = NormalizeAngle(Dto.angle + (angle - curTurnout->endPt[(int)curTurnoutEp].angle)); + PlaceTurnout(Dto.place, Dto.trk); + } + else { + CmdTurnoutAction(C_DOWN, pos); + CmdTurnoutAction(C_UP, pos); } return C_CONTINUE; case C_REDRAW: + wSetCursor(mainD.d, defaultCursor); if (Dto.state) { - DrawSegs( &tempD, Dto.pos, Dto.angle, - curTurnout->segs, curTurnout->segCnt, trackGauge, wDrawColorBlue ); + DrawSegs(&tempD, Dto.pos, Dto.angle, + curTurnout->segs, curTurnout->segCnt, trackGauge, selectedColor); } - if (anchors_da.cnt>0) { - DrawSegs( &tempD, zero, 0.0, &anchors(0), anchors_da.cnt, trackGauge, wDrawColorBlack ); + if (anchors_da.cnt > 0) { + DrawSegs(&tempD, zero, 0.0, &anchors(0), anchors_da.cnt, trackGauge, wDrawColorBlack); + wSetCursor(mainD.d, wCursorNone); } if (Dto.state == 2) - DrawLine( &tempD, Dto.rot0, Dto.rot1, 0, wDrawColorBlack ); + DrawLine(&tempD, Dto.rot0, Dto.rot1, 0, wDrawColorBlue); return C_CONTINUE; case C_CANCEL: - DYNARR_RESET(trkSeg_t,anchors_da); + DYNARR_RESET(trkSeg_t, anchors_da); Dto.state = 0; Dto.trk = NULL; /*wHide( newTurn.reg.win );*/ return C_TERMINATE; case C_TEXT: - if ((action>>8) != ' ') + if ((action >> 8) != ' ') return C_CONTINUE; /*no break*/ case C_OK: - DYNARR_RESET(trkSeg_t,anchors_da); + DYNARR_RESET(trkSeg_t, anchors_da); AddTurnout(); - Dto.state=0; + Dto.state = 0; Dto.trk = NULL; return C_TERMINATE; case C_FINISH: - DYNARR_RESET(trkSeg_t,anchors_da); + DYNARR_RESET(trkSeg_t, anchors_da); if (Dto.state != 0 && Dto.trk != NULL) - CmdTurnoutAction( C_OK, pos ); + CmdTurnoutAction(C_OK, pos); else - CmdTurnoutAction( C_CANCEL, pos ); + CmdTurnoutAction(C_CANCEL, pos); return C_TERMINATE; case C_CMDMENU: menuPos = pos; - wMenuPopupShow( turnoutPopupM ); + wMenuPopupShow(turnoutPopupM); return C_CONTINUE; default: @@ -2919,83 +4822,84 @@ LOG( log_turnout, 1, ( "RMOVE post @ %0.3fx%0.3f\n", Dto.pos.x, Dto.pos.y ) ); #ifdef TURNOUTCMD static STATUS_T CmdTurnout( - wAction_t action, - coOrd pos ) + wAction_t action, + coOrd pos) { wIndex_t turnoutIndex; - turnoutInfo_t * turnoutPtr; + turnoutInfo_t* turnoutPtr; switch (action & 0xFF) { case C_START: if (turnoutW == NULL) { -/* turnoutW = ParamCreateDialog( &turnoutPG, MakeWindowTitle("Turnout"), "Ok", , (paramActionCancelProc)Reset, TRUE, NULL, F_RESIZE|F_RECALLSIZE, TurnoutDlgUpdate ); */ - turnoutW = ParamCreateDialog( &turnoutPG, MakeWindowTitle(_("Turnout")), _("Close"), (paramActionOkProc)TurnoutOk, wHide, TRUE, NULL, F_RESIZE|F_RECALLSIZE|PD_F_ALT_CANCELLABEL, TurnoutDlgUpdate ); - InitNewTurn( turnoutNewM ); + /* turnoutW = ParamCreateDialog( &turnoutPG, MakeWindowTitle("Turnout"), "Ok", , (paramActionCancelProc)Reset, TRUE, NULL, F_RESIZE|F_RECALLSIZE, TurnoutDlgUpdate ); */ + turnoutW = ParamCreateDialog(&turnoutPG, MakeWindowTitle(_("Turnout")), _("Close"), (paramActionOkProc)TurnoutOk, wHide, TRUE, NULL, F_RESIZE | F_RECALLSIZE | PD_F_ALT_CANCELLABEL, TurnoutDlgUpdate); + InitNewTurn(turnoutNewM); } -/* ParamDialogOkActive( &turnoutPG, FALSE ); */ - turnoutIndex = wListGetIndex( turnoutListL ); + /* ParamDialogOkActive( &turnoutPG, FALSE ); */ + turnoutIndex = wListGetIndex(turnoutListL); turnoutPtr = curTurnout; - wShow( turnoutW ); - TurnoutChange( CHANGE_PARAMS|CHANGE_SCALE ); + wShow(turnoutW); + TurnoutChange(CHANGE_PARAMS | CHANGE_SCALE); if (curTurnout == NULL) { - NoticeMessage2( 0, MSG_TURNOUT_NO_TURNOUT, _("Ok"), NULL ); + NoticeMessage2(0, MSG_TURNOUT_NO_TURNOUT, _("Ok"), NULL); return C_TERMINATE; } if (turnoutIndex > 0 && turnoutPtr) { curTurnout = turnoutPtr; - wListSetIndex( turnoutListL, turnoutIndex ); - RedrawTurnout(); + wListSetIndex(turnoutListL, turnoutIndex); + RedrawTurnout( turnoutD.d, NULL, 0, 0 ); } - InfoMessage( _("Pick turnout and active End Point, then place on the layout")); - ParamLoadControls( &turnoutPG ); - ParamGroupRecord( &turnoutPG ); - return CmdTurnoutAction( action, pos ); + InfoMessage(_("Pick turnout and active End Point, then place on the layout")); + ParamLoadControls(&turnoutPG); + ParamGroupRecord(&turnoutPG); + SetAllTrackSelect(FALSE); + return CmdTurnoutAction(action, pos); case wActionMove: - return CmdTurnoutAction( action, pos ); + return CmdTurnoutAction(action, pos); case C_DOWN: case C_RDOWN: - ParamDialogOkActive( &turnoutPG, TRUE ); + ParamDialogOkActive(&turnoutPG, TRUE); if (hideTurnoutWindow) - wHide( turnoutW ); - if (((action&0xFF) == C_DOWN) && (MyGetKeyState()&WKEY_CTRL)) + wHide(turnoutW); + if (((action & 0xFF) == C_DOWN) && (MyGetKeyState() & WKEY_CTRL)) return CmdTurnoutAction(C_RDOWN, pos); //Convert CTRL into Right /*no break*/ case C_MOVE: - if (MyGetKeyState()&WKEY_CTRL) - return CmdTurnoutAction (C_RMOVE, pos); + if (MyGetKeyState() & WKEY_CTRL) + return CmdTurnoutAction(C_RMOVE, pos); /*no break*/ case C_RMOVE: - return CmdTurnoutAction( action, pos ); + return CmdTurnoutAction(action, pos); case C_UP: case C_RUP: if (hideTurnoutWindow) - wShow( turnoutW ); + wShow(turnoutW); - InfoMessage( _("Left-Drag to place, Ctrl+Left-Drag or Right-Drag to Rotate, Space or Enter to accept, Esc to Cancel") ); - if (((action&0xFF) == C_UP) && (MyGetKeyState()&WKEY_CTRL)) - return CmdTurnoutAction (C_RUP, pos); - return CmdTurnoutAction( action, pos ); + InfoMessage(_("Left-Drag to place, Ctrl+Left-Drag or Right-Drag to Rotate, Space or Enter to accept, Esc to Cancel")); + if (((action & 0xFF) == C_UP) && (MyGetKeyState() & WKEY_CTRL)) + return CmdTurnoutAction(C_RUP, pos); + return CmdTurnoutAction(action, pos); case C_LCLICK: - CmdTurnoutAction( action, pos ); + CmdTurnoutAction(action, pos); HilightEndPt(); return C_CONTINUE; case C_CANCEL: - wHide( turnoutW ); - return CmdTurnoutAction( action, pos ); + wHide(turnoutW); + return CmdTurnoutAction(action, pos); case C_TEXT: - CmdTurnoutAction( action, pos ); + CmdTurnoutAction(action, pos); return C_CONTINUE; case C_OK: case C_FINISH: case C_CMDMENU: case C_REDRAW: - return CmdTurnoutAction( action, pos ); + return CmdTurnoutAction(action, pos); default: return C_CONTINUE; @@ -3003,59 +4907,59 @@ static STATUS_T CmdTurnout( } #endif - + /** * Event procedure for the hotbar. * * \param op IN requested function - * \param data IN pointer to info on selected element + * \param data IN pointer to info on selected element * \param d IN * \param origP IN - * \return + * \return */ -static char * CmdTurnoutHotBarProc( - hotBarProc_e op, - void * data, - drawCmd_p d, - coOrd * origP ) +static char* CmdTurnoutHotBarProc( + hotBarProc_e op, + void* data, + drawCmd_p d, + coOrd* origP) { - turnoutInfo_t * to = (turnoutInfo_t*)data; - switch ( op ) { + turnoutInfo_t* to = (turnoutInfo_t*)data; + switch (op) { case HB_SELECT: /* new element is selected */ - CmdTurnoutAction( C_FINISH, zero ); /* finish current operation */ + CmdTurnoutAction(C_FINISH, zero); /* finish current operation */ curTurnout = to; - DoCommandB( (void*)(intptr_t)turnoutHotBarCmdInx ); /* continue with new turnout / structure */ + DoCommandB(I2VP(turnoutHotBarCmdInx)); /* continue with new turnout / structure */ return NULL; case HB_LISTTITLE: - FormatCompoundTitle( listLabels, to->title ); + FormatCompoundTitle(listLabels, to->title); if (message[0] == '\0') - FormatCompoundTitle( listLabels|LABEL_DESCR, to->title ); + FormatCompoundTitle(listLabels | LABEL_DESCR, to->title); return message; case HB_BARTITLE: - FormatCompoundTitle( hotBarLabels<<1, to->title ); + FormatCompoundTitle(hotBarLabels << 1, to->title); return message; case HB_FULLTITLE: return to->title; case HB_DRAW: - DrawSegs( d, *origP, 0.0, to->segs, to->segCnt, trackGauge, wDrawColorBlack ); + DrawSegs(d, *origP, 0.0, to->segs, to->segCnt, trackGauge, wDrawColorBlack); return NULL; } return NULL; } -EXPORT void AddHotBarTurnouts( void ) +EXPORT void AddHotBarTurnouts(void) { wIndex_t inx; - turnoutInfo_t * to; - for ( inx=0; inx < turnoutInfo_da.cnt; inx ++ ) { + turnoutInfo_t* to; + for (inx = 0; inx < turnoutInfo_da.cnt; inx++) { to = turnoutInfo(inx); - if ( !( IsParamValid(to->paramFileIndex) && - to->segCnt > 0 && - CompatibleScale( TRUE, to->scaleInx, GetLayoutCurScale()) ) ) - continue; - AddHotBarElement( to->contentsLabel, to->size, to->orig, TRUE, FALSE, to->barScale, to, CmdTurnoutHotBarProc ); + if (!(IsParamValid(to->paramFileIndex) && + to->segCnt > 0 && + (FIT_NONE != CompatibleScale(FIT_TURNOUT, to->scaleInx, GetLayoutCurScale())))) + continue; + AddHotBarElement(to->contentsLabel, to->size, to->orig, TRUE, FALSE, to->barScale, to, CmdTurnoutHotBarProc); } } @@ -3068,8 +4972,8 @@ EXPORT void AddHotBarTurnouts( void ) */ static STATUS_T CmdTurnoutHotBar( - wAction_t action, - coOrd pos ) + wAction_t action, + coOrd pos) { switch (action & 0xFF) { @@ -3077,61 +4981,61 @@ static STATUS_T CmdTurnoutHotBar( case C_START: //TurnoutChange( CHANGE_PARAMS|CHANGE_SCALE ); if (curTurnout == NULL) { - NoticeMessage2( 0, MSG_TURNOUT_NO_TURNOUT, _("Ok"), NULL ); + NoticeMessage2(0, MSG_TURNOUT_NO_TURNOUT, _("Ok"), NULL); return C_TERMINATE; } - FormatCompoundTitle( listLabels|LABEL_DESCR, curTurnout->title ); - InfoMessage( _("Place %s and draw into position"), message ); - wIndex_t listIndex = FindListItemByContext( turnoutListL, curTurnout ); - if ( listIndex > 0 ) - turnoutInx = listIndex; - ParamLoadControls( &turnoutPG ); - ParamGroupRecord( &turnoutPG ); - return CmdTurnoutAction( action, pos ); + FormatCompoundTitle(listLabels | LABEL_DESCR, curTurnout->title); + InfoMessage(_("Place %s and draw into position"), message); + wIndex_t listIndex = FindListItemByContext(turnoutListL, curTurnout); + if (listIndex >= 0) + turnoutInx = listIndex; + ParamLoadControls(&turnoutPG); + ParamGroupRecord(&turnoutPG); + return CmdTurnoutAction(action, pos); case wActionMove: - return CmdTurnoutAction( action, pos ); + return CmdTurnoutAction(action, pos); case C_DOWN: - if (MyGetKeyState()&WKEY_CTRL) { - return CmdTurnoutAction( C_RDOWN, pos ); + if (MyGetKeyState() & WKEY_CTRL) { + return CmdTurnoutAction(C_RDOWN, pos); } /*no break*/ case C_RDOWN: - return CmdTurnoutAction( action, pos ); + return CmdTurnoutAction(action, pos); case C_MOVE: - if (MyGetKeyState()&WKEY_CTRL) { - return CmdTurnoutAction( C_RMOVE, pos ); + if (MyGetKeyState() & WKEY_CTRL) { + return CmdTurnoutAction(C_RMOVE, pos); } /*no break*/ case C_RMOVE: - return CmdTurnoutAction( action, pos ); + return CmdTurnoutAction(action, pos); case C_UP: - if (MyGetKeyState()&WKEY_CTRL) { - return CmdTurnoutAction( C_RUP, pos ); + if (MyGetKeyState() & WKEY_CTRL) { + return CmdTurnoutAction(C_RUP, pos); } /*no break*/ case C_RUP: - InfoMessage( _("Left-Drag to place, Ctrl+Left-Drag or Right-Drag to Rotate, Space or Enter to accept, Esc to Cancel") ); - return CmdTurnoutAction( action, pos ); + InfoMessage(_("Left-Drag to place, Ctrl+Left-Drag or Right-Drag to Rotate, Space or Enter to accept, Esc to Cancel")); + return CmdTurnoutAction(action, pos); case C_REDRAW: - return CmdTurnoutAction( action, pos ); + return CmdTurnoutAction(action, pos); case C_TEXT: - if ((action>>8) != ' ') + if ((action >> 8) != ' ') return C_CONTINUE; /* no break*/ case C_OK: - CmdTurnoutAction( action, pos ); + CmdTurnoutAction(action, pos); return C_CONTINUE; case C_CANCEL: HotBarCancel(); /*no break*/ default: - return CmdTurnoutAction( action, pos ); + return CmdTurnoutAction(action, pos); } } @@ -3139,96 +5043,96 @@ static STATUS_T CmdTurnoutHotBar( #include "bitmaps/turnout.xpm" -EXPORT void InitCmdTurnout( wMenu_p menu ) +EXPORT void InitCmdTurnout(wMenu_p menu) { - AddMenuButton( menu, CmdTurnout, "cmdTurnout", _("Predefined Track"), wIconCreatePixMap(turnout_xpm), LEVEL0_50, IC_WANT_MOVE|IC_STICKY|IC_LCLICK|IC_CMDMENU|IC_POPUP2, ACCL_TURNOUT, NULL ); - turnoutHotBarCmdInx = AddMenuButton( menu, CmdTurnoutHotBar, "cmdTurnoutHotBar", "", NULL, LEVEL0_50, IC_WANT_MOVE|IC_STICKY|IC_LCLICK|IC_CMDMENU|IC_POPUP2, 0, NULL ); - RegisterChangeNotification( TurnoutChange ); - ParamRegister( &turnoutPG ); - log_turnout = LogFindIndex( "turnout" ); - log_traverseTurnout = LogFindIndex( "traverseTurnout" ); - log_suppressCheckPaths = LogFindIndex( "suppresscheckpaths" ); - log_splitturnout = LogFindIndex( "splitturnout" ); - if ( turnoutPopupM == NULL ) { - turnoutPopupM = MenuRegister( "Turnout Rotate" ); - AddRotateMenu( turnoutPopupM, TurnoutRotate ); + AddMenuButton(menu, CmdTurnout, "cmdTurnout", _("Predefined Track"), wIconCreatePixMap(turnout_xpm[iconSize]), LEVEL0_50, IC_WANT_MOVE | IC_STICKY | IC_LCLICK | IC_CMDMENU | IC_POPUP2, ACCL_TURNOUT, NULL); + turnoutHotBarCmdInx = AddMenuButton(menu, CmdTurnoutHotBar, "cmdTurnoutHotBar", "", NULL, LEVEL0_50, IC_WANT_MOVE | IC_STICKY | IC_LCLICK | IC_CMDMENU | IC_POPUP2, 0, NULL); + RegisterChangeNotification(TurnoutChange); + ParamRegister(&turnoutPG); + log_turnout = LogFindIndex("turnout"); + log_traverseTurnout = LogFindIndex("traverseTurnout"); + log_suppressCheckPaths = LogFindIndex("suppresscheckpaths"); + log_splitturnout = LogFindIndex("splitturnout"); + if (turnoutPopupM == NULL) { + turnoutPopupM = MenuRegister("Turnout Rotate"); + AddRotateMenu(turnoutPopupM, TurnoutRotate); } } #endif -EXPORT void InitTrkTurnout( void ) +EXPORT void InitTrkTurnout(void) { - T_TURNOUT = InitObject( &turnoutCmds ); + T_TURNOUT = InitObject(&turnoutCmds); /*InitDebug( "Turnout", &debugTurnout );*/ - AddParam( "TURNOUT ", ReadTurnoutParam); + AddParam("TURNOUT ", ReadTurnoutParam); } - + #ifdef TEST wDrawable_t turnoutD; -void wListAddValue( wList_p bl, char * val, wIcon_p, void * listData, void * itemData ) +void wListAddValue(wList_p bl, char* val, wIcon_p, void* listData, void* itemData) { } -void wListClear( wList_p bl ) +void wListClear(wList_p bl) { } -void wDrawSetScale( wDrawable_p d ) +void wDrawSetScale(wDrawable_p d) { d->scale = 1.0; } -void wDrawClear( wDrawable_p d ) +void wDrawClear(wDrawable_p d) { } -void GetTrkCurveCenter( track_p t, coOrd *pos, DIST_T *radius ) +void GetTrkCurveCenter(track_p t, coOrd* pos, DIST_T* radius) { } #ifdef NOTRACK_C -track_p NewTrack( wIndex_t index, TRKTYP_T type, EPINX_T endCnt, SIZE_T extraSize ) +track_p NewTrack(wIndex_t index, TRKTYP_T type, EPINX_T endCnt, SIZE_T extraSize) { return NULL; } -track_p OnTrack( coOrd *pos ) +track_p OnTrack(coOrd* pos) { return NULL; } -void ErrorMessage( char * msg, ... ) +void ErrorMessage(char* msg, ...) { - lprintf( "ERROR : %s\n", msg ); + lprintf("ERROR : %s\n", msg); } -void DeleteTrack( track_p t ) +void DeleteTrack(track_p t) { } -void ConnectTracks( track_p t0, EPINX_T ep0, track_p t1, EPINX_T ep1 ) +void ConnectTracks(track_p t0, EPINX_T ep0, track_p t1, EPINX_T ep1) { } #endif -main( INT_T argc, char * argv[] ) +main(INT_T argc, char* argv[]) { - FILE * f; + FILE* f; char line[STR_SIZE]; wIndex_t lineCnt = 0; /*debugTurnout = 3;*/ - if ((f = fopen("turnout.params", "r" )) == NULL ) { - Perror( "turnout.params" ); + if ((f = fopen("turnout.params", "r")) == NULL) { + Perror("turnout.params"); Exit(1); } - while ( fgets( line, sizeof line, f ) != NULL ) { + while (fgets(line, sizeof line, f) != NULL) { lineCnt++; - ReadTurnoutParam( &lineCnt ); + ReadTurnoutParam(&lineCnt); } } #endif |