diff options
Diffstat (limited to 'app/bin/cturnout.c')
-rw-r--r-- | app/bin/cturnout.c | 168 |
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 ); } |