summaryrefslogtreecommitdiff
path: root/app/bin/cturntbl.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/bin/cturntbl.c')
-rw-r--r--app/bin/cturntbl.c226
1 files changed, 158 insertions, 68 deletions
diff --git a/app/bin/cturntbl.c b/app/bin/cturntbl.c
index f15aeff..2ef49d1 100644
--- a/app/bin/cturntbl.c
+++ b/app/bin/cturntbl.c
@@ -20,27 +20,24 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include <math.h>
-#include <string.h>
-
#include "cstraigh.h"
#include "cundo.h"
#include "fileio.h"
-#include "i18n.h"
-#include "messages.h"
#include "param.h"
#include "track.h"
-#include "utility.h"
+#include "cselect.h"
+#include "common-ui.h"
static TRKTYP_T T_TURNTABLE = -1;
-struct extraData {
+typedef struct extraDataTurntable_t {
+ extraDataBase_t base;
coOrd pos;
DIST_T radius;
EPINX_T currEp;
BOOL_T reverse;
- };
+ } extraDataTurntable_t;
static DIST_T turntableDiameter = 1.0;
@@ -50,17 +47,17 @@ static paramFloatRange_t r1_100 = { 1.0, 100.0, 100 };
static paramData_t turntablePLs[] = {
#define turntableDiameterPD (turntablePLs[0])
{ PD_FLOAT, &turntableDiameter, "diameter", PDO_DIM|PDO_NOPREF, &r1_100, N_("Diameter") } };
-static paramGroup_t turntablePG = { "turntable", 0, turntablePLs, sizeof turntablePLs/sizeof turntablePLs[0] };
+static paramGroup_t turntablePG = { "turntable", 0, turntablePLs, COUNT( turntablePLs ) };
static BOOL_T ValidateTurntablePosition(
track_p trk )
{
- struct extraData * xx = GetTrkExtraData(trk);
EPINX_T ep, epCnt = GetTrkEndPtCnt(trk);
if ( epCnt <= 0 )
return FALSE;
+ struct extraDataTurntable_t * xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
ep = xx->currEp;
do {
if ( GetTrkEndTrk(trk,ep) ) {
@@ -77,8 +74,8 @@ static BOOL_T ValidateTurntablePosition(
static void ComputeTurntableBoundingBox( track_p trk )
{
- struct extraData *xx = GetTrkExtraData(trk);
coOrd hi, lo;
+ struct extraDataTurntable_t *xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
hi.x = xx->pos.x+xx->radius;
lo.x = xx->pos.x-xx->radius;
hi.y = xx->pos.y+xx->radius;
@@ -89,9 +86,9 @@ static void ComputeTurntableBoundingBox( track_p trk )
static track_p NewTurntable( coOrd p, DIST_T r )
{
track_p t;
- struct extraData *xx;
+ struct extraDataTurntable_t *xx;
t = NewTrack( 0, T_TURNTABLE, 0, sizeof *xx );
- xx = GetTrkExtraData(t);
+ xx = GET_EXTRA_DATA(t, T_TURNTABLE, extraDataTurntable_t);
xx->pos = p;
xx->radius = r;
xx->currEp = 0;
@@ -122,7 +119,7 @@ static track_p NewTurntable( coOrd p, DIST_T r )
static ANGLE_T ConstrainTurntableAngle( track_p trk, coOrd pos )
{
- struct extraData *xx = GetTrkExtraData(trk);
+ struct extraDataTurntable_t *xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
ANGLE_T a, al, ah, aa, aaa;
EPINX_T inx, cnt;
@@ -161,7 +158,7 @@ static ANGLE_T ConstrainTurntableAngle( track_p trk, coOrd pos )
static EPINX_T NewTurntableEndPt( track_p trk, ANGLE_T angle )
{
- struct extraData *xx = GetTrkExtraData(trk);
+ struct extraDataTurntable_t *xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
EPINX_T ep = -1;
/* Reuse an old empty ep if it exists */
for (int i =0;i< GetTrkEndPtCnt(trk)-1;i++) {
@@ -182,14 +179,14 @@ static EPINX_T NewTurntableEndPt( track_p trk, ANGLE_T angle )
static void TurntableGetCenter( track_p trk, coOrd * center, DIST_T * radius)
{
- struct extraData *xx = GetTrkExtraData(trk);
+ struct extraDataTurntable_t *xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
*center = xx->pos;
*radius = xx->radius;
}
static void DrawTurntable( track_p t, drawCmd_p d, wDrawColor color )
{
- struct extraData *xx = GetTrkExtraData(t);
+ struct extraDataTurntable_t *xx = GET_EXTRA_DATA(t, T_TURNTABLE, extraDataTurntable_t);
coOrd p0, p1;
EPINX_T ep;
long widthOptions = DTS_LEFT|DTS_RIGHT;
@@ -220,7 +217,7 @@ static void DrawTurntable( track_p t, drawCmd_p d, wDrawColor color )
static DIST_T DistanceTurntable( track_p trk, coOrd * p )
{
- struct extraData *xx = GetTrkExtraData(trk);
+ struct extraDataTurntable_t *xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
DIST_T d;
ANGLE_T a;
coOrd pos0, pos1;
@@ -231,7 +228,7 @@ static DIST_T DistanceTurntable( track_p trk, coOrd * p )
Translate( p, xx->pos, a, d+xx->radius );
} else {
if ( !ValidateTurntablePosition(trk) )
- return 100000.0;
+ return DIST_INF;
pos0 = GetTrkEndPos(trk,xx->currEp);
Translate( &pos1, xx->pos, GetTrkEndAngle(trk,xx->currEp)+180.0, xx->radius );
LineDistance( p, pos0, pos1 );
@@ -256,7 +253,7 @@ static descData_t trntblDesc[] = {
static void UpdateTurntable( track_p trk, int inx, descData_p descUpd, BOOL_T final )
{
- struct extraData *xx = GetTrkExtraData(trk);
+ struct extraDataTurntable_t *xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
if ( inx == -1 )
return;
@@ -282,7 +279,7 @@ static void UpdateTurntable( track_p trk, int inx, descData_p descUpd, BOOL_T fi
static void DescribeTurntable( track_p trk, char * str, CSIZE_T len )
{
- struct extraData *xx = GetTrkExtraData(trk);
+ struct extraDataTurntable_t *xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
sprintf( str, _("Turntable(%d): Layer=%d Center=[%s %s] Diameter=%s #EP=%d"),
GetTrkIndex(trk), GetTrkLayer(trk)+1,
FormatDistance(xx->pos.x), FormatDistance(xx->pos.y),
@@ -290,7 +287,11 @@ static void DescribeTurntable( track_p trk, char * str, CSIZE_T len )
trntblData.orig = xx->pos;
trntblData.diameter = xx->radius*2.0;
- trntblData.epCnt = GetTrkEndPtCnt(trk);
+ int j=0;
+ for (int i=0;i<GetTrkEndPtCnt(trk);i++) {
+ if (GetTrkEndTrk(trk,i)) j++; //Only count if track
+ }
+ trntblData.epCnt = j;
trntblData.layerNumber = GetTrkLayer(trk);
trntblDesc[OR].mode =
@@ -307,14 +308,20 @@ static void DeleteTurntable( track_p t )
static BOOL_T WriteTurntable( track_p t, FILE * f )
{
- struct extraData *xx = GetTrkExtraData(t);
+ struct extraDataTurntable_t *xx = GET_EXTRA_DATA(t, T_TURNTABLE, extraDataTurntable_t);
EPINX_T ep;
BOOL_T rc = TRUE;
+ int j = -1, k = 0;
+ for (ep=0; ep<GetTrkEndPtCnt(t); ep++) {
+ if (GetTrkEndTrk(t,ep)) j++;
+ if (ep == xx->currEp) k=j; //Write out the curr->Ep reset to real endPts
+ }
rc &= fprintf(f, "TURNTABLE %d %d 0 0 0 %s %d %0.6f %0.6f 0 %0.6f %d\n",
GetTrkIndex(t), GetTrkLayer(t), GetTrkScaleName(t), GetTrkVisible(t),
- xx->pos.x, xx->pos.y, xx->radius, xx->currEp )>0;
- for (ep=0; ep<GetTrkEndPtCnt(t); ep++)
- rc &= WriteEndPt( f, t, ep );
+ xx->pos.x, xx->pos.y, xx->radius, k )>0;
+ for (ep=0; ep<GetTrkEndPtCnt(t); ep++) {
+ if (GetTrkEndTrk(t,ep)) rc &= WriteEndPt( f, t, ep ); //Only write if there is a track
+ }
rc &= fprintf(f, "\t%s\n", END_SEGS)>0;
return rc;
}
@@ -322,7 +329,7 @@ static BOOL_T WriteTurntable( track_p t, FILE * f )
static BOOL_T ReadTurntable( char * line )
{
track_p trk;
- struct extraData *xx;
+ struct extraDataTurntable_t *xx;
TRKINX_T index;
BOOL_T visible;
DIST_T r;
@@ -343,7 +350,7 @@ static BOOL_T ReadTurntable( char * line )
return FALSE;
trk = NewTrack( index, T_TURNTABLE, 0, sizeof *xx );
SetEndPts( trk, 0 );
- xx = GetTrkExtraData(trk);
+ xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
if ( paramVersion < 3 ) {
SetTrkVisible(trk, visible!=0);
} else {
@@ -354,6 +361,7 @@ static BOOL_T ReadTurntable( char * line )
xx->pos = p;
xx->radius = r;
xx->currEp = currEp;
+ if (xx->currEp > GetTrkEndPtCnt(trk)) xx->currEp = 0;
xx->reverse = 0;
ComputeTurntableBoundingBox( trk );
return TRUE;
@@ -361,7 +369,7 @@ static BOOL_T ReadTurntable( char * line )
static void MoveTurntable( track_p trk, coOrd orig )
{
- struct extraData *xx = GetTrkExtraData(trk);
+ struct extraDataTurntable_t *xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
xx->pos.x += orig.x;
xx->pos.y += orig.y;
ComputeTurntableBoundingBox( trk );
@@ -369,21 +377,21 @@ static void MoveTurntable( track_p trk, coOrd orig )
static void RotateTurntable( track_p trk, coOrd orig, ANGLE_T angle )
{
- struct extraData *xx = GetTrkExtraData(trk);
+ struct extraDataTurntable_t *xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
Rotate( &xx->pos, orig, angle );
ComputeTurntableBoundingBox( trk );
}
static void RescaleTurntable( track_p trk, FLOAT_T ratio )
{
- struct extraData *xx = GetTrkExtraData(trk);
+ struct extraDataTurntable_t *xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
xx->pos.x *= ratio;
xx->pos.y *= ratio;
}
static ANGLE_T GetAngleTurntable( track_p trk, coOrd pos, EPINX_T * ep0, EPINX_T * ep1 )
{
- struct extraData *xx = GetTrkExtraData(trk);
+ struct extraDataTurntable_t *xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
if ( programMode == MODE_DESIGN ) {
return FindAngle( xx->pos, pos );
} else {
@@ -444,12 +452,46 @@ static BOOL_T FindTurntableEndPt(
}
+static EPINX_T FindTurntableNextEndPt(
+ track_p trk,
+ coOrd pos) {
+
+ EPINX_T ep,epfound=-1,epCnt;
+ struct extraDataTurntable_t * xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
+ ANGLE_T a = FindAngle(xx->pos,pos);
+ ANGLE_T foundangle = 370.0;
+ ANGLE_T diff = DifferenceBetweenAngles(GetTrkEndAngle(trk,xx->currEp),a);
+ BOOL_T forward = TRUE;
+ if (diff>90) {
+ forward = FALSE;
+ }
+ if (diff<0 && diff>-90) {
+ forward = FALSE;
+ }
+ ANGLE_T currdiff, angle1;
+ for (ep=0,epCnt=GetTrkEndPtCnt(trk); ep<epCnt; ep++) {
+ if ( (GetTrkEndTrk(trk,ep)) == NULL )
+ continue;
+ angle1 = GetTrkEndAngle(trk,ep);
+ if (forward)
+ currdiff = NormalizeAngle(angle1-a);
+ else
+ currdiff = NormalizeAngle(a-angle1);
+ if (currdiff<foundangle) {
+ foundangle = currdiff;
+ epfound = ep;
+ }
+ }
+ return epfound;
+}
+
+
static BOOL_T CheckTraverseTurntable(
track_p trk,
coOrd pos )
{
- struct extraData * xx = GetTrkExtraData(trk);
+ struct extraDataTurntable_t * xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
ANGLE_T angle;
if ( !ValidateTurntablePosition( trk ) )
@@ -467,7 +509,7 @@ static BOOL_T TraverseTurntable(
DIST_T * distR )
{
track_p trk = trvTrk->trk;
- struct extraData * xx = GetTrkExtraData(trk);
+ struct extraDataTurntable_t * xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
coOrd pos0;
DIST_T dist, dist1;
ANGLE_T angle, angle1;
@@ -522,27 +564,30 @@ static BOOL_T TraverseTurntable(
static BOOL_T EnumerateTurntable( track_p trk )
{
- struct extraData *xx;
+ struct extraDataTurntable_t *xx;
static dynArr_t turntables_da;
#define turntables(N) DYNARR_N( FLOAT_T, turntables_da, N )
- int inx;
+ size_t inx;
char tmp[40];
+ BOOL_T content = FALSE;
if ( trk != NULL ) {
- xx = GetTrkExtraData(trk);
+ content = TRUE;
+ xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
DYNARR_APPEND( FLOAT_T, turntables_da, 10 );
turntables(turntables_da.cnt-1) = xx->radius*2.0;
sprintf( tmp, "Turntable, diameter %s", FormatDistance(turntables(turntables_da.cnt-1)) );
inx = strlen( tmp );
- if ( inx > (int)enumerateMaxDescLen )
- enumerateMaxDescLen = inx;
+ if ( inx > enumerateMaxDescLen )
+ enumerateMaxDescLen = (int)inx;
} else {
for (inx=0; inx<turntables_da.cnt; inx++) {
+ content = TRUE;
sprintf( tmp, "Turntable, diameter %s", FormatDistance(turntables(inx)) );
- EnumerateList( 1, 0.0, tmp );
+ EnumerateList( 1, 0.0, tmp, NULL );
}
DYNARR_RESET( FLOAT_T, turntables_da );
}
- return TRUE;
+ return content;
}
@@ -620,7 +665,7 @@ EXPORT BOOL_T ConnectTurntableTracks(
UndoModify(trk1);
EPINX_T ep = NewTurntableEndPt(trk1,angle);
if (ConnectTracks( trk1, ep, trk2, ep2 )) {
- UndoUndo();
+ UndoUndo(NULL);
return FALSE;
}
return TRUE;
@@ -687,7 +732,7 @@ static BOOL_T MoveEndPtTurntable( track_p *trk, EPINX_T *ep, coOrd pos, DIST_T d
if (!found)
*ep = NewTurntableEndPt(*trk,angle0);
else {
- struct extraData *xx = GetTrkExtraData(*trk);
+ struct extraDataTurntable_t *xx = GET_EXTRA_DATA(*trk, T_TURNTABLE, extraDataTurntable_t);
coOrd pos1;
PointOnCircle( &pos1, xx->pos, xx->radius, angle0 );
SetTrkEndPoint(*trk, *ep, pos1, angle0); //Reuse
@@ -730,15 +775,16 @@ static void FlipTurntable(
coOrd orig,
ANGLE_T angle )
{
- struct extraData * xx = GetTrkExtraData(trk);
+ struct extraDataTurntable_t * xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
FlipPoint( &xx->pos, orig, angle );
ComputeBoundingBox( trk );
}
+BOOL_T debug = 0;
static void DrawTurntablePositionIndicator( track_p trk, wDrawColor color )
{
- struct extraData * xx = GetTrkExtraData(trk);
+ struct extraDataTurntable_t * xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
coOrd pos0, pos1;
ANGLE_T angle;
@@ -748,12 +794,22 @@ static void DrawTurntablePositionIndicator( track_p trk, wDrawColor color )
angle = FindAngle( xx->pos, pos0 );
PointOnCircle( &pos1, xx->pos, xx->radius, angle+180.0 );
DrawLine( &tempD, pos0, pos1, 3, color );
+ if (debug) {
+ if (xx->reverse) {
+
+ Rotate(&pos1,xx->pos, 15);
+ DrawFillCircle( &tempD, pos1, 0.5, color);
+ } else {
+ Rotate(&pos0,xx->pos, 10);
+ DrawFillCircle( &tempD, pos0, 0.5, color);
+ }
+ }
}
static wBool_t CompareTurntable( track_cp trk1, track_cp trk2 )
{
- struct extraData *xx1 = GetTrkExtraData( trk1 );
- struct extraData *xx2 = GetTrkExtraData( trk2 );
+ struct extraDataTurntable_t *xx1 = GET_EXTRA_DATA( trk1, T_TURNTABLE, extraDataTurntable_t );
+ struct extraDataTurntable_t *xx2 = GET_EXTRA_DATA( trk2, T_TURNTABLE, extraDataTurntable_t );
char * cp = message + strlen(message);
REGRESS_CHECK_POS( "Pos", xx1, xx2, pos )
REGRESS_CHECK_DIST( "Radius", xx1, xx2, radius )
@@ -768,31 +824,64 @@ static void AdvanceTurntablePositionIndicator(
coOrd * posR,
ANGLE_T * angleR )
{
- struct extraData * xx = GetTrkExtraData(trk);
+
+ struct extraDataTurntable_t * xx = GET_EXTRA_DATA(trk, T_TURNTABLE, extraDataTurntable_t);
EPINX_T ep;
ANGLE_T angle0, angle1;
- BOOL_T reverse;
-
- angle1 = FindAngle( xx->pos, pos );
- if ( !FindTurntableEndPt( trk, &angle1, &ep, &reverse ) )
- return;
+ BOOL_T reverse=FALSE, train_reversed = FALSE;
+ EPINX_T epCnt=GetTrkEndPtCnt(trk);
+ EPINX_T epbest = -1, epfound = -1;
+ coOrd inpos = *posR;
+ ANGLE_T inangle = *angleR;
angle0 = GetTrkEndAngle(trk,xx->currEp);
- if ( ep == xx->currEp ) {
- Rotate( posR, xx->pos, 180.0 );
- if ( xx->reverse ) {
- angle1 = angle0;
- xx->reverse = FALSE;
+ if (fabs(DifferenceBetweenAngles(angle0,*angleR))>90) train_reversed = TRUE;
+ DIST_T dd = DIST_INF;
+ // If on ep, use that
+ for (ep=0; ep<epCnt; ep++) {
+ if ( (GetTrkEndTrk(trk,ep)) == NULL )
+ continue;
+ coOrd end = GetTrkEndPos(trk,ep);
+ DIST_T d = FindDistance(end,pos);
+ if (d<dd) {
+ dd = d;
+ epbest = ep;
+ }
+ }
+ if (epbest>=0 && IsClose(dd)) {
+ epfound = epbest;
+ }
+ // Else find next track in given direction beyond current
+ if (epfound<0) {
+ epfound = FindTurntableNextEndPt( trk, pos );
+ }
+ if (epfound>=0) {
+ if (xx->currEp == epfound ) {
+ reverse = TRUE;
+ xx->reverse = !xx->reverse;
+ train_reversed = !train_reversed;
} else {
- angle1 = NormalizeAngle( angle0+180.0 );
- xx->reverse = TRUE;
+ //If back end moving, flip result
+ if (fabs(DifferenceBetweenAngles(FindAngle(xx->pos,pos),GetTrkEndAngle(trk,xx->currEp)))>90) {
+ if (epfound>=0 && epfound != xx->currEp) {
+ reverse = TRUE;
+ xx->reverse = !xx->reverse;
+ train_reversed = !train_reversed;
+ }
+ }
}
- } else {
- angle1 = GetTrkEndAngle(trk,ep);
- Rotate( posR, xx->pos, angle1-angle0 );
- xx->reverse = FALSE;
+ xx->currEp = epfound;
+ angle1 = GetTrkEndAngle(trk,xx->currEp);
+ if (!reverse) {
+ *angleR = NormalizeAngle(angle1+(train_reversed?180:0));
+ Translate( posR, xx->pos, *angleR, FindDistance(*posR,xx->pos) );
+ } else {
+ *angleR = NormalizeAngle(angle1+(train_reversed?180:0));
+ Translate(posR, xx->pos, *angleR, FindDistance(*posR,xx->pos) );
+ }
+ coOrd outpos = *posR;
+ if (debug)
+ InfoMessage("AO:%0.3f PO:(%0.3f,%0.3f) AI:%0.3f PI:(%0.3f,%0.3f)",*angleR,outpos.x,outpos.y,inangle,inpos.x,inpos.y);
}
- *angleR = angle1;
- xx->currEp = ep;
}
@@ -856,6 +945,7 @@ static STATUS_T CmdTurntable( wAction_t action, coOrd pos )
controls[1] = NULL;
labels[0] = N_("Diameter");
InfoSubstituteControls( controls, labels );
+ SetAllTrackSelect( FALSE );
/*InfoMessage( "Place Turntable");*/
state = 0;
return C_CONTINUE;
@@ -908,12 +998,12 @@ static STATUS_T CmdTurntable( wAction_t action, coOrd pos )
}
-#include "bitmaps/turntbl.xpm"
+#include "bitmaps/turntable.xpm"
EXPORT void InitCmdTurntable( wMenu_p menu )
{
- AddMenuButton( menu, CmdTurntable, "cmdTurntable", _("Custom Turntable"), wIconCreatePixMap(turntbl_xpm), LEVEL0_50, IC_STICKY|IC_INITNOTSTICKY, ACCL_TURNTABLE, NULL );
+ AddMenuButton( menu, CmdTurntable, "cmdTurntable", _("Custom Turntable"), wIconCreatePixMap(turntable_xpm[iconSize]), LEVEL0_50, IC_STICKY|IC_INITNOTSTICKY, ACCL_TURNTABLE, NULL );
}