From 7b358424ebad9349421acd533c2fa1cbf6cf3e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Wed, 28 Dec 2016 16:52:56 +0100 Subject: Initial import of xtrkcad version 1:4.0.2-2 --- app/bin/ctodesgn.c | 2539 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2539 insertions(+) create mode 100644 app/bin/ctodesgn.c (limited to 'app/bin/ctodesgn.c') diff --git a/app/bin/ctodesgn.c b/app/bin/ctodesgn.c new file mode 100644 index 0000000..e3c1b8e --- /dev/null +++ b/app/bin/ctodesgn.c @@ -0,0 +1,2539 @@ +/* \file ctodesgn.c + * T_TURNOUT Designer + * + */ + +/* 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. + */ + +#ifdef WINDOWS +#include +#endif + +#include + +#include +#include "track.h" +#include "ccurve.h" +#include "cstraigh.h" +#include "compound.h" +#include "i18n.h" + +#define TURNOUTDESIGNER "CTURNOUT DESIGNER" + + + +/***************************************** + * + * TURNOUT DESIGNER + * + */ + + +#define NTO_REGULAR (1) +#define NTO_CURVED (2) +#define NTO_WYE (3) +#define NTO_3WAY (4) +#define NTO_CROSSING (5) +#define NTO_S_SLIP (6) +#define NTO_D_SLIP (7) +#define NTO_R_CROSSOVER (8) +#define NTO_L_CROSSOVER (9) +#define NTO_D_CROSSOVER (10) +#define NTO_STR_SECTION (11) +#define NTO_CRV_SECTION (12) +#define NTO_BUMPER (13) +#define NTO_TURNTABLE (14) + +#define FLOAT (1) + + +typedef struct { + struct { + wPos_t x, y; + } pos; + int index; + char * winLabel; + char * printLabel; + enum { Dim_e, Frog_e, Angle_e } mode; + } toDesignFloat_t; + +typedef struct { + PATHPTR_T paths; + char * segOrder; + } toDesignSchema_t; + +typedef struct { + int type; + char * label; + int strCnt; + int lineCnt; + wLines_t * lines; + int floatCnt; + toDesignFloat_t * floats; + toDesignSchema_t * paths; + int angleModeCnt; + wLine_p lineC; + } toDesignDesc_t; + +static wWin_p newTurnW; +static FLOAT_T newTurnLen0; +static FLOAT_T newTurnLen1; +static FLOAT_T newTurnOff1; +static FLOAT_T newTurnAngle1; +static FLOAT_T newTurnLen2; +static FLOAT_T newTurnOff2; +static FLOAT_T newTurnAngle2; +static long newTurnAngleMode = 1; +static char newTurnRightDesc[STR_SIZE], newTurnLeftDesc[STR_SIZE]; +static char newTurnRightPartno[STR_SIZE], newTurnLeftPartno[STR_SIZE]; +static char newTurnManufacturer[STR_SIZE]; +static char *newTurnAngleModeLabels[] = { N_("Frog #"), N_("Degrees"), NULL }; +static DIST_T newTurnRoadbedWidth; +static long newTurnRoadbedLineWidth = 0; +static wDrawColor roadbedColor; +static DIST_T newTurnTrackGauge; +static char * newTurnScaleName; +static paramFloatRange_t r0_10000 = { 0, 10000, 80 }; +static paramFloatRange_t r0_360 = { 0, 360, 80 }; +static paramFloatRange_t r0_100 = { 0, 100, 80 }; +static paramIntegerRange_t i0_100 = { 0, 100, 40 }; +static void NewTurnOk( void * ); +static void ShowTurnoutDesigner( void * ); + + +static coOrd points[20]; +static DIST_T radii[10] = { 0.0 }; + +#define POSX(X) ((wPos_t)((X)*newTurnout_d.dpi)) +#define POSY(Y) ((wPos_t)((Y)*newTurnout_d.dpi)) + +static paramData_t turnDesignPLs[] = { +#define I_TOLENGTH (0) +#define I_TO_FIRST_FLOAT (0) + { PD_FLOAT, &newTurnLen1, "len1", PDO_DIM|PDO_DLGIGNORELABELWIDTH, &r0_10000, N_("Length") }, + { PD_FLOAT, &newTurnLen2, "len2", PDO_DIM|PDO_DLGIGNORELABELWIDTH, &r0_10000, N_("Length") }, + { PD_FLOAT, &newTurnLen0, "len0", PDO_DIM|PDO_DLGIGNORELABELWIDTH, &r0_10000, N_("Length") }, +#define I_TOOFFSET (3) + { PD_FLOAT, &newTurnOff1, "off1", PDO_DIM|PDO_DLGIGNORELABELWIDTH, &r0_10000, N_("Offset") }, + { PD_FLOAT, &newTurnOff2, "off2", PDO_DIM|PDO_DLGIGNORELABELWIDTH, &r0_10000, N_("Offset") }, +#define I_TOANGLE (5) + { PD_FLOAT, &newTurnAngle1, "angle1", PDO_DLGIGNORELABELWIDTH, &r0_360, N_("Angle") }, +#define I_TO_LAST_FLOAT (6) + { PD_FLOAT, &newTurnAngle2, "angle2", PDO_DLGIGNORELABELWIDTH, &r0_360, N_("Angle") }, +#define I_TOMANUF (7) + { PD_STRING, &newTurnManufacturer, "manuf", 0, NULL, N_("Manufacturer") }, +#define I_TOLDESC (8) + { PD_STRING, &newTurnLeftDesc, "desc1", 0, NULL, N_("Left Description") }, + { PD_STRING, &newTurnLeftPartno, "partno1", PDO_DLGHORZ, NULL, N_(" #") }, +#define I_TORDESC (10) + { PD_STRING, &newTurnRightDesc, "desc2", 0, NULL, N_("Right Description") }, + { PD_STRING, &newTurnRightPartno, "partno2", PDO_DLGHORZ, NULL, N_(" #") }, + { PD_FLOAT, &newTurnRoadbedWidth, "roadbedWidth", PDO_DIM, &r0_100, N_("Roadbed Width") }, + { PD_LONG, &newTurnRoadbedLineWidth, "roadbedLineWidth", PDO_DLGHORZ, &i0_100, N_("Line Width") }, + { PD_COLORLIST, &roadbedColor, "color", PDO_DLGHORZ|PDO_DLGBOXEND, NULL, N_("Color") }, + { PD_BUTTON, (void*)NewTurnOk, "done", PDO_DLGCMDBUTTON, NULL, N_("Ok") }, + { PD_BUTTON, (void*)wPrintSetup, "printsetup", 0, NULL, N_("Print Setup") }, +#define I_TOANGMODE (17) + { PD_RADIO, &newTurnAngleMode, "angleMode", 0, newTurnAngleModeLabels } + }; + +#ifndef MKTURNOUT +static paramGroup_t turnDesignPG = { "turnoutNew", 0, turnDesignPLs, sizeof turnDesignPLs/sizeof turnDesignPLs[0] }; + +static turnoutInfo_t * customTurnout1, * customTurnout2; +static BOOL_T includeNontrackSegments; +#endif + +#ifdef MKTURNOUT +int doCustomInfoLine = 1; +int doRoadBed = 0; +char specialLine[256]; +#endif + +static toDesignDesc_t * curDesign; + +/* + * Regular Turnouts + */ + + +static wLines_t RegLines[] = { +#include "toreg.lin" + }; +static toDesignFloat_t RegFloats[] = { +{ { 175, 10 }, I_TOLENGTH+0, N_("Length"), N_("Diverging Length"), Dim_e }, +{ { 400, 28 }, I_TOANGLE+0, N_("Angle"), N_("Diverging Angle"), Frog_e }, +{ { 325, 68 }, I_TOOFFSET+0, N_("Offset"), N_("Diverging Offset"), Dim_e }, +{ { 100, 120 }, I_TOLENGTH+2, N_("Length"), N_("Overall Length"), Dim_e }, + }; +static signed char RegPaths[] = { + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 2, 0, 0, + 'R', 'e', 'v', 'e', 'r', 's', 'e', 0, 1, 3, 4, 0, 0, 0 }; +static toDesignSchema_t RegSchema = { + RegPaths, + "030" "310" "341" "420" }; +static toDesignDesc_t RegDesc = { + NTO_REGULAR, + N_("Regular Turnout"), + 2, + sizeof RegLines/sizeof RegLines[0], RegLines, + sizeof RegFloats/sizeof RegFloats[0], RegFloats, + &RegSchema, 1 }; + +static wLines_t CrvLines[] = { +#include "tocrv.lin" + }; +static toDesignFloat_t CrvFloats[] = { +{ { 175, 10 }, I_TOLENGTH+0, N_("Length"), N_("Inner Length"), Dim_e }, +{ { 375, 12 }, I_TOANGLE+0, N_("Angle"), N_("Inner Angle"), Frog_e }, +{ { 375, 34 }, I_TOOFFSET+0, N_("Offset"), N_("Inner Offset"), Dim_e }, +{ { 400, 62 }, I_TOANGLE+1, N_("Angle"), N_("Outer Angle"), Frog_e }, +{ { 400, 84 }, I_TOOFFSET+1, N_("Offset"), N_("Outer Offset"), Dim_e }, +{ { 175, 120 }, I_TOLENGTH+1, N_("Length"), N_("Outer Length"), Dim_e } }; +static signed char Crv1Paths[] = { + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 4, 5, 0, 0, + 'R', 'e', 'v', 'e', 'r', 's', 'e', 0, 1, 2, 3, 0, 0, 0 }; +static toDesignSchema_t Crv1Schema = { + Crv1Paths, + "030" "341" "410" "362" "620" }; +static signed char Crv2Paths[] = { + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 4, 5, 0, 0, + 'R', 'e', 'v', 'e', 'r', 's', 'e', 0, 1, 6, 2, 3, 0, 0, 0 }; +static toDesignSchema_t Crv2Schema = { + Crv2Paths, + "050" "341" "410" "562" "620" "530" }; +static signed char Crv3Paths[] = { + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 6, 4, 5, 0, 0, + 'R', 'e', 'v', 'e', 'r', 's', 'e', 0, 1, 2, 3, 0, 0, 0 }; +static toDesignSchema_t Crv3Schema = { + Crv3Paths, + "030" "341" "410" "562" "620" "350" }; + +static toDesignDesc_t CrvDesc = { + NTO_CURVED, + N_("Curved Turnout"), + 2, + sizeof CrvLines/sizeof CrvLines[0], CrvLines, + sizeof CrvFloats/sizeof CrvFloats[0], CrvFloats, + &Crv1Schema, 1 }; + + +static wLines_t WyeLines[] = { +#include "towye.lin" + }; +static toDesignFloat_t WyeFloats[] = { +{ { 175, 10 }, I_TOLENGTH+0, N_("Length"), N_("Left Length"), Dim_e }, +{ { 400, 28 }, I_TOANGLE+0, N_("Angle"), N_("Left Angle"), Frog_e }, +{ { 325, 68 }, I_TOOFFSET+0, N_("Offset"), N_("Left Offset"), Dim_e }, +{ { 325, 115 }, I_TOOFFSET+1, N_("Offset"), N_("Right Offset"), Dim_e }, +{ { 400, 153 }, I_TOANGLE+1, N_("Angle"), N_("Right Angle"), Frog_e }, +{ { 175, 170 }, I_TOLENGTH+1, N_("Length"), N_("Right Length"), Dim_e }, + }; +static signed char Wye1Paths[] = { + 'L', 'e', 'f', 't', 0, 1, 2, 3, 0, 0, + 'R', 'i', 'g', 'h', 't', 0, 1, 4, 5, 0, 0, 0 }; +static toDesignSchema_t Wye1Schema = { + Wye1Paths, + "030" "341" "410" "362" "620" }; +static signed char Wye2Paths[] = { + 'L', 'e', 'f', 't', 0, 1, 2, 3, 4, 0, 0, + 'R', 'i', 'g', 'h', 't', 0, 1, 5, 6, 0, 0, 0 }; +static toDesignSchema_t Wye2Schema = { + Wye2Paths, + "050" "530" "341" "410" "562" "620" }; +static signed char Wye3Paths[] = { + 'L', 'e', 'f', 't', 0, 1, 2, 3, 0, 0, + 'R', 'i', 'g', 'h', 't', 0, 1, 4, 5, 6, 0, 0, 0 }; +static toDesignSchema_t Wye3Schema = { + Wye3Paths, + "030" "341" "410" "350" "562" "620" }; +static toDesignDesc_t WyeDesc = { + NTO_WYE, + N_("Wye Turnout"), + 1, + sizeof WyeLines/sizeof WyeLines[0], WyeLines, + sizeof WyeFloats/sizeof WyeFloats[0], WyeFloats, + NULL, 1 }; + +static wLines_t ThreewayLines[] = { +#include "to3way.lin" + }; +static toDesignFloat_t ThreewayFloats[] = { +{ { 175, 10 }, I_TOLENGTH+0, N_("Length"), N_("Left Length"), Dim_e }, +{ { 400, 28 }, I_TOANGLE+0, N_("Angle"), N_("Left Angle"), Frog_e }, +{ { 325, 68 }, I_TOOFFSET+0, N_("Offset"), N_("Left Offset"), Dim_e }, +{ { 100, 90 }, I_TOLENGTH+2, N_("Length"), N_("Length"), Dim_e }, +{ { 325, 115 }, I_TOOFFSET+1, N_("Offset"), N_("Right Offset"), Dim_e }, +{ { 400, 153 }, I_TOANGLE+1, N_("Angle"), N_("Right Angle"), Frog_e }, +{ { 175, 170 }, I_TOLENGTH+1, N_("Length"), N_("Right Length"), Dim_e }, + }; +static signed char Tri1Paths[] = { + 'L', 'e', 'f', 't', 0, 1, 2, 3, 0, 0, + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 6, 0, 0, + 'R', 'i', 'g', 'h', 't', 0, 1, 4, 5, 0, 0, 0 }; +static toDesignSchema_t Tri1Schema = { + Tri1Paths, + "030" "341" "410" "362" "620" "370" }; +static signed char Tri2Paths[] = { + 'L', 'e', 'f', 't', 0, 1, 2, 3, 4, 0, 0, + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 2, 7, 0, 0, + 'R', 'i', 'g', 'h', 't', 0, 1, 5, 6, 0, 0, 0 }; +static toDesignSchema_t Tri2Schema = { + Tri2Paths, + "050" "530" "341" "410" "562" "620" "370" }; +static signed char Tri3Paths[] = { + 'L', 'e', 'f', 't', 0, 1, 2, 3, 0, 0, + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 4, 7, 0, 0, + 'R', 'i', 'g', 'h', 't', 0, 1, 4, 5, 6, 0, 0, 0 }; +static toDesignSchema_t Tri3Schema = { + Tri3Paths, + "030" "341" "410" "350" "562" "620" "570" }; +static toDesignDesc_t ThreewayDesc = { + NTO_3WAY, + N_("3-way Turnout"), + 1, + sizeof ThreewayLines/sizeof ThreewayLines[0], ThreewayLines, + sizeof ThreewayFloats/sizeof ThreewayFloats[0], ThreewayFloats, + NULL, 1 }; + +static wLines_t CrossingLines[] = { +#include "toxing.lin" + }; +static toDesignFloat_t CrossingFloats[] = { +{ { 329, 30 }, I_TOLENGTH+0, N_("Length"), N_("Length"), Dim_e }, +{ { 370, 90 }, I_TOANGLE+0, N_("Angle"), N_("Angle"), Frog_e }, +{ { 329, 150 }, I_TOLENGTH+1, N_("Length"), N_("Length"), Dim_e } }; +static signed char CrossingPaths[] = { + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 0, 2, 0, 0, 0 }; +static toDesignSchema_t CrossingSchema = { + CrossingPaths, + "010" "230" }; +static toDesignDesc_t CrossingDesc = { + NTO_CROSSING, + N_("Crossing"), + 1, + sizeof CrossingLines/sizeof CrossingLines[0], CrossingLines, + sizeof CrossingFloats/sizeof CrossingFloats[0], CrossingFloats, + &CrossingSchema, 1 }; + +static wLines_t SingleSlipLines[] = { +#include "tosslip.lin" + }; +static toDesignFloat_t SingleSlipFloats[] = { +{ { 329, 30 }, I_TOLENGTH+0, N_("Length"), N_("Length"), Dim_e }, +{ { 370, 90 }, I_TOANGLE+0, N_("Angle"), N_("Angle"), Frog_e }, +{ { 329, 155 }, I_TOLENGTH+1, N_("Length"), N_("Length"), Dim_e } }; +static signed char SingleSlipPaths[] = { + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 2, 0, 3, 4, 0, 0, + 'R', 'e', 'v', 'e', 'r', 's', 'e', 0, 1, 5, 4, 0, 0, 0 }; +static toDesignSchema_t SingleSlipSchema = { + SingleSlipPaths, + "040" "410" "250" "530" "451" }; +static toDesignDesc_t SingleSlipDesc = { + NTO_S_SLIP, + N_("Single Slipswitch"), + 1, + sizeof SingleSlipLines/sizeof SingleSlipLines[0], SingleSlipLines, + sizeof SingleSlipFloats/sizeof SingleSlipFloats[0], SingleSlipFloats, + &SingleSlipSchema, 1 }; + +static wLines_t DoubleSlipLines[] = { +#include "todslip.lin" + }; +static toDesignFloat_t DoubleSlipFloats[] = { +{ { 329, 30 }, I_TOLENGTH+0, N_("Length"), N_("Length"), Dim_e }, +{ { 370, 90 }, I_TOANGLE+0, N_("Angle"), N_("Angle"), Frog_e }, +{ { 329, 155 }, I_TOLENGTH+1, N_("Length"), N_("Length"), Dim_e } }; +static signed char DoubleSlipPaths[] = { + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 2, 3, 0, 4, 5, 6, 0, 0, + 'R', 'e', 'v', 'e', 'r', 's', 'e', 0, 1, 7, 6, 0, 4, 8, 3, 0, 0, 0 }; +static toDesignSchema_t DoubleSlipSchema = { + DoubleSlipPaths, + "040" "460" "610" "270" "750" "530" "451" "762" }; +static toDesignDesc_t DoubleSlipDesc = { + NTO_D_SLIP, + N_("Double Slipswitch"), + 1, + sizeof DoubleSlipLines/sizeof DoubleSlipLines[0], DoubleSlipLines, + sizeof DoubleSlipFloats/sizeof DoubleSlipFloats[0], DoubleSlipFloats, + &DoubleSlipSchema, 1 }; + +static wLines_t RightCrossoverLines[] = { +#include "torcross.lin" + }; +static toDesignFloat_t RightCrossoverFloats[] = { +{ { 200, 10 }, I_TOLENGTH+0, N_("Length"), N_("Length"), Dim_e }, +{ { 90, 85 }, I_TOOFFSET+0, N_("Separation"), N_("Separation"), Dim_e } }; +static signed char RightCrossoverPaths[] = { + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 2, 0, 3, 4, 0, 0, + 'R', 'e', 'v', 'e', 'r', 's', 'e', 0, 3, 5, 6, 7, 2, 0, 0, 0 }; +static toDesignSchema_t RightCrossoverSchema = { + RightCrossoverPaths, + "060" "610" "280" "830" "892" "970" "761" }; +static toDesignDesc_t RightCrossoverDesc = { + NTO_R_CROSSOVER, + N_("Right Crossover"), + 1, + sizeof RightCrossoverLines/sizeof RightCrossoverLines[0], RightCrossoverLines, + sizeof RightCrossoverFloats/sizeof RightCrossoverFloats[0], RightCrossoverFloats, + &RightCrossoverSchema, 0 }; + +static wLines_t LeftCrossoverLines[] = { +#include "tolcross.lin" + }; +static toDesignFloat_t LeftCrossoverFloats[] = { +{ { 200, 10 }, I_TOLENGTH+0, N_("Length"), N_("Length"), Dim_e }, +{ { 90, 85 }, I_TOOFFSET+0, N_("Separation"), N_("Separation"), Dim_e } }; +static signed char LeftCrossoverPaths[] = { + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 2, 0, 3, 4, 0, 0, + 'R', 'e', 'v', 'e', 'r', 's', 'e', 0, 1, 5, 6, 7, 4, 0, 0, 0 }; +static toDesignSchema_t LeftCrossoverSchema = { + LeftCrossoverPaths, + "040" "410" "2A0" "A30" "451" "5B0" "BA2" }; +static toDesignDesc_t LeftCrossoverDesc = { + NTO_L_CROSSOVER, + N_("Left Crossover"), + 1, + sizeof LeftCrossoverLines/sizeof LeftCrossoverLines[0], LeftCrossoverLines, + sizeof LeftCrossoverFloats/sizeof LeftCrossoverFloats[0], LeftCrossoverFloats, + &LeftCrossoverSchema, 0 }; + +static wLines_t DoubleCrossoverLines[] = { +#include "todcross.lin" + }; +static toDesignFloat_t DoubleCrossoverFloats[] = { +{ { 200, 10 }, I_TOLENGTH+0, N_("Length"), N_("Length"), Dim_e }, +{ { 90, 85 }, I_TOOFFSET+0, N_("Separation"), N_("Separation"), Dim_e } }; +static signed char DoubleCrossoverPaths[] = { + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 2, 3, 0, 4, 5, 6, 0, 0, + 'R', 'e', 'v', 'e', 'r', 's', 'e', 0, 1, 7, 8, 9, 6, 0, 4, 10, 11, 12, 3, 0, 0, 0 }; +static toDesignSchema_t DoubleCrossoverSchema = { + DoubleCrossoverPaths, + "040" "460" "610" "280" "8A0" "A30" "451" "5B0" "BA2" "892" "970" "761" }; +static toDesignDesc_t DoubleCrossoverDesc = { + NTO_D_CROSSOVER, + N_("Double Crossover"), + 1, + sizeof DoubleCrossoverLines/sizeof DoubleCrossoverLines[0], DoubleCrossoverLines, + sizeof DoubleCrossoverFloats/sizeof DoubleCrossoverFloats[0], DoubleCrossoverFloats, + &DoubleCrossoverSchema, 0 }; + +static wLines_t StrSectionLines[] = { +#include "tostrsct.lin" + }; +static toDesignFloat_t StrSectionFloats[] = { +{ { 200, 10 }, I_TOLENGTH+0, N_("Length"), N_("Length"), Dim_e } }; +static signed char StrSectionPaths[] = { + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 0, 0, 0 }; +static toDesignSchema_t StrSectionSchema = { + StrSectionPaths, + "010" }; +static toDesignDesc_t StrSectionDesc = { + NTO_STR_SECTION, + N_("Straight Section"), + 1, + sizeof StrSectionLines/sizeof StrSectionLines[0], StrSectionLines, + sizeof StrSectionFloats/sizeof StrSectionFloats[0], StrSectionFloats, + &StrSectionSchema, 0 }; + +static wLines_t CrvSectionLines[] = { +#include "tocrvsct.lin" + }; +static toDesignFloat_t CrvSectionFloats[] = { +{ { 225, 90 }, I_TOLENGTH+0, N_("Radius"), N_("Radius"), Dim_e }, +{ { 225, 140}, I_TOANGLE+0, N_("Angle (Degrees)"), N_("Angle"), Angle_e } }; +static signed char CrvSectionPaths[] = { + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 0, 0, 0 }; +static toDesignSchema_t CrvSectionSchema = { + CrvSectionPaths, + "011" }; +static toDesignDesc_t CrvSectionDesc = { + NTO_CRV_SECTION, + N_("Curved Section"), + 1, + sizeof CrvSectionLines/sizeof CrvSectionLines[0], CrvSectionLines, + sizeof CrvSectionFloats/sizeof CrvSectionFloats[0], CrvSectionFloats, + &CrvSectionSchema, 0 }; + +#ifdef LATER +static wLines_t BumperLines[] = { +#include "tostrsct.lin" + }; +static toDesignFloat_t BumperFloats[] = { +{ { 200, 10 }, I_TOLENGTH+0, N_("Length"), N_("Length"), Dim_e } }; +static signed char BumperPaths[] = { + 'N', 'o', 'r', 'm', 'a', 'l', 0, 1, 0, 0, 0 }; +static toDesignSchema_t BumperSchema = { + BumperPaths, + "010" }; +static toDesignDesc_t BumperDesc = { + NTO_BUMPER, + N_("Bumper Section"), + 1, + sizeof StrSectionLines/sizeof StrSectionLines[0], StrSectionLines, + sizeof BumperFloats/sizeof BumperFloats[0], BumperFloats, + &BumperSchema, 0 }; + +static wLines_t TurntableLines[] = { +#include "tostrsct.lin" + }; +static toDesignFloat_t TurntableFloats[] = { +{ { 200, 10 }, I_TOOFFSET+0, N_("Offset"), N_("Count"), 0 }, +{ { 200, 10 }, I_TOLENGTH+0, N_("Length"), N_("Radius1"), Dim_e }, +{ { 200, 10 }, I_TOLENGTH+1, N_("Length"), N_("Radius2"), Dim_e } }; +static signed char TurntablePaths[] = { + '1', 0, 1, 0, 0, + '2', 0, 2, 0, 0, + '3', 0, 3, 0, 0, + '4', 0, 4, 0, 0, + '5', 0, 5, 0, 0, + '6', 0, 6, 0, 0, + '7', 0, 7, 0, 0, + '8', 0, 8, 0, 0, + '9', 0, 9, 0, 0, + '1', '0', 0, 10, 0, 0, + '1', '1', 0, 11, 0, 0, + '1', '2', 0, 12, 0, 0, + '1', '3', 0, 13, 0, 0, + '1', '4', 0, 14, 0, 0, + '1', '5', 0, 15, 0, 0, + '1', '6', 0, 16, 0, 0, + '1', '7', 0, 17, 0, 0, + '1', '8', 0, 18, 0, 0, + '1', '9', 0, 19, 0, 0, + '2', '0', 0, 20, 0, 0, + '2', '1', 0, 21, 0, 0, + '2', '2', 0, 22, 0, 0, + '2', '3', 0, 23, 0, 0, + '2', '4', 0, 24, 0, 0, + '2', '5', 0, 25, 0, 0, + '2', '6', 0, 26, 0, 0, + '2', '7', 0, 27, 0, 0, + '2', '8', 0, 28, 0, 0, + '2', '9', 0, 29, 0, 0, + '3', '0', 0, 30, 0, 0, + '3', '1', 0, 31, 0, 0, + '3', '2', 0, 32, 0, 0, + '3', '3', 0, 33, 0, 0, + '3', '4', 0, 34, 0, 0, + '3', '5', 0, 35, 0, 0, + '3', '6', 0, 36, 0, 0, + '3', '7', 0, 37, 0, 0, + '3', '8', 0, 38, 0, 0, + '3', '9', 0, 39, 0, 0, + '4', '0', 0, 40, 0, 0, + '4', '1', 0, 41, 0, 0, + '4', '2', 0, 42, 0, 0, + '4', '3', 0, 43, 0, 0, + '4', '4', 0, 44, 0, 0, + '4', '5', 0, 45, 0, 0, + '4', '6', 0, 46, 0, 0, + '4', '7', 0, 47, 0, 0, + '4', '8', 0, 48, 0, 0, + '4', '9', 0, 49, 0, 0, + '5', '0', 0, 50, 0, 0, + '5', '1', 0, 51, 0, 0, + '5', '2', 0, 52, 0, 0, + '5', '3', 0, 53, 0, 0, + '5', '4', 0, 54, 0, 0, + '5', '5', 0, 55, 0, 0, + '5', '6', 0, 56, 0, 0, + '5', '7', 0, 57, 0, 0, + '5', '8', 0, 58, 0, 0, + '5', '9', 0, 59, 0, 0, + '6', '0', 0, 60, 0, 0, + '6', '1', 0, 61, 0, 0, + '6', '2', 0, 62, 0, 0, + '6', '3', 0, 63, 0, 0, + '6', '4', 0, 64, 0, 0, + '6', '5', 0, 65, 0, 0, + '6', '6', 0, 66, 0, 0, + '6', '7', 0, 67, 0, 0, + '6', '8', 0, 68, 0, 0, + '6', '9', 0, 69, 0, 0, + '7', '0', 0, 70, 0, 0, + '7', '1', 0, 71, 0, 0, + '7', '2', 0, 72, 0, 0, + 0 }; +static toDesignSchema_t TurntableSchema = { + TurntablePaths, + "010" "020" "030" "040" "050" "060" "070" "080" "090" "0A0" "0B0" }; +static toDesignDesc_t TurntableDesc = { + NTO_TURNTABLE, + N_("Turntable Section"), + 1, + sizeof StrSectionLines/sizeof StrSectionLines[0], StrSectionLines, + sizeof TurntableFloats/sizeof TurntableFloats[0], TurntableFloats, + &TurntableSchema, 0 }; +#endif + +#ifndef MKTURNOUT +static toDesignDesc_t * designDescs[] = { + &RegDesc, + &CrvDesc, + &WyeDesc, + &ThreewayDesc, + &CrossingDesc, + &SingleSlipDesc, + &DoubleSlipDesc, + &RightCrossoverDesc, + &LeftCrossoverDesc, + &DoubleCrossoverDesc, + &StrSectionDesc, + &CrvSectionDesc }; +#endif + +/************************************************************************** + * + * Compute Roadbed + * + */ + +int debugComputeRoadbed = 0; +#ifdef LATER +typedef struct { + int start; + unsigned long bits; + unsigned long mask; + int width; + } searchTable_t; +static searchTable_t searchTable[] = { + { 0, 0xFFFF0000, 0xFFFF0000, 32000} , + { 32, 0x0000FFFF, 0x0000FFFF, 32000} , + + { 16, 0x00FFFF00, 0x00FFFF00, 16} , + + { 8, 0x0FF00000, 0x0FF00000, 8} , + { 24, 0x00000FF0, 0x00000FF0, 8} , + + { 4, 0x3C000000, 0x3C000000, 4} , + { 12, 0x003C0000, 0x003C0000, 4} , + { 20, 0x00003C00, 0x00003C00, 4} , + { 28, 0x0000003C, 0x0000003C, 4} , + + { 2, 0x60000000, 0x60000000, 2} , + { 6, 0x06000000, 0x06000000, 2}, + { 10, 0x00600000, 0x00600000, 2}, + { 14, 0x00060000, 0x00060000, 2}, + { 18, 0x00006000, 0x00006000, 2}, + { 22, 0x00000600, 0x00000600, 2}, + { 26, 0x00000060, 0x00000060, 2}, + { 30, 0x00000006, 0x00000006, 2}, + + { 1, 0x40000000, 0x60000000, 1}, + { 3, 0x10000000, 0x30000000, 1}, + { 5, 0x04000000, 0x06000000, 1}, + { 7, 0x01000000, 0x03000000, 1}, + { 9, 0x00400000, 0x00600000, 1}, + { 11, 0x00100000, 0x00300000, 1}, + { 13, 0x00040000, 0x00060000, 1}, + { 15, 0x00010000, 0x00030000, 1}, + { 17, 0x00004000, 0x00006000, 1}, + { 19, 0x00001000, 0x00003000, 1}, + { 21, 0x00000400, 0x00000600, 1}, + { 23, 0x00000100, 0x00000300, 1}, + { 25, 0x00000040, 0x00000060, 1}, + { 27, 0x00000010, 0x00000030, 1}, + { 29, 0x00000004, 0x00000006, 1}, + { 31, 0x00000001, 0x00000003, 1}}; +#endif + + +double LineSegDistance( coOrd p, coOrd p0, coOrd p1 ) +{ + double d, a; + coOrd pp, zero; + zero.x = zero.y = (POS_T)0.0; + d = FindDistance( p0, p1 ); + a = FindAngle( p0, p1 ); + pp.x = p.x-p0.x; + pp.y = p.y-p0.y; + Rotate( &pp, zero, -a ); + if (pp.y < 0.0-EPSILON) { + return FindDistance( p, p0 ); + } else if (pp.y > d+EPSILON ) { + return FindDistance( p, p1 ); + } else { + return pp.x>=0? pp.x : -pp.x; + } +} + + + +double CircleSegDistance( coOrd p, coOrd c, double r, double a0, double a1 ) +{ + double d, d0, d1; + double a,aa; + coOrd p1; + + d = FindDistance( c, p ); + a = FindAngle( c, p ); + aa = NormalizeAngle( a - a0 ); + d -= r; + if ( aa <= a1 ) { + return d>=0 ? d : -d; + } + PointOnCircle( &p1, c, r, a0 ); + d0 = FindDistance( p, p1 ); + PointOnCircle( &p1, c, r, a0+a1 ); + d1 = FindDistance( p, p1 ); + if (d0 < d1) + return d0; + else + return d1; +} + + +BOOL_T HittestTurnoutRoadbed( + trkSeg_p segPtr, + int segCnt, + int segInx, + ANGLE_T side, + int fraction, + DIST_T roadbedWidth ) +{ + ANGLE_T a; + DIST_T d; + int inx; + trkSeg_p sp; + coOrd p0, p1; + DIST_T dd; + int closest; + + sp = &segPtr[segInx]; + if (sp->type == SEG_STRTRK) { + d = FindDistance( sp->u.l.pos[0], sp->u.l.pos[1] ); + a = FindAngle( sp->u.l.pos[0], sp->u.l.pos[1] ); + d *= (fraction*2+1)/64.0; + Translate( &p0, sp->u.l.pos[0], a, d ); + Translate( &p0, p0, a+side, roadbedWidth/2.0 ); + } else { + d = sp->u.c.radius; + if ( d < 0 ) { + d = -d; + fraction = 31-fraction; + } + a = sp->u.c.a0 + sp->u.c.a1*(fraction*2+1)/64.0; + if (side>0) + d += roadbedWidth/2.0; + else + d -= roadbedWidth/2.0; + PointOnCircle( &p0, sp->u.c.center, d, a ); + } + dd = 100000.0; + closest = -1; + for (inx=0; inxtype ) { + case SEG_STRTRK: + d = LineSegDistance( p1, sp->u.l.pos[0], sp->u.l.pos[1] ); + break; + case SEG_CRVTRK: + d = CircleSegDistance( p1, sp->u.c.center, fabs(sp->u.c.radius), sp->u.c.a0, sp->u.c.a1 ); + break; + default: + continue; + } +#ifdef LATER + if (inx==segInx) + d *= .999; +#endif + if ( d < dd ) { + dd = d; + closest = inx; + } + } + if (closest == segInx) + return FALSE; + else + return TRUE; +} + +#ifdef LATER +EXPORT long ComputeTurnoutRoadbedSide( + trkSeg_p segPtr, + int segCnt, + int segInx, + ANGLE_T side, + DIST_T roadbedWidth ) +{ + DIST_T length; + int rbw; + unsigned long res, res1; + searchTable_t * p; + double where; + trkSeg_p sp; + + sp = &segPtr[segInx]; + if (sp->type == SEG_STRTRK) + length = FindDistance( sp->u.l.pos[0], sp->u.l.pos[1] ); + else + length = (fabs(sp->u.c.radius) + (side>0?roadbedWidth/2.0:-roadbedWidth/2.0) ) * 2 * M_PI * sp->u.c.a1 / 360.0; + rbw = (int)(roadbedWidth/length*32/2); +/*printf( "L=%0.3f G=%0.3f [%0.3f %0.3f] RBW=%d\n", length, gapWidth, first, last, rbw );*/ + res = 0xFF0000FF; + for ( p=searchTable; p<&searchTable[sizeof searchTable/sizeof searchTable[0]]; p++) { + if ( (p->width < rbw && res==0xFFFFFFFF) || res==0 ) + break; + res1 = (p->mask & res); + where = p->start*length/32.0; + if (p->width >= rbw || (res1!=p->mask && res1!=0)) { + if (HittestTurnoutRoadbed(segPtr, segCnt, segInx, side, p->start)) { + res &= ~p->bits; +if (debugComputeRoadbed>=1) printf( "res=%08lx *p={%02d %08lx %08lx %02d} res1=%08lx W=%0.3f HIT\n", res, p->start, p->bits, p->mask, p->width, res1, where ); + } else { + res |= p->bits; +if (debugComputeRoadbed>=1) printf( "res=%08lx *p={%02d %08lx %08lx %02d} res1=%08lx W=%0.3f MISS\n", res, p->start, p->bits, p->mask, p->width, res1, where ); + } + } else { +if (debugComputeRoadbed>=2) printf( "res=%08lx *p={%02d %08lx %08lx %02d} res1=%08lx W=%0.3f SKIP\n", res, p->start, p->bits, p->mask, p->width, res1, where ); + } + } +if (debugComputeRoadbed>=1) printf( "res=%08lx\n", res ); + return res; +} +#endif + + +EXPORT long ComputeTurnoutRoadbedSide( + trkSeg_p segPtr, + int segCnt, + int segInx, + ANGLE_T side, + DIST_T roadbedWidth ) +{ + trkSeg_p sp; + DIST_T length; + int bitWidth; + unsigned long res, mask; + int hit0, hit1, inx0, inx1; + int i, j, k, hitx; + + sp = &segPtr[segInx]; + if (sp->type == SEG_STRTRK) + length = FindDistance( sp->u.l.pos[0], sp->u.l.pos[1] ); + else + length = (fabs(sp->u.c.radius) + (side>0?roadbedWidth/2.0:-roadbedWidth/2.0) ) * 2 * M_PI * sp->u.c.a1 / 360.0; + bitWidth = (int)floor(roadbedWidth*32/length); + if ( bitWidth > 31 ) + bitWidth = 31; + else if ( bitWidth <= 0 ) + bitWidth = 2; + res = 0; + mask = (1<=3 ) printf( "bW=%d HT[0]=%d\n", bitWidth, hit0 ); + while ( 1 ) { + if ( inx1 > 31 ) + inx1 = 31; + hit1 = HittestTurnoutRoadbed( segPtr, segCnt, segInx, side, inx1, roadbedWidth ); +if ( debugComputeRoadbed>=3 ) printf( " HT[%d]=%d\n", inx1, hit1 ); + if ( hit0 != hit1 ) { + i=inx0; + j=inx1; + while ( j-i >= 2 ) { + k = (i+j)/2; + hitx = HittestTurnoutRoadbed( segPtr, segCnt, segInx, side, k, roadbedWidth ); +if ( debugComputeRoadbed>=3 ) printf( " .HT[%d]=%d\n", k, hitx ); + if ( hitx == hit0 ) + i = k; + else + j = k; + } + if ( !hit0 ) { + res |= ((1<<(i-inx0+1))-1)<=3 ) printf( " res=%lx\n", res ); + if ( inx1 >= 31 ) { + if ( !hit1 ) + res |= 0x80000000; + break; + } + mask <<= bitWidth; + inx0 = inx1; + inx1 += bitWidth; + hit0 = hit1; + } +if ( debugComputeRoadbed>=2 ) printf( "S%d %c res=%lx\n", segInx, side>0?'+':'-', res ); + return res; +} + + +static BOOL_T IsNear( coOrd p0, coOrd p1 ) +{ + DIST_T d; + d = FindDistance( p0, p1 ); + return d < 0.05; +} + + +static void AddRoadbedPieces( + int inx, + ANGLE_T side, + int first, + int last ) +{ + DIST_T d0, d1; + ANGLE_T a0, a1; + coOrd p0, p1; + trkSeg_p sp, sq; +#ifdef MKTURNOUT +#define _DPI (76.0) +#else +#define _DPI mainD.dpi +#endif + + if (last<=first) + return; + sp = &tempSegs(inx); + if ( sp->type == SEG_STRTRK ) { + d0 = FindDistance( sp->u.l.pos[0], sp->u.l.pos[1] ); + a0 = FindAngle( sp->u.l.pos[0], sp->u.l.pos[1] ); + d1 = d0*first/32.0; + Translate( &p0, sp->u.l.pos[0], a0, d1 ); + Translate( &p0, p0, a0+side, newTurnRoadbedWidth/2.0 ); + d1 = d0*last/32.0; + Translate( &p1, sp->u.l.pos[0], a0, d1 ); + Translate( &p1, p1, a0+side, newTurnRoadbedWidth/2.0 ); + if ( first==0 || last==32 ) { + for ( sq=&tempSegs(0); sq<&tempSegs(tempSegs_da.cnt); sq++ ) { + if ( sq->type == SEG_STRLIN ) { + a1 = FindAngle( sq->u.l.pos[0], sq->u.l.pos[1] ); + a1 = NormalizeAngle( a1-a0+0.5 ); + if ( first==0 ) { + if ( a1 < 1.0 && IsNear( p0, sq->u.l.pos[1] ) ) { + sq->u.l.pos[1] = p1; + return; + } else if ( a1 > 180.0 && a1 < 181.0 && IsNear( p0, sq->u.l.pos[0] ) ) { + sq->u.l.pos[0] = p1; + return; + } + } + if ( last==32 ) { + if ( a1 < 1.0 && IsNear( p1, sq->u.l.pos[0] ) ) { + sq->u.l.pos[0] = p0; + return; + } else if ( a1 > 180.0 && a1 < 181.0 && IsNear( p1, sq->u.l.pos[1] ) ) { + sq->u.l.pos[1] = p0; + return; + } + } + } + } + } + } + DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 ); + sp = &tempSegs(inx); + sq = &tempSegs(tempSegs_da.cnt-1); + sq->width = newTurnRoadbedLineWidth/(_DPI); + sq->color = roadbedColor; + if (sp->type == SEG_STRTRK) { + sq->type = SEG_STRLIN; + sq->u.l.pos[0] = p0; + sq->u.l.pos[1] = p1; + } else { + d0 = sp->u.c.radius; + if ( d0 > 0 ) { + a0 = NormalizeAngle( sp->u.c.a0 + sp->u.c.a1*first/32.0 ); + } else { + d0 = -d0; + a0 = NormalizeAngle( sp->u.c.a0 + sp->u.c.a1*(32-last)/32.0 ); + } + a1 = sp->u.c.a1*(last-first)/32.0; + if (side>0) + d0 += newTurnRoadbedWidth/2.0; + else + d0 -= newTurnRoadbedWidth/2.0; + sq->type = SEG_CRVLIN; + sq->u.c.center = sp->u.c.center; + sq->u.c.radius = d0; + sq->u.c.a0 = a0; + sq->u.c.a1 = a1; + } +} + + +static void AddRoadbedToOneSide( + int trkCnt, + int inx, + ANGLE_T side ) +{ + unsigned long res, res1; + int b0, b1; + + res = ComputeTurnoutRoadbedSide( &tempSegs(0), trkCnt, inx, side, newTurnRoadbedWidth ); + if ( res == 0L ) { + return; + } else if ( res == 0xFFFFFFFF ) { + AddRoadbedPieces( inx, 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 ); + AddRoadbedPieces( inx, side, 0, b0 ); + AddRoadbedPieces( inx, side, b1, 32 ); + } +} + + +static void AddRoadbed( void ) +{ + int trkCnt, inx; + trkSeg_p sp; + if ( newTurnRoadbedWidth < newTurnTrackGauge ) + return; + trkCnt = tempSegs_da.cnt; + for ( inx=0; inxtype!=SEG_STRTRK && sp->type!=SEG_CRVTRK ) + continue; + AddRoadbedToOneSide( trkCnt, inx, +90 ); + AddRoadbedToOneSide( trkCnt, inx, -90 ); + } +} + + +/********************************************************************* + * + * Functions + * + */ + +static BOOL_T ComputeCurve( + coOrd *p0, coOrd *p1, DIST_T *radius, + DIST_T len, DIST_T off, ANGLE_T angle ) +{ + coOrd Pf; + coOrd Px, Pc; + DIST_T d; + + Pf.x = len; + Pf.y = off; + p0->x = p0->y = 0.0; + /*lprintf( "Angle = %0.3f\n", angle );*/ + FindIntersection( &Px, *p0, 90.0, Pf, 90.0-angle ); + d = FindDistance( Px, Pf )-newTurnTrackGauge; + if (Px.x < newTurnTrackGauge || d < 0.0) { + NoticeMessage( MSG_TODSGN_NO_CONVERGE, _("Ok"), NULL ); + return FALSE; + } + if (Px.x-newTurnTrackGauge < d) + d = Px.x-newTurnTrackGauge; + *radius = d * cos( D2R(angle/2.0) ) / sin( D2R(angle/2.0) ); + + p0->x = Px.x - *radius * sin( D2R(angle/2.0) ) / cos( D2R(angle/2.0) ); + Translate( &Pc, *p0, 0.0, *radius ); + PointOnCircle( p1, Pc, *radius, 180.0-angle ); + + return TRUE; +} + + + +static toDesignSchema_t * LoadSegs( + toDesignDesc_t * dp, + wBool_t loadPoints, + wIndex_t * pathLenP ) +{ + wIndex_t s; + int i, p, p0, p1; + DIST_T d; +#ifndef MKTURNOUT + wIndex_t pathLen; +#endif + toDesignSchema_t * pp; + char *segOrder; + coOrd pos; + wIndex_t segCnt; + ANGLE_T angle1, angle2; + trkSeg_p segPtr; + + DYNARR_RESET( trkSeg_t, tempSegs_da ); + angle1 = newTurnAngle1; + angle2 = newTurnAngle2; + if ( newTurnAngleMode == 0 && dp->type != NTO_CRV_SECTION ) { + /* convert from Frog Num to degrees */ + if ( angle1 > 0 ) + angle1 = R2D(asin(1.0 / angle1)); + if ( angle2 > 0 ) + angle2 = R2D(asin(1.0 / angle2)); + } + + pp = dp->paths; + if (loadPoints) { + DYNARR_RESET( trkEndPt_t, tempEndPts_da ); + for ( i=0; ifloatCnt; i++ ) + if ( *(FLOAT_T*)(turnDesignPLs[dp->floats[i].index].valueP) == 0.0 ) { + NoticeMessage( MSG_TODSGN_VALUES_GTR_0, _("Ok"), NULL ); + return NULL; + } + + switch (dp->type) { + case NTO_REGULAR: + DYNARR_SET( trkEndPt_t, tempEndPts_da, 3 ); + if ( !ComputeCurve( &points[3], &points[4], &radii[0], + (newTurnLen1), (newTurnOff1), angle1 ) ) + return NULL; + radii[0] = - radii[0]; + points[0].x = points[0].y = points[1].y = 0.0; + points[1].x = (newTurnLen0); + points[2].y = (newTurnOff1); + points[2].x = (newTurnLen1); + tempEndPts(0).pos = points[0]; tempEndPts(0).angle = 270.0; + tempEndPts(1).pos = points[1]; tempEndPts(1).angle = 90.0; + tempEndPts(2).pos = points[2]; tempEndPts(2).angle = 90.0-angle1; + break; + + case NTO_CURVED: + DYNARR_SET( trkEndPt_t, tempEndPts_da, 3 ); + if ( !ComputeCurve( &points[3], &points[4], &radii[0], + (newTurnLen1), (newTurnOff1), angle1 ) ) + return NULL; + if ( !ComputeCurve( &points[5], &points[6], &radii[1], + (newTurnLen2), (newTurnOff2), angle2 ) ) + return NULL; + d = points[3].x - points[5].x; + if ( d < -0.10 ) + pp = &Crv3Schema; + else if ( d > 0.10 ) + pp = &Crv2Schema; + else + pp = &Crv1Schema; + radii[0] = - radii[0]; + radii[1] = - radii[1]; + points[0].x = points[0].y = 0.0; + points[1].y = (newTurnOff1); points[1].x = (newTurnLen1); + points[2].y = (newTurnOff2); points[2].x = (newTurnLen2); + tempEndPts(0).pos = points[0]; tempEndPts(0).angle = 270.0; + tempEndPts(2).pos = points[1]; tempEndPts(2).angle = 90.0-angle1; + tempEndPts(1).pos = points[2]; tempEndPts(1).angle = 90.0-angle2; + break; + + case NTO_WYE: + case NTO_3WAY: + DYNARR_SET( trkEndPt_t, tempEndPts_da, (dp->type==NTO_3WAY)?4:3 ); + if ( !ComputeCurve( &points[3], &points[4], &radii[0], + (newTurnLen1), (newTurnOff1), angle1 ) ) + return NULL; + if ( !ComputeCurve( &points[5], &points[6], &radii[1], + (newTurnLen2), (newTurnOff2), angle2 ) ) + return NULL; + points[5].y = - points[5].y; + points[6].y = - points[6].y; + radii[0] = - radii[0]; + points[0].x = points[0].y = 0.0; + points[1].y = (newTurnOff1); + points[1].x = (newTurnLen1); + points[2].y = -(newTurnOff2); + points[2].x = (newTurnLen2); + points[7].y = 0; + points[7].x = (newTurnLen0); + d = points[3].x - points[5].x; + if ( d < -0.10 ) { + pp = (dp->type==NTO_3WAY ? &Tri3Schema : &Wye3Schema ); + } else if ( d > 0.10 ) { + pp = (dp->type==NTO_3WAY ? &Tri2Schema : &Wye2Schema ); + } else { + pp = (dp->type==NTO_3WAY ? &Tri1Schema : &Wye1Schema ); + } + tempEndPts(0).pos = points[0]; tempEndPts(0).angle = 270.0; + tempEndPts(1).pos = points[1]; tempEndPts(1).angle = 90.0-angle1; + tempEndPts(2).pos = points[2]; tempEndPts(2).angle = 90.0+angle2; + if (dp->type == NTO_3WAY) { + tempEndPts(3).pos = points[7]; tempEndPts(3).angle = 90.0; + } + break; + + case NTO_D_SLIP: + case NTO_S_SLIP: + case NTO_CROSSING: + DYNARR_SET( trkEndPt_t, tempEndPts_da, 4 ); + points[0].x = points[0].y = points[1].y = 0.0; + points[1].x = (newTurnLen1); + pos.y = 0; pos.x = (newTurnLen1)/2.0; + Translate( &points[3], pos, 90.0+angle1, (newTurnLen2)/2.0 ); + points[2].y = - points[3].y; + points[2].x = (newTurnLen1)-points[3].x; + if (dp->type != NTO_CROSSING) { + Translate( &pos, points[3], 90.0+angle1, -newTurnTrackGauge ); + if (!ComputeCurve( &points[4], &points[5], &radii[0], + pos.x, fabs(pos.y), angle1 )) /*???*/ + return NULL; + radii[1] = - radii[0]; + points[5].y = - points[5].y; + points[6].y = 0; points[6].x = (newTurnLen1)-points[4].x; + points[7].y = -points[5].y; + points[7].x = (newTurnLen1)-points[5].x; + } + tempEndPts(0).pos = points[0]; tempEndPts(0).angle = 270.0; + tempEndPts(1).pos = points[1]; tempEndPts(1).angle = 90.0; + tempEndPts(2).pos = points[2]; tempEndPts(2).angle = 270.0+angle1; + tempEndPts(3).pos = points[3]; tempEndPts(3).angle = 90.0+angle1; + break; + + case NTO_R_CROSSOVER: + case NTO_L_CROSSOVER: + case NTO_D_CROSSOVER: + DYNARR_SET( trkEndPt_t, tempEndPts_da, 4 ); + d = (newTurnLen1)/2.0 - newTurnTrackGauge; + if (d < 0.0) { + NoticeMessage( MSG_TODSGN_CROSSOVER_TOO_SHORT, _("Ok"), NULL ); + return NULL; + } + angle1 = R2D( atan2( (newTurnOff1), d ) ); + points[0].y = 0.0; points[0].x = 0.0; + points[1].y = 0.0; points[1].x = (newTurnLen1); + points[2].y = (newTurnOff1); points[2].x = 0.0; + points[3].y = (newTurnOff1); points[3].x = (newTurnLen1); + if (!ComputeCurve( &points[4], &points[5], &radii[1], + (newTurnLen1)/2.0, (newTurnOff1)/2.0, angle1 ) ) + return NULL; + radii[0] = - radii[1]; + points[6].y = 0.0; points[6].x = (newTurnLen1)-points[4].x; + points[7].y = points[5].y; points[7].x = (newTurnLen1)-points[5].x; + points[8].y = (newTurnOff1); points[8].x = points[4].x; + points[9].y = (newTurnOff1)-points[5].y; points[9].x = points[5].x; + points[10].y = (newTurnOff1); points[10].x = points[6].x; + points[11].y = points[9].y; points[11].x = points[7].x; + tempEndPts(0).pos = points[0]; tempEndPts(0).angle = 270.0; + tempEndPts(1).pos = points[1]; tempEndPts(1).angle = 90.0; + tempEndPts(2).pos = points[2]; tempEndPts(2).angle = 270.0; + tempEndPts(3).pos = points[3]; tempEndPts(3).angle = 90.0; + break; + + case NTO_STR_SECTION: + DYNARR_SET( trkEndPt_t, tempEndPts_da, 2 ); + points[0].y = points[0].x = 0; + points[1].y = 0/*(newTurnOff1)*/; points[1].x = (newTurnLen1); + tempEndPts(0).pos = points[0]; tempEndPts(0).angle = 270.0; + tempEndPts(1).pos = points[1]; tempEndPts(1).angle = 90.0; + break; + + case NTO_CRV_SECTION: + DYNARR_SET( trkEndPt_t, tempEndPts_da, 2 ); + points[0].y = points[0].x = 0; + points[1].y = (newTurnLen1) * (1.0 - cos( D2R(angle1) ) ); + points[1].x = (newTurnLen1) * sin( D2R(angle1) ); + radii[0] = -(newTurnLen1); + tempEndPts(0).pos = points[0]; tempEndPts(0).angle = 270.0; + tempEndPts(1).pos = points[1]; tempEndPts(1).angle = 90.0-angle1; + break; + + case NTO_BUMPER: + DYNARR_SET( trkEndPt_t, tempEndPts_da, 1 ); + points[0].y = points[0].x = 0; + points[1].y = 0/*(newTurnOff1)*/; points[1].x = (newTurnLen1); + tempEndPts(0).pos = points[0]; tempEndPts(0).angle = 270.0; + break; + + default: + ; + } + } else { + switch (dp->type) { + case NTO_CURVED: + d = points[3].x - points[5].x; + if ( d < -0.10 ) + pp = &Crv3Schema; + else if ( d > 0.10 ) + pp = &Crv2Schema; + else + pp = &Crv1Schema; + break; + } + } + + segOrder = pp->segOrder; + segCnt = strlen( segOrder ); + if (segCnt%3 != 0) + AbortProg( dp->label ); + segCnt /= 3; + DYNARR_SET( trkSeg_t, tempSegs_da, segCnt ); + tempSegs_da.cnt = segCnt; + memset( &tempSegs(0), 0, segCnt * sizeof tempSegs(0) ); + for ( s=0; scolor = wDrawColorBlack; + if (*segOrder <= '9') + p0 = *segOrder++ - '0'; + else + p0 = *segOrder++ - 'A' + 10; + if (*segOrder <= '9') + p1 = *segOrder++ - '0'; + else + p1 = *segOrder++ - 'A' + 10; + p = *segOrder++ - '0'; + if (p != 0) { + segPtr->type = SEG_CRVTRK; + ComputeCurvedSeg( segPtr, radii[p-1], points[p0], points[p1] ); + } else { + segPtr->type = SEG_STRTRK; + segPtr->u.l.pos[0] = points[p0]; + segPtr->u.l.pos[1] = points[p1]; + } + } + + AddRoadbed(); + +#ifndef MKTURNOUT + if ( (pathLen=CheckPaths( segCnt, &tempSegs(0), pp->paths )) < 0 ) + return NULL; + + if (pathLenP) + *pathLenP = pathLen; +#endif + return pp; +} + + +static void CopyNonTracks( turnoutInfo_t * to ) +{ + trkSeg_p sp0; + for ( sp0=to->segs; sp0<&to->segs[to->segCnt]; sp0++ ) { + if ( sp0->type != SEG_STRTRK && sp0->type != SEG_CRVTRK ) { + DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 ); + tempSegs(tempSegs_da.cnt-1) = *sp0; + } + } +} + + +#ifndef MKTURNOUT +static void NewTurnPrint( + void * junk ) +{ + coOrd pos, p0, p1; + WDOUBLE_T px, py; + int i, j, ii, jj, p; + EPINX_T ep; + wFont_p fp; + coOrd orig, size; + toDesignSchema_t * pp; + POS_T tmp; + FLOAT_T tmpR; + static drawCmd_t newTurnout_d = { + NULL, + &printDrawFuncs, + DC_PRINT, + 1.0, + 0.0, + { 0.0, 0.0 }, + { 0.0, 0.0 }, + Pix2CoOrd, CoOrd2Pix }; + + if ((pp=LoadSegs( curDesign, TRUE, NULL )) == NULL) + return; + if (includeNontrackSegments && customTurnout1) + CopyNonTracks( customTurnout1 ); + + GetSegBounds( zero, 0.0, tempSegs_da.cnt, &tempSegs(0), &orig, &size ); + tmp = orig.x; orig.x = orig.y; orig.y = tmp; +#ifdef LATER + size.x = 0.0; size.y = 0.0; + orig.x = 0.0; orig.y = 0.0; + for ( i=0; itype) { + case SEG_STRLIN: + case SEG_STRTRK: + pos[0] = segPtr->u.l.pos[0]; + pos[1] = segPtr->u.l.pos[1]; + break; + case SEG_CRVTRK: + case SEG_CRVLIN: + PointOnCircle( &pos[0], segPtr->u.c.center, segPtr->u.c.radius, + segPtr->u.c.a0 ); + PointOnCircle( &pos[1], segPtr->u.c.center, segPtr->u.c.radius, + segPtr->u.c.a0+segPtr->u.c.a1 ); + } + for ( ep=0; ep<2; ep++ ) { + if (pos[ep].x < orig.x) + orig.x = pos[ep].x; + if (pos[ep].x > size.x) + size.x = pos[ep].x; + if (pos[ep].y < orig.y) + orig.y = pos[ep].y; + if (pos[ep].y > size.y) + size.y = pos[ep].y; + } + } + + size.x -= orig.x; + size.y -= orig.y; +#endif + + fp = wStandardFont( F_TIMES, FALSE, FALSE ); + wPrintGetPageSize( &px, &py ); + newTurnout_d.size.x = px; + newTurnout_d.size.y = py; + ii = (int)(size.y/newTurnout_d.size.x)+1; + jj = (int)(size.x/newTurnout_d.size.y)+1; + if ( !wPrintDocStart( sTurnoutDesignerW, ii*jj, NULL ) ) + return; +#ifdef LATER + orig.x -= (0.5); + orig.y -= (jj*newTurnout_d.size.y-size.y)/2.0; +#endif + orig.x = - ( size.y + orig.x + newTurnTrackGauge/2.0 + 0.5 ); + orig.y -= (0.5); + for ( i=0, newTurnout_d.orig.x=orig.x; ilabel) ); + wDrawString( newTurnout_d.d, POSX(3.0), + POSY(6.25), 0.0, message, fp, 30, + wDrawColorBlack, 0 ); + sprintf( message, "%s %d x %d (of %d x %d)", _("Page"), i+1, j+1, ii, jj ); + wDrawString( newTurnout_d.d, POSX(3.0), + POSY(5.75), 0.0, message, fp, 20, + wDrawColorBlack, 0 ); + + for ( p=0; pfloatCnt; p++ ) { + tmpR = *(FLOAT_T*)(turnDesignPLs[curDesign->floats[p].index].valueP); + sprintf( message, "%s: %s", + (curDesign->floats[p].mode!=Frog_e||newTurnAngleMode!=0)?_(curDesign->floats[p].printLabel):_("Frog Number"), + curDesign->floats[p].mode==Dim_e? + FormatDistance(tmpR): + FormatFloat(tmpR) ); + wDrawString( newTurnout_d.d, POSX(3.0), + POSY(5.50-p*0.25), 0.0, + message, fp, 20, wDrawColorBlack, 0 ); + } + if (newTurnLeftDesc[0] || newTurnLeftPartno[0]) { + sprintf( message, "%s %s %s", newTurnManufacturer, newTurnLeftPartno, newTurnLeftDesc ); + wDrawString( newTurnout_d.d, POSX(3.0), + POSY(5.50-curDesign->floatCnt*0.25), 0.0, + message, fp, 20, wDrawColorBlack, 0 ); + } + if (newTurnRightDesc[0] || newTurnRightPartno[0]) { + sprintf( message, "%s %s %s", newTurnManufacturer, newTurnRightPartno, newTurnRightDesc ); + wDrawString( newTurnout_d.d, POSX(3.0), + POSY(5.50-curDesign->floatCnt*0.25-0.25), 0.0, + message, fp, 20, wDrawColorBlack, 0 ); + } + + wDrawLine( newTurnout_d.d, POSX(0), POSY(0), + POSX(newTurnout_d.size.x), POSY(0), 0, wDrawLineSolid, + wDrawColorBlack, 0 ); + wDrawLine( newTurnout_d.d, POSX(newTurnout_d.size.x), POSY(0.0), + POSX(newTurnout_d.size.x), POSY(newTurnout_d.size.y), 0, + wDrawLineSolid, wDrawColorBlack, 0 ); + wDrawLine( newTurnout_d.d, POSX(newTurnout_d.size.x), POSY(newTurnout_d.size.y), + POSX(0.0), POSY(newTurnout_d.size.y), 0, wDrawLineSolid, + wDrawColorBlack, 0 ); + wDrawLine( newTurnout_d.d, POSX(0.0), POSY(newTurnout_d.size.y), + POSX(0.0), POSX(0.0), 0, wDrawLineSolid, wDrawColorBlack, 0 ); + + DrawSegs( &newTurnout_d, zero, 270.0, &tempSegs(0), tempSegs_da.cnt, newTurnTrackGauge, wDrawColorBlack ); + + for ( ep=0; epstrCnt >= 1 && newTurnLeftDesc[0] == 0) || + (curDesign->strCnt >= 2 && newTurnRightDesc[0] == 0) ) { + NoticeMessage( MSG_TODSGN_DESC_NONBLANK, _("Ok"), NULL ); + return; + } + + BuildTrimedTitle( message, "\t", newTurnManufacturer, newTurnLeftDesc, newTurnLeftPartno ); +#ifndef MKTURNOUT + if ( customTurnout1 == NULL && + ( foundR || FindCompound( FIND_TURNOUT, newTurnScaleName, message ) ) ) { + if ( !NoticeMessage( MSG_TODSGN_REPLACE, _("Yes"), _("No") ) ) + return; + } + oldLocale = SaveLocale("C"); +#endif + + f = OpenCustom("a"); + + sprintf( tempCustom, "\"%s\" \"%s\" \"", + curDesign->label, "" ); + cp = tempCustom + strlen(tempCustom); + cp = Strcpytrimed( cp, newTurnManufacturer, TRUE ); + strcpy( cp, "\" \"" ); + cp += 3; + cp = Strcpytrimed( cp, newTurnLeftDesc, TRUE ); + strcpy( cp, "\" \"" ); + cp += 3; + cp = Strcpytrimed( cp, newTurnLeftPartno, TRUE ); + strcpy( cp, "\"" ); + cp += 1; + if (curDesign->type == NTO_REGULAR || curDesign->type == NTO_CURVED) { + strcpy( cp, " \"" ); + cp += 2; + cp = Strcpytrimed( cp, newTurnRightDesc, TRUE ); + strcpy( cp, "\" \"" ); + cp += 3; + cp = Strcpytrimed( cp, newTurnRightPartno, TRUE ); + strcpy( cp, "\"" ); + cp += 1; + } + if ( cp-tempCustom > sizeof tempCustom ) + AbortProg( "Custom line overflow" ); + for ( i=0; ifloatCnt; i++ ) { + flt = *(FLOAT_T*)(turnDesignPLs[curDesign->floats[i].index].valueP); + switch( curDesign->floats[i].mode ) { + case Dim_e: + flt = ( flt ); + break; + case Frog_e: + if (newTurnAngleMode == 0 && flt > 0.0) + flt = R2D(asin(1.0/flt)); + break; + case Angle_e: + break; + } + sprintf( cp, " %0.6f", flt ); + cp += strlen(cp); + } + sprintf( cp, " %0.6f %0.6f %ld", newTurnRoadbedWidth, newTurnRoadbedLineWidth/(_DPI), wDrawGetRGB(roadbedColor) ); + customInfoP = MyStrdup( tempCustom ); + strcpy( tempCustom, message ); + + segCnt = tempSegs_da.cnt; +#ifndef MKTURNOUT + if (includeNontrackSegments && customTurnout1) + CopyNonTracks( customTurnout1 ); + if ( customTurnout1 ) + customTurnout1->segCnt = 0; + to = CreateNewTurnout( newTurnScaleName, tempCustom, tempSegs_da.cnt, &tempSegs(0), + pathLen, pp->paths, tempEndPts_da.cnt, &tempEndPts(0), FALSE ); + to->customInfo = customInfoP; +#endif + if (f) { + fprintf( f, "TURNOUT %s \"%s\"\n", newTurnScaleName, PutTitle(tempCustom) ); +#ifdef MKTURNOUT + if (doCustomInfoLine) +#endif + fprintf( f, "\tU %s\n", customInfoP ); + WriteCompoundPathsEndPtsSegs( f, pp->paths, tempSegs_da.cnt, &tempSegs(0), + tempEndPts_da.cnt, &tempEndPts(0) ); + } + + switch (curDesign->type) { + case NTO_REGULAR: + points[2].y = - points[2].y; + points[4].y = - points[4].y; + radii[0] = - radii[0]; + LoadSegs( curDesign, FALSE, &pathLen ); + tempEndPts(2).pos.y = - tempEndPts(2).pos.y; + tempEndPts(2).angle = 180.0 - tempEndPts(2).angle; + BuildTrimedTitle( tempCustom, "\t", newTurnManufacturer, newTurnRightDesc, newTurnRightPartno ); + tempSegs_da.cnt = segCnt; +#ifndef MKTURNOUT + if (includeNontrackSegments && customTurnout2) + CopyNonTracks( customTurnout2 ); + if ( customTurnout2 ) + customTurnout2->segCnt = 0; + to = CreateNewTurnout( newTurnScaleName, tempCustom, tempSegs_da.cnt, &tempSegs(0), + pathLen, pp->paths, tempEndPts_da.cnt, &tempEndPts(0), FALSE ); + to->customInfo = customInfoP; +#endif + if (f) { + fprintf( f, "TURNOUT %s \"%s\"\n", newTurnScaleName, PutTitle(tempCustom) ); +#ifdef MKTURNOUT + if (doCustomInfoLine) +#endif + fprintf( f, "\tU %s\n", customInfoP ); + WriteCompoundPathsEndPtsSegs( f, pp->paths, tempSegs_da.cnt, &tempSegs(0), tempEndPts_da.cnt, &tempEndPts(0) ); + } + break; + case NTO_CURVED: + points[1].y = - points[1].y; + points[2].y = - points[2].y; + points[4].y = - points[4].y; + points[6].y = - points[6].y; + radii[0] = - radii[0]; + radii[1] = - radii[1]; + LoadSegs( curDesign, FALSE, &pathLen ); + tempEndPts(1).pos.y = - tempEndPts(1).pos.y; + tempEndPts(1).angle = 180.0 - tempEndPts(1).angle; + tempEndPts(2).pos.y = - tempEndPts(2).pos.y; + tempEndPts(2).angle = 180.0 - tempEndPts(2).angle; + BuildTrimedTitle( tempCustom, "\t", newTurnManufacturer, newTurnRightDesc, newTurnRightPartno ); + tempSegs_da.cnt = segCnt; +#ifndef MKTURNOUT + if (includeNontrackSegments && customTurnout2) + CopyNonTracks( customTurnout2 ); + if ( customTurnout2 ) + customTurnout2->segCnt = 0; + to = CreateNewTurnout( newTurnScaleName, tempCustom, tempSegs_da.cnt, &tempSegs(0), + pathLen, pp->paths, tempEndPts_da.cnt, &tempEndPts(0), FALSE ); + to->customInfo = customInfoP; +#endif + if (f) { + fprintf( f, "TURNOUT %s \"%s\"\n", newTurnScaleName, PutTitle(tempCustom) ); +#ifdef MKTURNOUT + if (doCustomInfoLine) +#endif + fprintf( f, "\tU %s\n", customInfoP ); + WriteCompoundPathsEndPtsSegs( f, pp->paths, tempSegs_da.cnt, &tempSegs(0), tempEndPts_da.cnt, &tempEndPts(0) ); + } + break; + default: + ; + } + tempCustom[0] = '\0'; + +#ifndef MKTURNOUT + if (f) + fclose(f); + RestoreLocale(oldLocale); + includeNontrackSegments = TRUE; + wHide( newTurnW ); + DoChangeNotification( CHANGE_PARAMS ); + +#endif + +} + + +#ifndef MKTURNOUT +static void NewTurnCancel( wWin_p win ) +{ + wHide( newTurnW ); + includeNontrackSegments = TRUE; +} + + + +static wPos_t turnDesignWidth; +static wPos_t turnDesignHeight; + +static void TurnDesignLayout( + paramData_t * pd, + int index, + wPos_t colX, + wPos_t * w, + wPos_t * h ) +{ + wPos_t inx; + if ( curDesign == NULL ) + return; + if ( index >= I_TO_FIRST_FLOAT && index <= I_TO_LAST_FLOAT ) { + for ( inx=0; inxfloatCnt; inx++ ) { + if ( index == curDesign->floats[inx].index ) { + *w = curDesign->floats[inx].pos.x; + *h = curDesign->floats[inx].pos.y; + return; + } + } + AbortProg( "turnDesignLayout: bad index = %d", index ); + } else if ( index == I_TOMANUF ) { + *h = turnDesignHeight + 10; + } +} + + +static void SetupTurnoutDesignerW( toDesignDesc_t * newDesign ) +{ + static wPos_t partnoWidth; + int inx; + wPos_t w, h, ctlH; + + if ( newTurnW == NULL ) { + partnoWidth = wLabelWidth( "999-99999-9999" ); + turnDesignPLs[I_TOLDESC+1].winData = + turnDesignPLs[I_TORDESC+1].winData = + (void*)(intptr_t)partnoWidth; + partnoWidth += wLabelWidth( " # " ); + newTurnW = ParamCreateDialog( &turnDesignPG, _("Turnout Designer"), _("Print"), NewTurnPrint, NewTurnCancel, TRUE, TurnDesignLayout, F_BLOCK, NULL ); + for ( inx=0; inx<(sizeof designDescs/sizeof designDescs[0]); inx++ ) { + designDescs[inx]->lineC = wLineCreate( turnDesignPG.win, NULL, designDescs[inx]->lineCnt, designDescs[inx]->lines ); + wControlShow( (wControl_p)designDescs[inx]->lineC, FALSE ); + } + } + if ( curDesign != newDesign ) { + if ( curDesign ) + wControlShow( (wControl_p)curDesign->lineC, FALSE ); + curDesign = newDesign; + sprintf( message, _("%s %s Designer"), sProdName, _(curDesign->label) ); + wWinSetTitle( newTurnW, message ); + for ( inx=I_TO_FIRST_FLOAT; inx<=I_TO_LAST_FLOAT; inx++ ) { + turnDesignPLs[inx].option |= PDO_DLGIGNORE; + wControlShow( turnDesignPLs[inx].control, FALSE ); + } + for ( inx=0; inxfloatCnt; inx++ ) { + turnDesignPLs[curDesign->floats[inx].index].option &= ~PDO_DLGIGNORE; + wControlSetLabel( turnDesignPLs[curDesign->floats[inx].index].control, _(curDesign->floats[inx].winLabel) ); + wControlShow( turnDesignPLs[curDesign->floats[inx].index].control, TRUE ); + } + wControlShow( turnDesignPLs[I_TORDESC+0].control, curDesign->strCnt>1 ); + wControlShow( turnDesignPLs[I_TORDESC+1].control, curDesign->strCnt>1 ); + wControlShow( (wControl_p)curDesign->lineC, TRUE ); + + turnDesignWidth = turnDesignHeight = 0; + for (inx=0;inxlineCnt;inx++) { + if (curDesign->lines[inx].x0 > turnDesignWidth) + turnDesignWidth = curDesign->lines[inx].x0; + if (curDesign->lines[inx].x1 > turnDesignWidth) + turnDesignWidth = curDesign->lines[inx].x1; + if (curDesign->lines[inx].y0 > turnDesignHeight) + turnDesignHeight = curDesign->lines[inx].y0; + if (curDesign->lines[inx].y1 > turnDesignHeight) + turnDesignHeight = curDesign->lines[inx].y1; + } + ctlH = wControlGetHeight( turnDesignPLs[I_TO_FIRST_FLOAT].control ); + for ( inx=0; inxfloatCnt; inx++ ) { + w = curDesign->floats[inx].pos.x + 80; + h = curDesign->floats[inx].pos.y + ctlH; + if (turnDesignWidth < w) + turnDesignWidth = w; + if (turnDesignHeight < h) + turnDesignHeight = h; + } + if ( curDesign->strCnt > 1 ) { + w = wLabelWidth( _("Right Description") ); + wControlSetLabel( turnDesignPLs[I_TOLDESC].control, _("Left Description") ); + turnDesignPLs[I_TOLDESC].winLabel = N_("Left Description"); + turnDesignPLs[I_TORDESC+0].option &= ~PDO_DLGIGNORE; + turnDesignPLs[I_TORDESC+1].option &= ~PDO_DLGIGNORE; + } else { + w = wLabelWidth( _("Manufacturer") ); + wControlSetLabel( turnDesignPLs[I_TOLDESC].control, _("Description") ); + turnDesignPLs[I_TOLDESC].winLabel = N_("Description"); + turnDesignPLs[I_TORDESC+0].option |= PDO_DLGIGNORE; + turnDesignPLs[I_TORDESC+1].option |= PDO_DLGIGNORE; + } + if ( curDesign->angleModeCnt > 0 ) { + turnDesignPLs[I_TOANGMODE].option &= ~PDO_DLGIGNORE; + wControlShow( turnDesignPLs[I_TOANGMODE].control, TRUE ); + } else { + turnDesignPLs[I_TOANGMODE].option |= PDO_DLGIGNORE; + wControlShow( turnDesignPLs[I_TOANGMODE].control, FALSE ); + } + + w = turnDesignWidth-w; + wStringSetWidth( (wString_p)turnDesignPLs[I_TOMANUF].control, w ); + w -= partnoWidth; + wStringSetWidth( (wString_p)turnDesignPLs[I_TOLDESC].control, w ); + wStringSetWidth( (wString_p)turnDesignPLs[I_TORDESC].control, w ); + ParamLayoutDialog( &turnDesignPG ); + } +} + + +static void ShowTurnoutDesigner( void * context ) +{ + if (recordF) + fprintf( recordF, TURNOUTDESIGNER " SHOW %s\n", ((toDesignDesc_t*)context)->label ); + newTurnScaleName = curScaleName; + newTurnTrackGauge = trackGauge; + SetupTurnoutDesignerW( (toDesignDesc_t*)context ); + newTurnRightDesc[0] = '\0'; + newTurnRightPartno[0] = '\0'; + newTurnLeftDesc[0] = '\0'; + newTurnLeftPartno[0] = '\0'; + newTurnLen0 = + newTurnOff1 = newTurnLen1 = newTurnAngle1 = + newTurnOff2 = newTurnLen2 = newTurnAngle2 = 0.0; + ParamLoadControls( &turnDesignPG ); + ParamGroupRecord( &turnDesignPG ); + customTurnout1 = NULL; + customTurnout2 = NULL; + wShow( newTurnW ); +} + + +static BOOL_T NotClose( DIST_T d ) +{ + return d < -0.001 || d > 0.001; +} + + +EXPORT void EditCustomTurnout( turnoutInfo_t * to, turnoutInfo_t * to1 ) +{ + int i; + toDesignDesc_t * dp; + char * type, * name, *cp, *mfg, *descL, *partL, *descR, *partR; + wIndex_t pathLen; + long rgb; + trkSeg_p sp0, sp1; + BOOL_T segsDiff; + DIST_T width; + + if ( ! GetArgs( to->customInfo, "qqqqqc", &type, &name, &mfg, &descL, &partL, &cp ) ) + return; + for ( i=0; i<(sizeof designDescs/sizeof designDescs[0]); i++ ) { + dp = designDescs[i]; + if ( strcmp( type, dp->label ) == 0 ) { + break; + } + } + if ( i >= (sizeof designDescs/sizeof designDescs[0]) ) + return; + + SetupTurnoutDesignerW(dp); + newTurnTrackGauge = GetScaleTrackGauge( to->scaleInx ); + newTurnScaleName = GetScaleName( to->scaleInx ); + strcpy( newTurnManufacturer, mfg ); + strcpy( newTurnLeftDesc, descL ); + strcpy( newTurnLeftPartno, partL ); + if (dp->type == NTO_REGULAR || dp->type == NTO_CURVED) { + if ( ! GetArgs( cp, "qqc", &descR, &partR, &cp )) + return; + strcpy( newTurnRightDesc, descR ); + strcpy( newTurnRightPartno, partR ); + } else { + descR = partR = ""; + } + for ( i=0; ifloatCnt; i++ ) { + if ( ! GetArgs( cp, "fc", turnDesignPLs[dp->floats[i].index].valueP, &cp ) ) + return; + switch (dp->floats[i].mode) { + case Dim_e: + /* *dp->floats[i].valueP = PutDim( *dp->floats[i].valueP ); */ + break; + case Frog_e: + if (newTurnAngleMode == 0) { + if ( *(FLOAT_T*)(turnDesignPLs[dp->floats[i].index].valueP) > 0.0 ) + *(FLOAT_T*)(turnDesignPLs[dp->floats[i].index].valueP) = 1.0/sin(D2R(*(FLOAT_T*)(turnDesignPLs[dp->floats[i].index].valueP))); + } + break; + case Angle_e: + break; + } + } + rgb = 0; + if ( cp && GetArgs( cp, "ffl", &newTurnRoadbedWidth, &width, &rgb ) ) { + roadbedColor = wDrawFindColor(rgb); + newTurnRoadbedLineWidth = (long)floor(width*mainD.dpi+0.5); + } else { + newTurnRoadbedWidth = 0; + newTurnRoadbedLineWidth = 0; + roadbedColor = wDrawColorBlack; + } + + customTurnout1 = to; + customTurnout2 = to1; + + segsDiff = FALSE; + if ( to ) { + LoadSegs( dp, TRUE, &pathLen ); + segsDiff = FALSE; + if ( to->segCnt == tempSegs_da.cnt ) { + for ( sp0=to->segs,sp1=&tempSegs(0); (!segsDiff) && sp0<&to->segs[to->segCnt]; sp0++,sp1++ ) { + switch (sp0->type) { + case SEG_STRLIN: + if (sp0->type != sp1->type || + sp0->color != sp1->color || + NotClose(sp0->width-width) || + NotClose(sp0->u.l.pos[0].x-sp1->u.l.pos[0].x) || + NotClose(sp0->u.l.pos[0].y-sp1->u.l.pos[0].y) || + NotClose(sp0->u.l.pos[1].x-sp1->u.l.pos[1].x) || + NotClose(sp0->u.l.pos[1].y-sp1->u.l.pos[1].y) ) + segsDiff = TRUE; + break; + case SEG_CRVLIN: + if (sp0->type != sp1->type || + sp0->color != sp1->color || + NotClose(sp0->width-width) || + NotClose(sp0->u.c.center.x-sp1->u.c.center.x) || + NotClose(sp0->u.c.center.y-sp1->u.c.center.y) || + NotClose(sp0->u.c.radius-sp1->u.c.radius) || + NotClose(sp0->u.c.a0-sp1->u.c.a0) || + NotClose(sp0->u.c.a1-sp1->u.c.a1) ) + segsDiff = TRUE; + break; + case SEG_STRTRK: + case SEG_CRVTRK: + break; + default: + segsDiff = TRUE; + } + } + } else { + for ( sp0=to->segs; (!segsDiff) && sp0<&to->segs[to->segCnt]; sp0++ ) { + if ( sp0->type != SEG_STRTRK && sp0->type != SEG_CRVTRK ) + segsDiff = TRUE; + } + } + } + if ( (!segsDiff) && to1 && (dp->type==NTO_REGULAR||dp->type==NTO_CURVED) ) { + if ( dp->type==NTO_REGULAR ) { + points[2].y = - points[2].y; + points[4].y = - points[4].y; + radii[0] = - radii[0]; + } else { + points[1].y = - points[1].y; + points[2].y = - points[2].y; + points[4].y = - points[4].y; + points[6].y = - points[6].y; + radii[0] = - radii[0]; + radii[1] = - radii[1]; + } + LoadSegs( dp, FALSE, &pathLen ); + if ( dp->type==NTO_REGULAR ) { + points[2].y = - points[2].y; + points[4].y = - points[4].y; + radii[0] = - radii[0]; + } else { + points[1].y = - points[1].y; + points[2].y = - points[2].y; + points[4].y = - points[4].y; + points[6].y = - points[6].y; + radii[0] = - radii[0]; + radii[1] = - radii[1]; + } + segsDiff = FALSE; + if ( to1->segCnt == tempSegs_da.cnt ) { + for ( sp0=to1->segs,sp1=&tempSegs(0); (!segsDiff) && sp0<&to1->segs[to1->segCnt]; sp0++,sp1++ ) { + switch (sp0->type) { + case SEG_STRLIN: + if (sp0->type != sp1->type || + sp0->color != sp1->color || + NotClose(sp0->width-width) || + NotClose(sp0->u.l.pos[0].x-sp1->u.l.pos[0].x) || + NotClose(sp0->u.l.pos[0].y-sp1->u.l.pos[0].y) || + NotClose(sp0->u.l.pos[1].x-sp1->u.l.pos[1].x) || + NotClose(sp0->u.l.pos[1].y-sp1->u.l.pos[1].y) ) + segsDiff = TRUE; + break; + case SEG_CRVLIN: + if (sp0->type != sp1->type || + sp0->color != sp1->color || + NotClose(sp0->width-width) || + NotClose(sp0->u.c.center.x-sp1->u.c.center.x) || + NotClose(sp0->u.c.center.y-sp1->u.c.center.y) || + NotClose(sp0->u.c.radius-sp1->u.c.radius) || + NotClose(sp0->u.c.a0-sp1->u.c.a0) || + NotClose(sp0->u.c.a1-sp1->u.c.a1) ) + segsDiff = TRUE; + break; + case SEG_STRTRK: + case SEG_CRVTRK: + break; + default: + segsDiff = TRUE; + } + } + } else { + for ( sp0=to1->segs; (!segsDiff) && sp0<&to1->segs[to1->segCnt]; sp0++ ) { + if ( sp0->type != SEG_STRTRK && sp0->type != SEG_CRVTRK ) + segsDiff = TRUE; + } + } + } + + includeNontrackSegments = TRUE; + if ( segsDiff ) { + if ( NoticeMessage( MSG_SEGMENTS_DIFFER, _("Yes"), _("No") ) <= 0 ) { + includeNontrackSegments = FALSE; + } + } else { + includeNontrackSegments = FALSE; + } + /*if (recordF) + fprintf( recordF, TURNOUTDESIGNER " SHOW %s\n", dp->label );*/ + ParamLoadControls( &turnDesignPG ); + ParamGroupRecord( &turnDesignPG ); + wShow( newTurnW ); +} + + +EXPORT void InitNewTurn( wMenu_p m ) +{ + int i; + ParamRegister( &turnDesignPG ); + for ( i=0; i<(sizeof designDescs/sizeof designDescs[0]); i++ ) { + wMenuPushCreate( m, NULL, _(designDescs[i]->label), 0, + ShowTurnoutDesigner, (void*)designDescs[i] ); + sprintf( message, "%s SHOW %s", TURNOUTDESIGNER, designDescs[i]->label ); + AddPlaybackProc( message, (playbackProc_p)ShowTurnoutDesigner, designDescs[i] ); + } + roadbedColor = wDrawColorBlack; + includeNontrackSegments = TRUE; +} +#endif + +#ifdef MKTURNOUT + + +#include +#include +#include + +char message[1024]; +char * curScaleName; +double trackGauge; +long units = 0; +wDrawColor drawColorBlack; +long roadbedColorRGB = 0; + +EXPORT void AbortProg( + char * msg, + ... ) +{ + static BOOL_T abort2 = FALSE; +// int rc; + va_list ap; + va_start( ap, msg ); + vsprintf( message, msg, ap ); + va_end( ap ); + fprintf( stderr, "%s", message ); + abort(); +} + +void * MyRealloc( void * ptr, long size ) +{ + return realloc( ptr, size ); +} + +EXPORT char * MyStrdup( const char * str ) +{ + char * ret; + ret = (char*)malloc( strlen( str ) + 1 ); + strcpy( ret, str ); + return ret; +} + + +int NoticeMessage( char * msg, char * yes, char * no, ... ) +{ + /*fprintf( stderr, "%s\n", msg );*/ + return 0; +} + +FILE * OpenCustom( char * mode) +{ + return stdout; +} + +void wPrintSetup( wPrintSetupCallBack_p notused ) +{ +} + +EXPORT void ComputeCurvedSeg( + trkSeg_p s, + DIST_T radius, + coOrd p0, + coOrd p1 ) +{ + DIST_T d; + ANGLE_T a, aa, aaa; + s->u.c.radius = radius; + d = FindDistance( p0, p1 )/2.0; + a = FindAngle( p0, p1 ); + if (radius > 0) { + aa = R2D(asin( d/radius )); + aaa = a + (90.0 - aa); + Translate( &s->u.c.center, p0, aaa, radius ); + s->u.c.a0 = NormalizeAngle( aaa + 180.0 ); + s->u.c.a1 = aa*2.0; + } else { + aa = R2D(asin( d/(-radius) )); + aaa = a - (90.0 - aa); + Translate( &s->u.c.center, p0, aaa, -radius ); + s->u.c.a0 = NormalizeAngle( aaa + 180.0 - aa *2.0 ); + s->u.c.a1 = aa*2.0; + } +} + +EXPORT char * Strcpytrimed( char * dst, char * src, BOOL_T double_quotes ) +{ + char * cp; + while (*src && isspace(*src) ) src++; + if (!*src) + return dst; + cp = src+strlen(src)-1; + while ( cp>src && isspace(*cp) ) cp--; + while ( src<=cp ) { + if (*src == '"' && double_quotes) + *dst++ = '"'; + *dst++ = *src++; + } + *dst = '\0'; + return dst; +} + + +EXPORT char * BuildTrimedTitle( char * cp, char * sep, char * mfg, char * desc, char * partno ) +{ + cp = Strcpytrimed( cp, mfg, FALSE ); + strcpy( cp, sep ); + cp += strlen(cp); + cp = Strcpytrimed( cp, desc, FALSE ); + strcpy( cp, sep ); + cp += strlen(cp); + cp = Strcpytrimed( cp, partno, FALSE ); + return cp; +} + + +EXPORT char * PutTitle( char * cp ) +{ + static char title[STR_SIZE]; + char * tp = title; + while (*cp) { + if (*cp == '\"') { + *tp++ = '\"'; + *tp++ = '\"'; + } else { + *tp++ = *cp; + } + cp++; + } + *tp = '\0'; + return title; +} + + +long wDrawGetRGB( + wDrawColor color ) +{ + return roadbedColorRGB; +} + +EXPORT BOOL_T WriteSegs( + FILE * f, + wIndex_t segCnt, + trkSeg_p segs ) +{ + int i, j; + BOOL_T rc = TRUE; + for ( i=0; i0; + break; + case SEG_CRVTRK: + case SEG_CRVLIN: + rc &= fprintf( f, "\t%c %ld %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f\n", + segs[i].type, (segs[i].type==SEG_CRVTRK?0:roadbedColorRGB), segs[i].width, + segs[i].u.c.radius, + segs[i].u.c.center.x, segs[i].u.c.center.y, + segs[i].u.c.a0, segs[i].u.c.a1 )>0; + break; + case SEG_FILCRCL: + rc &= fprintf( f, "\t%c %ld %0.6f %0.6f %0.6f %0.6f\n", + segs[i].type, roadbedColorRGB, segs[i].width, + segs[i].u.c.radius, + segs[i].u.c.center.x, segs[i].u.c.center.y )>0; + break; + case SEG_POLY: + case SEG_FILPOLY: + rc &= fprintf( f, "\t%c %ld %0.6f %d\n", + segs[i].type, roadbedColorRGB, segs[i].width, + segs[i].u.p.cnt )>0; + for ( j=0; j0; + break; + } + } + rc &= fprintf( f, "\tEND\n" )>0; + return rc; +} + +BOOL_T WriteCompoundPathsEndPtsSegs( + FILE * f, + PATHPTR_T paths, + wIndex_t segCnt, + trkSeg_p segs, + EPINX_T endPtCnt, + trkEndPt_t * endPts ) +{ + int i; + PATHPTR_T pp; + BOOL_T rc = TRUE; + for ( pp=paths; *pp; pp+=2 ) { + rc &= fprintf( f, "\tP \"%s\"", (char*)pp )>0; + for ( pp+=strlen((char*)pp)+1; pp[0]!=0||pp[1]!=0; pp++ ) + rc &= fprintf( f, " %d", *pp )>0; + rc &= fprintf( f, "\n" )>0; + } + for ( i=0; i0; +#ifdef MKTURNOUT + if ( specialLine[0] ) + rc &= fprintf( f, "%s\n", specialLine ); +#endif + rc &= WriteSegs( f, segCnt, segs ); + return rc; +} + + +void Usage( int argc, char **argv ) +{ + int inx; + for (inx=1;inx B # Create bumper\n" +" S # Create straight track\n" +" J # Create adjustable track\n" +" C # Create curved track\n" +" R # Create Regular Turnout\n" +" Q # Create Radial Turnout\n" +" V # Create Curved Turnout\n" +" W # Create Radial Curved Turnout\n" +" Y # Create Wye Turnout\n" +" 3 # Create 3-Way Turnout\n" +" X # Create Crossing\n" +" 1 # Create Single Slipswitch\n" +" 2 # Create Double Slipswitch\n" +" D # Create Double Crossover\n" +" T # Create TurnTable\n" +); + exit(1); +} + +struct { + char * scale; + double trackGauge; + } scaleMap[] = { + { "N", 0.3531 }, + { "HO", 0.6486 }, + { "O", 1.1770 }, + { "HOm", 0.472440 }, + { "G", 1.770 } + }; + + + +int main ( int argc, char * argv[] ) +{ +// char * cmd; + double radius, radius2; + int inx, cnt; + double ang, x0, y0, x1, y1; + char **argv0; + int argc0; + + argc0 = argc; + argv0 = argv; + doCustomInfoLine = FALSE; + argv++; + + if (argc < 7) { + Usage(argc0,argv0); + } + + while ( argv[0][0] == '-' ) { + switch (argv[0][1]) { + case 'm': + units = UNITS_METRIC; + break; + case 'u': + doCustomInfoLine = TRUE; + break; + case 'r': + doRoadBed = TRUE; + if (argv[0][2] == '\0') + Usage(argc0,argv0); + newTurnRoadbedWidth = atof(&argv[0][2]); + roadbedColorRGB = 0; + roadbedColor = 0; + newTurnRoadbedLineWidth = 0; + break; + case 'c': + roadbedColorRGB = atol(&argv[0][2]); + break; + case 'l': + newTurnRoadbedLineWidth = atol(&argv[0][2]); + break; + default: + fprintf( stderr, "Unknown option: %s\n", argv[0] ); + } + argv++; + argc--; + } + + newTurnScaleName = curScaleName = *argv++; + trackGauge = 0.0; + for ( inx=0; inx