summaryrefslogtreecommitdiff
path: root/app/bin/cturnout.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/bin/cturnout.c')
-rw-r--r--app/bin/cturnout.c168
1 files changed, 101 insertions, 67 deletions
diff --git a/app/bin/cturnout.c b/app/bin/cturnout.c
index 55b7a4d..c3125ad 100644
--- a/app/bin/cturnout.c
+++ b/app/bin/cturnout.c
@@ -1,8 +1,5 @@
-/*
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/bin/cturnout.c,v 1.8 2009-08-16 13:07:14 m_fischer Exp $
- *
+/** \file cturnout.c
* T_TURNOUT
- *
*/
/* XTrkCad - Model Railroad CAD
@@ -24,14 +21,24 @@
*/
#include <ctype.h>
-#include "track.h"
+#include <math.h>
+#include <stdint.h>
+#include <string.h>
+
#include "ccurve.h"
-#include "cstraigh.h"
-#include "compound.h"
+#include "tbezier.h"
#include "cjoin.h"
+#include "compound.h"
+#include "cstraigh.h"
+#include "cundo.h"
+#include "custom.h"
+#include "fileio.h"
#include "i18n.h"
-
-#include <stdint.h>
+#include "layout.h"
+#include "messages.h"
+#include "param.h"
+#include "track.h"
+#include "utility.h"
EXPORT TRKTYP_T T_TURNOUT = -1;
@@ -120,6 +127,8 @@ EXPORT turnoutInfo_t * CreateNewTurnout(
}
to->segCnt = segCnt;
to->segs = (trkSeg_p)memdup( segData, (sizeof *segData) * 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 );
@@ -154,7 +163,7 @@ EXPORT wIndex_t CheckPaths(
PATHPTR_T paths )
{
int pc, ps;
- PATHPTR_T pp;
+ PATHPTR_T pp = 0;
int inx, inx1;
static dynArr_t segMap_da;
int segInx[2], segEp[2];
@@ -663,7 +672,7 @@ static ANGLE_T GetAngleTurnout(
pos.x -= xx->orig.x;
pos.y -= xx->orig.y;
Rotate( &pos, zero, -xx->angle );
- angle = GetAngleSegs( segCnt, xx->segs, pos, &segInx );
+ angle = GetAngleSegs( segCnt, xx->segs, &pos, &segInx, NULL, NULL, NULL, NULL );
return NormalizeAngle( angle+xx->angle );
}
@@ -1202,7 +1211,6 @@ static BOOL_T TraverseTurnout(
coOrd pos0, pos1, pos2;
DIST_T d, dist;
PATHPTR_T path, pathCurr;
- BOOL_T backwards=FALSE;
trkSeg_p segPtr;
EPINX_T ep, epCnt, ep2;
int segInx;
@@ -1222,10 +1230,6 @@ LOG( log_traverseTurnout, 1, ( "TraverseTurnout( T%d, [%0.3f %0.3f] [%0.3f %0.3f
continue;
GetSegInxEP( path[0], &segInx, &segEP );
segPtr = xx->segs+segInx;
-#ifdef LATER
- for ( inx = 0; inx<xx->segCnt; inx++ ) {
- segPtr = xx->segs+inx;
-#endif
segProcData.distance.pos1 = pos0;
SegProc( SEGPROC_DISTANCE, segPtr, &segProcData );
if ( segProcData.distance.dd < d ) {
@@ -1241,46 +1245,63 @@ LOG( log_traverseTurnout, 1, ( "TraverseTurnout( T%d, [%0.3f %0.3f] [%0.3f %0.3f
LOG( log_traverseTurnout, 1, ( " PC=%d ", pathCurr[0] ) )
GetSegInxEP( pathCurr[0], &segInx, &segEP );
segPtr = xx->segs+segInx;
-#ifdef LATER
- for ( pathCurr = xx->pathCurr+strlen((char*)xx->pathCurr)+1; pathCurr[0] || pathCurr[1]; pathCurr++ ) {
- if ( pathCurr[0] == 0 )
- continue;
- if ( Abs(pathCurr[0])-1 == currInx )
- break;
- }
- if ( pathCurr[0] == 0 ) {
- fprintf( stderr, "Open turnout [%d]\n", currInx );
- return FALSE;
- }
- segPtr = xx->segs+currInx;
-#endif
segProcData.traverse1.pos = pos2;
- segProcData.traverse1.angle = xx->angle-trvTrk->angle;
+ segProcData.traverse1.angle = -xx->angle+trvTrk->angle;
SegProc( SEGPROC_TRAVERSE1, segPtr, &segProcData );
dist += segProcData.traverse1.dist;
- backwards = segProcData.traverse1.backwards;
- if ( segEP ) backwards = !backwards;
-LOG( log_traverseTurnout, 2, ( " B%d D%0.3f\n", backwards, dist ) )
-
+ //Get ready for Traverse2 - copy all Traverse1 first
+ BOOL_T backwards = segProcData.traverse1.backwards;
+ BOOL_T segs_backwards = segProcData.traverse1.segs_backwards;
+ BOOL_T neg = segProcData.traverse1.negative;
+ int BezSegInx = segProcData.traverse1.BezSegInx;
+
+ // Backwards means universally we going towards EP=0 on this segment.
+ // But the overall direction we are going can have two types of reversal,
+ // a curve that is flipped is negative (the end points are reversed) which Traverse1 handles,
+ // and a path can also be reversed (negative path number) and will have segEP = 1
+ 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?1-segEP:segEP);
+ 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;
- pathCurr += (backwards?-1:1);
-LOG( log_traverseTurnout, 1, ( " D%0.3f\n", dist ) )
- }
-
- pathCurr += (backwards?1:-1);
- pos1 = MapPathPos( xx, pathCurr[0], (backwards?0:1) );
+ 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) );
*distR = dist;
epCnt = GetTrkEndPtCnt(trk);
ep = 0;
@@ -1354,10 +1375,25 @@ 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 )
{
- params->type = curveTypeStraight;
- params->ep = PickUnconnectedEndPoint( pos, trk );
+
+
+ params->type = curveTypeStraight; //TODO should check if last segment is actually straight
+ if (inx == PARAMS_CORNU || inx == PARAMS_BEZIER) {
+ 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;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ params->ep = PickUnconnectedEndPointSilent( pos, trk );
if (params->ep == -1)
- return FALSE;
+ return FALSE;
params->lineOrig = GetTrkEndPos(trk,params->ep);
params->lineEnd = params->lineOrig;
params->len = 0.0;
@@ -1405,7 +1441,15 @@ static BOOL_T QueryTurnout( track_p trk, int query )
case Q_NOT_PLACE_FROGPOINTS:
case Q_HAS_DESC:
case Q_MODIFY_REDRAW_DONT_UNDRAW_TRACK:
+ case Q_CAN_EXTEND:
return TRUE;
+ case Q_MODIFY_CAN_SPLIT:
+ if (GetTrkEndPtCnt(trk) <= 2) { // allow splitting of simple track und buffers
+ return TRUE ;
+ }
+ else {
+ return FALSE;
+ }
case Q_CAN_PARALLEL:
if( GetTrkEndPtCnt( trk ) == 2 && fabs( GetTrkEndAngle( trk, 0 ) - GetTrkEndAngle( trk, 1 )) == 180.0 )
return TRUE;
@@ -1413,6 +1457,8 @@ static BOOL_T QueryTurnout( track_p trk, int query )
return FALSE;
case Q_CAN_NEXT_POSITION:
return ( GetTrkEndPtCnt(trk) > 2 );
+ case Q_CORNU_CAN_MODIFY:
+ return FALSE;
default:
return FALSE;
}
@@ -1663,7 +1709,7 @@ static void TurnoutChange( long changes )
maxTurnoutDim.x = maxTurnoutDim.y = 0.0;
if (turnoutInfo_da.cnt <= 0)
return;
- curTurnout = TurnoutAdd( LABEL_TABBED|LABEL_MANUF|LABEL_PARTNO|LABEL_DESCR, curScaleInx, turnoutListL, &maxTurnoutDim, -1 );
+ curTurnout = TurnoutAdd( LABEL_TABBED|LABEL_MANUF|LABEL_PARTNO|LABEL_DESCR, GetLayoutCurScale(), turnoutListL, &maxTurnoutDim, -1 );
wListSetIndex( turnoutListL, 0 );
wControlShow( (wControl_p)turnoutListL, TRUE );
if (curTurnout == NULL) {
@@ -1871,6 +1917,9 @@ LOG( log_turnout, 3, ( "placeTurnout T%d (%0.3f %0.3f) A%0.3f\n",
}
}
}
+ } else {
+ trk = NULL;
+ *trkR = NULL;
}
*connCntR = connCnt;
*maxDR = maxD;
@@ -1975,14 +2024,6 @@ static void AddTurnout( void )
curTurnout->segs, curTurnout->segCnt, trackGauge, wDrawColorBlack );
UndoStart( _("Place New Turnout"), "addTurnout" );
titleLen = strlen( curTurnout->title );
-#ifdef LATER
- newTrk = NewTrack( 0, T_TURNOUT, curTurnout->endCnt, sizeof (*xx) + 1 );
- xx = GetTrkExtraData(newTrk);
- xx->orig = Dto.pos;
- xx->angle = Dto.angle;
- xx->customInfo = curTurnout->customInfo;
- xx->segs = MyMalloc( (curTurnout->segCnt)*sizeof curTurnout->segs[0] );
-#endif
DYNARR_SET( trkEndPt_t, tempEndPts_da, curTurnout->endCnt );
DYNARR_SET( junk_t, connection_da, curTurnout->endCnt );
@@ -2078,23 +2119,13 @@ LOG( log_turnout, 1, ( " deleting leftover T%d\n",
xx->customInfo = curTurnout->customInfo;
if (connection((int)curTurnoutEp).trk) {
CopyAttributes( connection((int)curTurnoutEp).trk, newTrk );
- SetTrkScale( newTrk, curScaleInx );
+ SetTrkScale( newTrk, GetLayoutCurScale());
}
xx->special = curTurnout->special;
xx->u = curTurnout->u;
-#ifdef LATER
- xx->segCnt = curTurnout->segCnt;
- memcpy( xx->segs, curTurnout->segs, xx->segCnt * sizeof *(trkSeg_p)0 );
- xx->title = curTurnout->title;
- xx->paths = xx->pathCurr = curTurnout->paths;
- xx->pathLen = curTurnout->pathLen;
-#endif
/* Make the connections */
-#ifdef LATER
- for (i=0; i<curTurnout->endCnt; i++)
- SetTrkEndPoint( newTrk, i, tempEndPts(i).pos, tempEndPts(i).angle );
-#endif
+
visible = FALSE;
noConnections = TRUE;
AuditTracks( "addTurnout T%d before connection", GetTrkIndex(newTrk) );
@@ -2102,6 +2133,9 @@ LOG( log_turnout, 1, ( " deleting leftover T%d\n",
if ( connection(i).trk != NULL ) {
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 = NormalizeAngle(a1-a0+180);
d = FindDistance( p0, p1 );
if ( d < connectDistance ) {
noConnections = FALSE;
@@ -2481,7 +2515,7 @@ EXPORT void AddHotBarTurnouts( void )
to = turnoutInfo(inx);
if ( !( IsParamValid(to->paramFileIndex) &&
to->segCnt > 0 &&
- CompatibleScale( TRUE, to->scaleInx, curScaleInx ) ) )
+ CompatibleScale( TRUE, to->scaleInx, GetLayoutCurScale()) ) )
continue;
AddHotBarElement( to->contentsLabel, to->size, to->orig, TRUE, to->barScale, to, CmdTurnoutHotBarProc );
}