diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2016-12-28 16:52:56 +0100 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2016-12-28 16:52:56 +0100 |
commit | 7b358424ebad9349421acd533c2fa1cbf6cf3e3e (patch) | |
tree | 686678532eefed525c242fd214d0cfb2914726c5 /app/bin/cturntbl.c |
Initial import of xtrkcad version 1:4.0.2-2
Diffstat (limited to 'app/bin/cturntbl.c')
-rw-r--r-- | app/bin/cturntbl.c | 838 |
1 files changed, 838 insertions, 0 deletions
diff --git a/app/bin/cturntbl.c b/app/bin/cturntbl.c new file mode 100644 index 0000000..31f33ed --- /dev/null +++ b/app/bin/cturntbl.c @@ -0,0 +1,838 @@ +/* + * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/bin/cturntbl.c,v 1.4 2008-03-06 19:35:06 m_fischer Exp $ + * + * TURNTABLE + * + */ + +/* 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. + */ + +#include "track.h" +#include "cstraigh.h" +#include "i18n.h" + +static TRKTYP_T T_TURNTABLE = -1; + + +struct extraData { + coOrd pos; + DIST_T radius; + EPINX_T currEp; + BOOL_T reverse; + }; + +static DIST_T turntableDiameter = 1.0; + +EXPORT ANGLE_T turntableAngle = 0.0; + +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 BOOL_T ValidateTurntablePosition( + track_p trk ) +{ + struct extraData * xx = GetTrkExtraData(trk); + EPINX_T ep, epCnt = GetTrkEndPtCnt(trk); + + if ( epCnt <= 0 ) + return FALSE; + ep = xx->currEp; + do { + if ( GetTrkEndTrk(trk,ep) ) { + xx->currEp = ep; + return TRUE; + } + ep++; + if ( ep >= epCnt ) + ep = 0; + } while ( ep != xx->currEp ); + return FALSE; +} + + +static void ComputeTurntableBoundingBox( track_p trk ) +{ + struct extraData *xx = GetTrkExtraData(trk); + coOrd hi, lo; + hi.x = xx->pos.x+xx->radius; + lo.x = xx->pos.x-xx->radius; + hi.y = xx->pos.y+xx->radius; + lo.y = xx->pos.y-xx->radius; + SetBoundingBox( trk, hi, lo ); +} + +static track_p NewTurntable( coOrd p, DIST_T r ) +{ + track_p t; + struct extraData *xx; + t = NewTrack( 0, T_TURNTABLE, 0, sizeof *xx ); + xx = GetTrkExtraData(t); + xx->pos = p; + xx->radius = r; + xx->currEp = 0; + xx->reverse = 0; + ComputeTurntableBoundingBox( t ); + return t; +} + +#ifdef LATER +-static void PruneTurntable( track_p trk ) +-{ +- EPINX_T inx0; +- EPINX_T inx1; +- for (inx0=inx1=0; inx0<trk->endCnt; inx0++) { +- if (GetTrkEndTrk(trk,inx0) == NULL) { +- continue; +- } else { +- if (inx0 != inx1) { +- trk->endPt[inx1] = GetTrkEndTrk(trk,inx0); +- } +- inx1++; +- } +- } +- trk->endPt = Realloc( trk->endPt, inx1*sizeof trk->endPt[0] ); +- trk->endCnt = inx1; +-} +#endif + +static ANGLE_T ConstrainTurntableAngle( track_p trk, coOrd pos ) +{ + struct extraData *xx = GetTrkExtraData(trk); + ANGLE_T a, al, ah, aa, aaa; + EPINX_T inx, cnt; + + a = FindAngle( xx->pos, pos ); + cnt = GetTrkEndPtCnt(trk); + if ( cnt == 0 || turntableAngle == 0.0 ) + return a; + ah = 360.0; + al = 360.0; + for ( inx = 0; inx<cnt; inx++ ) { + if (GetTrkEndTrk(trk,inx) == NULL) + continue; + aa = NormalizeAngle( GetTrkEndAngle(trk,inx) - a ); + if (aa < al) + al = aa; + aa = 360 - aa; + if (aa < ah) + ah = aa; + } + if (al+ah>361) + return a; + if ( (al+ah) < turntableAngle*2.0 ) { + ErrorMessage( MSG_NO_ROOM_BTW_TRKS ); + aaa = -1; + } else if ( al <= turntableAngle) + aaa = NormalizeAngle( a - ( turntableAngle - al ) ); + else if ( ah <= turntableAngle) + aaa = NormalizeAngle( a + ( turntableAngle - ah ) ); + else + aaa = a; +#ifdef VERBOSE + Lprintf( "CTA( %0.3f ) [ %0.3f .. %0.3f ] = %0.3f\n", a, ah, al, aaa ); +#endif + return aaa; +} + +static EPINX_T NewTurntableEndPt( track_p trk, ANGLE_T angle ) +{ + struct extraData *xx = GetTrkExtraData(trk); + EPINX_T ep = GetTrkEndPtCnt(trk); + coOrd pos; + SetTrkEndPtCnt( trk, ep+1 ); + PointOnCircle( &pos, xx->pos, xx->radius, angle ); + SetTrkEndPoint( trk, ep, pos, angle ); + return ep; +} + +static void TurntableGetCenter( track_p trk, coOrd * center, DIST_T * radius) +{ + struct extraData *xx = GetTrkExtraData(trk); + *center = xx->pos; + *radius = xx->radius; +} + +static void DrawTurntable( track_p t, drawCmd_p d, wDrawColor color ) +{ + struct extraData *xx = GetTrkExtraData(t); + coOrd p0, p1; + EPINX_T ep; + long widthOptions = DTS_TIES; + + if ( !ValidateTurntablePosition(t) ) { + p0.y = p1.y = xx->pos.y; + p0.x = xx->pos.x-xx->radius; + p1.x = xx->pos.x+xx->radius; + } else { + p0 = GetTrkEndPos( t, xx->currEp ); + Translate( &p1, xx->pos, GetTrkEndAngle(t,xx->currEp)+180.0, xx->radius ); + } + if (color == wDrawColorBlack) + color = normalColor; + DrawArc( d, xx->pos, xx->radius, 0.0, 360.0, 0, 0, color ); + if ( programMode != MODE_DESIGN ) + return; + if ( (d->options&DC_QUICK) == 0 ) { + DrawStraightTrack( d, p0, p1, FindAngle(p0,p1), t, GetTrkGauge(t), color, widthOptions ); + for ( ep=0; ep<GetTrkEndPtCnt(t); ep++ ) { + if (GetTrkEndTrk(t,ep) != NULL ) + DrawEndPt( d, t, ep, color ); + } + } + if ( ((d->funcs->options&wDrawOptTemp)==0) && + (labelWhen == 2 || (labelWhen == 1 && (d->options&DC_PRINT))) && + labelScale >= d->scale ) { + LabelLengths( d, t, color ); + } +} + +static DIST_T DistanceTurntable( track_p trk, coOrd * p ) +{ + struct extraData *xx = GetTrkExtraData(trk); + DIST_T d; + ANGLE_T a; + coOrd pos0, pos1; + + d = FindDistance( xx->pos, *p ) - xx->radius; + if (d < 0.0) + d = 0.0; + if ( programMode == MODE_DESIGN ) { + a = FindAngle( xx->pos, *p ); + Translate( p, xx->pos, a, d+xx->radius ); + } else { + if ( !ValidateTurntablePosition(trk) ) + return 100000.0; + pos0 = GetTrkEndPos(trk,xx->currEp); + Translate( &pos1, xx->pos, GetTrkEndAngle(trk,xx->currEp)+180.0, xx->radius ); + LineDistance( p, pos0, pos1 ); + } + return d; +} + +static struct { + coOrd orig; + DIST_T diameter; + long epCnt; + LAYER_T layerNumber; + } trntblData; +typedef enum { OR, RA, EC, LY } trntblDesc_e; +static descData_t trntblDesc[] = { +/*OR*/ { DESC_POS, N_("Origin: X"), &trntblData.orig }, +/*RA*/ { DESC_DIM, N_("Diameter"), &trntblData.diameter }, +/*EC*/ { DESC_LONG, N_("# EndPt"), &trntblData.epCnt }, +/*LY*/ { DESC_LAYER, N_("Layer"), &trntblData.layerNumber }, + { DESC_NULL } }; + + +static void UpdateTurntable( track_p trk, int inx, descData_p descUpd, BOOL_T final ) +{ + struct extraData *xx = GetTrkExtraData(trk); + + if ( inx == -1 ) + return; + UndrawNewTrack( trk ); + switch ( inx ) { + case OR: + xx->pos = trntblData.orig; + break; + case RA: + if ( trntblData.diameter > 2.0 ) + xx->radius = trntblData.diameter/2.0; + break; + case LY: + SetTrkLayer( trk, trntblData.layerNumber ); + break; + default: + break; + } + ComputeTurntableBoundingBox( trk ); + DrawNewTrack( trk ); +} + + +static void DescribeTurntable( track_p trk, char * str, CSIZE_T len ) +{ + struct extraData *xx = GetTrkExtraData(trk); + 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), + FormatDistance(xx->radius * 2.0), GetTrkEndPtCnt(trk) ); + + trntblData.orig = xx->pos; + trntblData.diameter = xx->radius*2.0; + trntblData.epCnt = GetTrkEndPtCnt(trk); + trntblData.layerNumber = GetTrkLayer(trk); + + trntblDesc[OR].mode = + trntblDesc[RA].mode = + trntblData.epCnt>0?DESC_RO:0; + trntblDesc[EC].mode = DESC_RO; + trntblDesc[LY].mode = DESC_NOREDRAW; + DoDescribe( _("Turntable"), trk, trntblDesc, UpdateTurntable ); +} + +static void DeleteTurntable( track_p t ) +{ +} + +static BOOL_T WriteTurntable( track_p t, FILE * f ) +{ + struct extraData *xx = GetTrkExtraData(t); + EPINX_T ep; + BOOL_T rc = TRUE; + 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 ); + rc &= fprintf(f, "\tEND\n")>0; + return rc; +} + +static void ReadTurntable( char * line ) +{ + track_p trk; + struct extraData *xx; + TRKINX_T index; + BOOL_T visible; + DIST_T r; + coOrd p; + DIST_T elev; + char scale[10]; + wIndex_t layer; + int currEp; + + if ( !GetArgs( line+10, + paramVersion<3?"dXsdpYfX": + paramVersion<9?"dL000sdpYfX": + paramVersion<10?"dL000sdpffX": + "dL000sdpffd", + &index, &layer, scale, &visible, &p, &elev, &r, &currEp )) + return; + trk = NewTrack( index, T_TURNTABLE, 0, sizeof *xx ); + ReadSegs(); + SetEndPts( trk, 0 ); + xx = GetTrkExtraData(trk); + SetTrkVisible(trk, visible); + SetTrkScale(trk, LookupScale( scale ) ); + SetTrkLayer(trk, layer); + xx->pos = p; + xx->radius = r; + xx->currEp = currEp; + xx->reverse = 0; + ComputeTurntableBoundingBox( trk ); +} + +static void MoveTurntable( track_p trk, coOrd orig ) +{ + struct extraData *xx = GetTrkExtraData(trk); + xx->pos.x += orig.x; + xx->pos.y += orig.y; + ComputeTurntableBoundingBox( trk ); +} + +static void RotateTurntable( track_p trk, coOrd orig, ANGLE_T angle ) +{ + struct extraData *xx = GetTrkExtraData(trk); + Rotate( &xx->pos, orig, angle ); + ComputeTurntableBoundingBox( trk ); +} + +static void RescaleTurntable( track_p trk, FLOAT_T ratio ) +{ + struct extraData *xx = GetTrkExtraData(trk); + 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); + if ( programMode == MODE_DESIGN ) { + return FindAngle( xx->pos, pos ); + } else { + if ( !ValidateTurntablePosition( trk ) ) + return 90.0; + else + return GetTrkEndAngle( trk, xx->currEp ); + } +} + + +static BOOL_T SplitTurntable( track_p trk, coOrd pos, EPINX_T ep, track_p *leftover, EPINX_T *ep0, EPINX_T *ep1 ) +{ + if (leftover) + *leftover = NULL; + ErrorMessage( MSG_CANT_SPLIT_TRK, "Turntable" ); + return FALSE; +} + + +static BOOL_T FindTurntableEndPt( + track_p trk, + ANGLE_T *angleR, + EPINX_T *epR, + BOOL_T *reverseR ) +{ + EPINX_T ep, ep0, epCnt=GetTrkEndPtCnt(trk); + ANGLE_T angle=*angleR, angle0, angle1; + for (ep=0,ep0=-1,epCnt=GetTrkEndPtCnt(trk),angle0=370.0; ep<epCnt; ep++) { + if ( (GetTrkEndTrk(trk,ep)) == NULL ) + continue; + angle1 = GetTrkEndAngle(trk,ep); + angle1 = NormalizeAngle(angle1-angle); + if ( angle1 > 180.0 ) + angle1 = 360.0-angle1; + if ( angle1 < angle0 ) { + *epR = ep; + *reverseR = FALSE; + angle0 = angle1; + } +#ifdef LATER + if ( angle1 > 90.0 ) { + angle1 = 180.0-angle1; + if ( angle1 < angle0 ) { + *epR = ep; + *reverseR = TRUE; + angle0 = angle1; + } + } +#endif + } + if ( angle0 < 360.0 ) { + *angleR = angle0; + return TRUE; + } else { + return FALSE; + } +} + + + +static BOOL_T CheckTraverseTurntable( + track_p trk, + coOrd pos ) +{ + struct extraData * xx = GetTrkExtraData(trk); + ANGLE_T angle; + + if ( !ValidateTurntablePosition( trk ) ) + return FALSE; + angle = FindAngle( xx->pos, pos ) - GetTrkEndAngle( trk, xx->currEp )+connectAngle/2.0; + if ( angle <= connectAngle || + ( angle >= 180.0 && angle <= 180+connectAngle ) ) + return TRUE; + return FALSE; +} + + +static BOOL_T TraverseTurntable( + traverseTrack_p trvTrk, + DIST_T * distR ) +{ + track_p trk = trvTrk->trk; + struct extraData * xx = GetTrkExtraData(trk); + coOrd pos0; + DIST_T dist, dist1; + ANGLE_T angle, angle1; + EPINX_T ep; + BOOL_T reverse; + + if ( !ValidateTurntablePosition( trk ) ) + return FALSE; + dist = FindDistance( xx->pos, trvTrk->pos ); + pos0 = GetTrkEndPos( trk, xx->currEp ); + angle = FindAngle( pos0, xx->pos ); + if ( NormalizeAngle( angle-trvTrk->angle+90 ) < 180 ) { + angle1 = angle; + } else { + angle1 = NormalizeAngle( angle+180.0 ); + } + if ( dist > xx->radius*0.9 ) { + angle = NormalizeAngle( angle-trvTrk->angle ); + if ( ( angle < 90.0 && angle > connectAngle ) || + ( angle > 270.0 && angle < 360.0-connectAngle ) ) + return FALSE; + } + trvTrk->angle = angle1; + angle = FindAngle( trvTrk->pos, xx->pos ); + if ( NormalizeAngle( angle-angle1+90.0 ) < 180 ) { + if ( dist > *distR ) { + Translate( &trvTrk->pos, xx->pos, angle1+180.0, dist-*distR ); + *distR = 0; + return TRUE; + } else { + *distR -= dist; + dist = 0.0; + } + } + dist1 = xx->radius-dist; + if ( dist1 > *distR ) { + Translate( &trvTrk->pos, xx->pos, angle1, dist+*distR ); + *distR = 0.0; + return TRUE; + } + Translate( &trvTrk->pos, xx->pos, angle1, xx->radius ); + *distR -= dist1; + if ( FindTurntableEndPt( trk, &angle1, &ep, &reverse ) && angle1 < connectAngle ) { + trk = GetTrkEndTrk(trk,ep); + } else { + trk = NULL; + } + trvTrk->trk = trk; + return TRUE; +} + + +static BOOL_T EnumerateTurntable( track_p trk ) +{ + struct extraData *xx; + static dynArr_t turntables_da; +#define turntables(N) DYNARR_N( FLOAT_T, turntables_da, N ) + int inx; + char tmp[40]; + if ( trk != NULL ) { + xx = GetTrkExtraData(trk); + 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; + } else { + for (inx=0; inx<turntables_da.cnt; inx++) { + sprintf( tmp, "Turntable, diameter %s", FormatDistance(turntables(inx)) ); + EnumerateList( 1, 0.0, tmp ); + } + DYNARR_RESET( FLOAT_T, turntables_da ); + } + return TRUE; +} + + +static STATUS_T ModifyTurntable( track_p trk, wAction_t action, coOrd pos ) +{ + static coOrd ttCenter; + static DIST_T ttRadius; + static ANGLE_T angle; + static BOOL_T valid; + + DIST_T r; + EPINX_T ep; + track_p trk1; + + switch ( action ) { + case C_DOWN: + TurntableGetCenter( trk, &ttCenter, &ttRadius ); + tempSegs(0).type = SEG_STRTRK; + tempSegs(0).width = 0; + InfoMessage( _("Drag to create stall track") ); + + case C_MOVE: + valid = FALSE; + if ( (angle = ConstrainTurntableAngle( trk, pos )) < 0.0) { + ; + } else if ((r=FindDistance( ttCenter, pos )) < ttRadius) { + ErrorMessage( MSG_POINT_INSIDE_TURNTABLE ); + } else if ( (r-ttRadius) <= minLength ) { + if (action == C_MOVE) + ErrorMessage( MSG_TRK_TOO_SHORT, "Stall ", PutDim(fabs(minLength-(r-ttRadius))) ); + } else { + Translate( &tempSegs(0).u.l.pos[0], ttCenter, angle, ttRadius ); + Translate( &tempSegs(0).u.l.pos[1], ttCenter, angle, r ); + if (action == C_MOVE) + InfoMessage( _("Straight Track: Length=%s Angle=%0.3f"), + FormatDistance( r-ttRadius ), PutAngle( angle ) ); + tempSegs_da.cnt = 1; + valid = TRUE; + } + return C_CONTINUE; + + case C_UP: + if (!valid) + return C_TERMINATE; + ep = NewTurntableEndPt( trk, angle ); + trk1 = NewStraightTrack( tempSegs(0).u.l.pos[0], tempSegs(0).u.l.pos[1] ); + CopyAttributes( trk, trk1 ); + ConnectTracks( trk, ep, trk1, 0 ); + DrawNewTrack( trk1 ); + return C_TERMINATE; + + default: + ; + } + return C_ERROR; +} + + +static BOOL_T GetParamsTurntable( int inx, track_p trk, coOrd pos, trackParams_t * params ) +{ + coOrd center; + DIST_T radius; + + if (inx == PARAMS_1ST_JOIN) { + ErrorMessage( MSG_JOIN_TURNTABLE ); + return FALSE; + } + params->type = curveTypeStraight; + params->ep = -1; + params->angle = ConstrainTurntableAngle( trk, pos ); + if (params->angle < 0.0) + return FALSE; + TurntableGetCenter( trk, ¢er, &radius ); + PointOnCircle( ¶ms->lineOrig, center, radius, params->angle ); + params->lineEnd = params->lineOrig; + params->len = 0.0; + params->arcR = 0.0; + return TRUE; +} + + +static BOOL_T MoveEndPtTurntable( track_p *trk, EPINX_T *ep, coOrd pos, DIST_T d0 ) +{ + coOrd posCen; + DIST_T r; + ANGLE_T angle0; + DIST_T d; + track_p trk1; + + TurntableGetCenter( *trk, &posCen, &r ); + angle0 = FindAngle( posCen, pos ); + d = FindDistance( posCen, pos ); + if (d0 > 0.0) { + d -= d0; + Translate( &pos, pos, angle0+180, d0 ); + } + if (d < r) { + ErrorMessage( MSG_POINT_INSIDE_TURNTABLE ); + return FALSE; + } + *ep = NewTurntableEndPt( *trk, angle0 ); + if ((d-r) > connectDistance) { + trk1 = NewStraightTrack( GetTrkEndPos(*trk,*ep), pos ); + CopyAttributes( *trk, trk1 ); + ConnectTracks( *trk, *ep, trk1, 0 ); + *trk = trk1; + *ep = 1; + DrawNewTrack( *trk ); + } + return TRUE; +} + + +static BOOL_T QueryTurntable( track_p trk, int query ) +{ + switch ( query ) { + case Q_REFRESH_JOIN_PARAMS_ON_MOVE: + case Q_CANNOT_PLACE_TURNOUT: + case Q_DONT_DRAW_ENDPOINT: + case Q_CAN_NEXT_POSITION: + case Q_ISTRACK: + case Q_NOT_PLACE_FROGPOINTS: + case Q_MODIFY_REDRAW_DONT_UNDRAW_TRACK: + return TRUE; + default: + return FALSE; + } +} + + +static void FlipTurntable( + track_p trk, + coOrd orig, + ANGLE_T angle ) +{ + struct extraData * xx = GetTrkExtraData(trk); + FlipPoint( &xx->pos, orig, angle ); + ComputeBoundingBox( trk ); +} + + +static void DrawTurntablePositionIndicator( track_p trk, wDrawColor color ) +{ + struct extraData * xx = GetTrkExtraData(trk); + coOrd pos0, pos1; + ANGLE_T angle; + + if ( !ValidateTurntablePosition(trk) ) + return; + pos0 = GetTrkEndPos(trk,xx->currEp); + angle = FindAngle( xx->pos, pos0 ); + PointOnCircle( &pos1, xx->pos, xx->radius, angle+180.0 ); + DrawLine( &mainD, pos0, pos1, 3, color ); +} + +static void AdvanceTurntablePositionIndicator( + track_p trk, + coOrd pos, + coOrd * posR, + ANGLE_T * angleR ) +{ + struct extraData * xx = GetTrkExtraData(trk); + EPINX_T ep; + ANGLE_T angle0, angle1; + BOOL_T reverse; + + angle1 = FindAngle( xx->pos, pos ); + if ( !FindTurntableEndPt( trk, &angle1, &ep, &reverse ) ) + return; + DrawTurntablePositionIndicator( trk, wDrawColorWhite ); + angle0 = GetTrkEndAngle(trk,xx->currEp); + if ( ep == xx->currEp ) { + Rotate( posR, xx->pos, 180.0 ); + if ( xx->reverse ) { + angle1 = angle0; + xx->reverse = FALSE; + } else { + angle1 = NormalizeAngle( angle0+180.0 ); + xx->reverse = TRUE; + } + } else { + angle1 = GetTrkEndAngle(trk,ep); + Rotate( posR, xx->pos, angle1-angle0 ); + xx->reverse = FALSE; + } + *angleR = angle1; + xx->currEp = ep; + DrawTurntablePositionIndicator( trk, selectedColor ); +} + + +static trackCmd_t turntableCmds = { + "TURNTABLE", + DrawTurntable, + DistanceTurntable, + DescribeTurntable, + DeleteTurntable, + WriteTurntable, + ReadTurntable, + MoveTurntable, + RotateTurntable, + RescaleTurntable, + NULL, /* audit */ + GetAngleTurntable, + SplitTurntable, /* split */ + TraverseTurntable, + EnumerateTurntable, + NULL, /* redraw */ + NULL, /* trim */ + NULL, /* merge */ + ModifyTurntable, + NULL, /* getLength */ + GetParamsTurntable, + MoveEndPtTurntable, + QueryTurntable, + NULL, /* ungroup */ + FlipTurntable, + DrawTurntablePositionIndicator, + AdvanceTurntablePositionIndicator, + CheckTraverseTurntable }; + + +static STATUS_T CmdTurntable( wAction_t action, coOrd pos ) +{ + track_p t; + static coOrd pos0; + wControl_p controls[2]; + char * labels[1]; + + switch (action) { + + case C_START: + if (turntableDiameterPD.control==NULL) + ParamCreateControls( &turntablePG, NULL ); + sprintf( message, "turntable-diameter-%s", curScaleName ); + turntableDiameter = ceil(80.0*12.0/curScaleRatio); + wPrefGetFloat( "misc", message, &turntableDiameter, turntableDiameter ); + ParamLoadControls( &turntablePG ); + ParamGroupRecord( &turntablePG ); + controls[0] = turntableDiameterPD.control; + controls[1] = NULL; + labels[0] = N_("Diameter"); + InfoSubstituteControls( controls, labels ); + /*InfoMessage( "Place Turntable");*/ + return C_CONTINUE; + + case C_DOWN: + SnapPos( &pos ); + if ( turntableDiameter <= 0.0 ) { + ErrorMessage( MSG_TURNTABLE_DIAM_GTR_0 ); + return C_ERROR; + } + controls[0] = turntableDiameterPD.control; + controls[1] = NULL; + labels[0] = N_("Diameter"); + InfoSubstituteControls( controls, labels ); + ParamLoadData( &turntablePG ); + pos0 = pos; + DrawArc( &tempD, pos0, turntableDiameter/2.0, 0.0, 360.0, 0, 0, wDrawColorBlack ); + return C_CONTINUE; + + case C_MOVE: + DrawArc( &tempD, pos0, turntableDiameter/2.0, 0.0, 360.0, 0, 0, wDrawColorBlack ); + SnapPos( &pos ); + pos0 = pos; + DrawArc( &tempD, pos0, turntableDiameter/2.0, 0.0, 360.0, 0, 0, wDrawColorBlack ); + return C_CONTINUE; + + case C_UP: + DrawArc( &tempD, pos0, turntableDiameter/2.0, 0.0, 360.0, 0, 0, wDrawColorBlack ); + SnapPos( &pos ); + UndoStart( _("Create Turntable"), "NewTurntable" ); + t = NewTurntable( pos, turntableDiameter/2.0 ); + UndoEnd(); + DrawNewTrack(t); + InfoSubstituteControls( NULL, NULL ); + sprintf( message, "turntable-diameter-%s", curScaleName ); + wPrefSetFloat( "misc", message, turntableDiameter ); + return C_TERMINATE; + + case C_REDRAW: + DrawArc( &tempD, pos0, turntableDiameter/2.0, 0.0, 360.0, 0, 0, wDrawColorBlack ); + return C_CONTINUE; + + case C_CANCEL: + InfoSubstituteControls( NULL, NULL ); + return C_CONTINUE; + + default: + return C_CONTINUE; + } +} + + +#include "bitmaps/turntbl.xpm" + + +EXPORT void InitCmdTurntable( wMenu_p menu ) +{ + AddMenuButton( menu, CmdTurntable, "cmdTurntable", _("Turntable"), wIconCreatePixMap(turntbl_xpm), LEVEL0_50, IC_STICKY, ACCL_TURNTABLE, NULL ); +} + + +EXPORT void InitTrkTurntable( void ) +{ + T_TURNTABLE = InitObject( &turntableCmds ); + + ParamRegister( &turntablePG ); +} |