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 );  	} | 
