diff options
Diffstat (limited to 'app/bin/ccurve.c')
-rw-r--r-- | app/bin/ccurve.c | 637 |
1 files changed, 404 insertions, 233 deletions
diff --git a/app/bin/ccurve.c b/app/bin/ccurve.c index 58bb5c1..e119610 100644 --- a/app/bin/ccurve.c +++ b/app/bin/ccurve.c @@ -39,57 +39,102 @@ #include "utility.h" #include "wlib.h" #include "cbezier.h" +#include "ccornu.h" +#include "layout.h" /* * STATE INFO */ +typedef enum createState_e {NOCURVE,FIRSTEND_DEF,SECONDEND_DEF,CENTER_DEF} createState_e; + static struct { STATE_T state; + createState_e create_state; coOrd pos0; coOrd pos1; curveData_t curveData; track_p trk; EPINX_T ep; BOOL_T down; + BOOL_T lock0; + coOrd middle; + coOrd end0; + coOrd end1; } Da; static long curveMode; +static dynArr_t anchors_da; +#define anchors(N) DYNARR_N(trkSeg_t,anchors_da,N) +#define array_anchor(N) DYNARR_N(trkSeg_t,*anchor_array,N) + -EXPORT void DrawArrowHeads( +EXPORT int DrawArrowHeads( trkSeg_p sp, coOrd pos, ANGLE_T angle, BOOL_T bidirectional, wDrawColor color ) { - coOrd p0, p1; - DIST_T d, w; - int inx; - d = mainD.scale*0.25; - w = mainD.scale/mainD.dpi*2; - for ( inx=0; inx<5; inx++ ) { - sp[inx].type = SEG_STRLIN; - sp[inx].width = w; - sp[inx].color = color; - } - Translate( &p0, pos, angle, d ); - Translate( &p1, pos, angle+180, bidirectional?d:(d/2.0) ); - sp[0].u.l.pos[0] = p0; - sp[0].u.l.pos[1] = p1; - sp[1].u.l.pos[0] = p0; - Translate( &sp[1].u.l.pos[1], p0, angle+135, d/2.0 ); - sp[2].u.l.pos[0] = p0; - Translate( &sp[2].u.l.pos[1], p0, angle-135, d/2.0 ); - if (bidirectional) { - sp[3].u.l.pos[0] = p1; - Translate( &sp[3].u.l.pos[1], p1, angle-45, d/2.0 ); - sp[4].u.l.pos[0] = p1; - Translate( &sp[4].u.l.pos[1], p1, angle+45, d/2.0 ); - } + coOrd p0, p1; + DIST_T d, w; + int inx; + d = mainD.scale*0.25; + w = mainD.scale/mainD.dpi*2; + for ( inx=0; inx<5; inx++ ) { + sp[inx].type = SEG_STRLIN; + sp[inx].width = w; + sp[inx].color = color; + } + Translate( &p0, pos, angle, d ); + Translate( &p1, pos, angle+180, bidirectional?d:(d/2.0) ); + sp[0].u.l.pos[0] = p0; + sp[0].u.l.pos[1] = p1; + sp[1].u.l.pos[0] = p0; + Translate( &sp[1].u.l.pos[1], p0, angle+135, d/2.0 ); + sp[2].u.l.pos[0] = p0; + Translate( &sp[2].u.l.pos[1], p0, angle-135, d/2.0 ); + if (bidirectional) { + sp[3].u.l.pos[0] = p1; + Translate( &sp[3].u.l.pos[1], p1, angle-45, d/2.0 ); + sp[4].u.l.pos[0] = p1; + Translate( &sp[4].u.l.pos[1], p1, angle+45, d/2.0 ); + } else { + sp[3].u.l.pos[0] = p1; + sp[3].u.l.pos[1] = p1; + sp[4].u.l.pos[0] = p1; + sp[4].u.l.pos[1] = p1; + } + return 5; } +EXPORT int DrawArrowHeadsArray( + dynArr_t *anchor_array, + coOrd pos, + ANGLE_T angle, + BOOL_T bidirectional, + wDrawColor color ) +{ + int i = (*anchor_array).cnt; + DYNARR_SET(trkSeg_t,*anchor_array,i+5) + return DrawArrowHeads(&DYNARR_N(trkSeg_t,*anchor_array,i),pos,angle,bidirectional,color); + +} + +static void CreateEndAnchor(coOrd p, dynArr_t * anchor_array, wBool_t lock) { + DIST_T d = tempD.scale*0.15; + + DYNARR_APPEND(trkSeg_t,*anchor_array,1); + int i = (*anchor_array).cnt-1; + array_anchor(i).type = lock?SEG_FILCRCL:SEG_CRVLIN; + array_anchor(i).color = wDrawColorBlue; + array_anchor(i).u.c.center = p; + array_anchor(i).u.c.radius = d/2; + array_anchor(i).u.c.a0 = 0.0; + array_anchor(i).u.c.a1 = 360.0; + array_anchor(i).width = 0; +} @@ -100,6 +145,7 @@ EXPORT STATUS_T CreateCurve( wDrawColor color, DIST_T width, long mode, + dynArr_t * anchor_array, curveMessageProc message ) { track_p t; @@ -110,23 +156,28 @@ EXPORT STATUS_T CreateCurve( switch ( action ) { case C_START: - DYNARR_SET( trkSeg_t, tempSegs_da, 8 ); + DYNARR_RESET(trkSeg_t,*anchor_array); + DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); + Da.create_state = NOCURVE; + tempSegs_da.cnt = 0; Da.down = FALSE; //Not got a valid start yet + Da.pos0 = zero; + Da.pos1 = zero; switch ( curveMode ) { case crvCmdFromEP1: if (track) - message(_("Drag from End-Point in direction of curve - Shift locks to track open end-point") ); + message(_("Drag from endpoint in direction of curve - lock to track open endpoint") ); else - message (_("Drag from End-Point in direction of curve") ); + message (_("Drag from endpoint in direction of curve") ); break; case crvCmdFromTangent: if (track) - message(_("Drag from End-Point to Center - Shift locks to track open end-point") ); + message(_("Drag from endpoint to center - lock to track open endpoint") ); else - message(_("Drag from End-Point to Center") ); + message(_("Drag from endpoint to center") ); break; case crvCmdFromCenter: - message(_("Drag from Center to End-Point") ); + message(_("Drag from center to endpoint") ); break; case crvCmdFromChord: message(_("Drag from one to other end of chord") ); @@ -134,6 +185,7 @@ EXPORT STATUS_T CreateCurve( } return C_CONTINUE; case C_DOWN: + DYNARR_RESET(trkSeg_t, *anchor_array); for ( inx=0; inx<8; inx++ ) { tempSegs(inx).color = wDrawColorBlack; tempSegs(inx).width = 0; @@ -141,150 +193,212 @@ EXPORT STATUS_T CreateCurve( tempSegs_da.cnt = 0; p = pos; BOOL_T found = FALSE; - Da.trk = NULL; - if ((mode == crvCmdFromEP1 || mode == crvCmdFromTangent) && track && (MyGetKeyState() & WKEY_SHIFT) != 0) { - if ((t = OnTrack(&p, FALSE, TRUE)) != NULL) { - EPINX_T ep = PickUnconnectedEndPointSilent(p, t); - if (ep != -1) { - Da.trk = t; - Da.ep = ep; - pos = GetTrkEndPos(t, ep); - found = TRUE; - } else { - Da.pos0=pos; - message(_("No unconnected end-point on track - Try again or release Shift and click")); - return C_CONTINUE; - } - } else { - Da.pos0=pos; - message(_("Not on a track - Try again or release Shift and click")); - return C_CONTINUE; + Da.trk = NULL; + if (track) { + if ((mode == crvCmdFromEP1 || mode == crvCmdFromTangent || (mode == crvCmdFromChord)) && + ((MyGetKeyState() & WKEY_ALT) == 0 ) == magneticSnap) { + if ((t = OnTrack(&p, FALSE, TRUE)) != NULL) { + EPINX_T ep = PickUnconnectedEndPointSilent(p, t); + if (ep != -1) { + if (GetTrkScale(t) != (char)GetLayoutCurScale()) { + wBeep(); + InfoMessage(_("Track is different gauge")); + return C_CONTINUE; + } + Da.trk = t; + Da.ep = ep; + pos = GetTrkEndPos(t, ep); + found = TRUE; + } + } } - Da.down = TRUE; - } + } else { + if ((t = OnTrack(&p, FALSE, FALSE)) != NULL) { + if (!IsTrack(t)) { + pos = p; + found = TRUE; + } + } + } Da.down = TRUE; if (!found) SnapPos( &pos ); - pos0 = pos; - Da.pos0 = pos; + Da.lock0 = found; + + if (Da.create_state == NOCURVE) + Da.pos0 = pos; + else + Da.pos1 = pos; + + tempSegs_da.cnt = 1; switch (mode) { case crvCmdFromEP1: tempSegs(0).type = (track?SEG_STRTRK:SEG_STRLIN); tempSegs(0).color = color; tempSegs(0).width = width; - if (Da.trk) message(_("End Locked: Drag out curve start")); + Da.create_state = FIRSTEND_DEF; + Da.end0 = pos; + CreateEndAnchor(pos,anchor_array,found); + if (Da.trk && !(MyGetKeyState() & WKEY_SHIFT)) message(_("End locked: Drag out curve start")); + else if (Da.trk) message(_("End Position locked: Drag out curve start with Shift")); else message(_("Drag along curve start") ); break; case crvCmdFromTangent: + Da.create_state = FIRSTEND_DEF; + tempSegs(0).type = SEG_STRLIN; + tempSegs(0).color = color; + Da.create_state = CENTER_DEF; + CreateEndAnchor(pos,anchor_array,found); + if (Da.trk && !(MyGetKeyState() & WKEY_SHIFT)) message(_("End locked: Drag out curve center")); + else if (Da.trk) message(_("End Position locked: Drag out curve start with Shift")); + else message(_("Drag out curve center") ); + break; case crvCmdFromCenter: tempSegs(0).type = SEG_STRLIN; - tempSegs(1).type = SEG_CRVLIN; - tempSegs(1).u.c.radius = mainD.scale*0.05; - tempSegs(1).u.c.a0 = 0; - tempSegs(1).u.c.a1 = 360; - tempSegs(2).type = SEG_STRLIN; - if (Da.trk && mode==crvCmdFromTangent) message(_("End Locked: Drag out to center")); - else - message( mode==crvCmdFromTangent?_("Drag from End-Point to Center"):_("Drag from Center to End-Point") ); + tempSegs(0).color = color; + Da.create_state = CENTER_DEF; + CreateEndAnchor(pos,anchor_array,FALSE); + message(_("Drag out from center to endpoint")); break; case crvCmdFromChord: tempSegs(0).type = (track?SEG_STRTRK:SEG_STRLIN); tempSegs(0).color = color; tempSegs(0).width = width; - message( _("Drag to other end of chord") ); + CreateEndAnchor(pos,anchor_array,FALSE); + Da.create_state = FIRSTEND_DEF; + if (Da.trk && !(MyGetKeyState() & WKEY_SHIFT)) + message( _("End locked: Drag to other end of chord") ); + else if (Da.trk) message(_("End Position locked: Drag out curve start with Shift")); + else + message( _("Drag to other end of chord") ); break; } - tempSegs(0).u.l.pos[0] = pos; + tempSegs(0).u.l.pos[0] = tempSegs(0).u.l.pos[1] = pos; return C_CONTINUE; case C_MOVE: + DYNARR_RESET(trkSeg_t,*anchor_array); + DYNARR_APPEND(trkSeg_t,*anchor_array,1); if (!Da.down) return C_CONTINUE; - if (Da.trk) { + if (Da.trk && !(MyGetKeyState() & WKEY_SHIFT)) { //Shift inhibits direction lock angle1 = NormalizeAngle(GetTrkEndAngle(Da.trk, Da.ep)); - angle2 = NormalizeAngle(FindAngle(pos, pos0)-angle1); - if (mode ==crvCmdFromEP1) { + angle2 = NormalizeAngle(FindAngle(pos, Da.pos0)-angle1); + if (mode ==crvCmdFromEP1 ) { if (angle2 > 90.0 && angle2 < 270.0) - Translate( &pos, pos0, angle1, -FindDistance( pos0, pos )*cos(D2R(angle2)) ); - else pos = pos0; - } else { - DIST_T dp = -FindDistance(pos0, pos)*sin(D2R(angle2)); - if (angle2 > 180.0) - Translate( &pos, pos0, angle1+90.0, dp ); + Translate( &pos, Da.pos0, angle1, -FindDistance( Da.pos0, pos )*cos(D2R(angle2)) ); + else pos = Da.pos0; + } else if ( mode == crvCmdFromChord ) { + DIST_T dp = -FindDistance(Da.pos0, pos)*sin(D2R(angle2)); + if (DifferenceBetweenAngles(FindAngle(Da.pos0,pos),angle1)>0) + Translate( &pos, Da.pos0, angle1+90, dp ); + else + Translate( &pos, Da.pos0, angle1-90, -dp ); + } else if (mode == crvCmdFromCenter) { + DIST_T dp = -FindDistance(Da.pos0, pos)*sin(D2R(angle2)); + if (angle2 > 90 && angle2 < 270.0) + Translate( &pos, Da.pos0, angle1+90.0, dp ); else - Translate( &pos, pos0, angle1-90.0, dp ); + Translate( &pos, Da.pos0, angle1-90.0, dp ); + } else if (mode == crvCmdFromTangent) { + DIST_T dp = FindDistance(Da.pos0, pos)*sin(D2R(angle2)); + Translate( &pos, Da.pos0, angle1-90.0, dp ); } } else SnapPos(&pos); - tempSegs(0).u.l.pos[1] = pos; - d = FindDistance( pos0, pos ); - a = FindAngle( pos0, pos ); + tempSegs_da.cnt =1; + if (Da.trk && mode == crvCmdFromChord) { + tempSegs(0).type = SEG_CRVTRK; + tempSegs(0).u.c.center.x = (pos.x+Da.pos0.x)/2.0; + tempSegs(0).u.c.center.y = (pos.y+Da.pos0.y)/2.0; + tempSegs(0).u.c.radius = FindDistance(pos,Da.pos0)/2; + ANGLE_T a0 = FindAngle(tempSegs(0).u.c.center,Da.pos0); + ANGLE_T a1 = FindAngle(tempSegs(0).u.c.center,pos); + if (NormalizeAngle(a0+90-GetTrkEndAngle(Da.trk,Da.ep))<90) { + tempSegs(0).u.c.a0 = a0; + } else { + tempSegs(0).u.c.a0 = a1; + } + tempSegs(0).u.c.a1 = 180.0; + } else tempSegs(0).u.l.pos[1] = pos; + Da.pos1 = pos; + + d = FindDistance( Da.pos0, Da.pos1 ); + a = FindAngle( Da.pos0, Da.pos1 ); switch ( mode ) { case crvCmdFromEP1: if (Da.trk) message( _("Start Locked: Drag out curve start - Angle=%0.3f"), PutAngle(a)); else message( _("Drag out curve start - Angle=%0.3f"), PutAngle(a) ); + CreateEndAnchor(Da.pos0,anchor_array,Da.lock0); + DrawArrowHeadsArray( anchor_array, pos, FindAngle(Da.pos0,Da.pos1)+90, TRUE, wDrawColorBlue ); tempSegs_da.cnt = 1; break; case crvCmdFromTangent: - if (Da.trk) message( _("Tangent Locked: Drag out center - Radius=%s Angle=%0.3f"), FormatDistance(d), PutAngle(a) ); + if (Da.trk) message( _("Tangent locked: Drag out center - Radius=%s Angle=%0.3f"), FormatDistance(d), PutAngle(a) ); else message( _("Drag out center - Radius=%s Angle=%0.3f"), FormatDistance(d), PutAngle(a) ); - tempSegs(1).u.c.center = pos; - DrawArrowHeads( &tempSegs(2), pos0, FindAngle(pos0,pos)+90, TRUE, wDrawColorBlack ); - tempSegs_da.cnt = 7; + CreateEndAnchor(Da.pos1,anchor_array,TRUE); + DrawArrowHeadsArray( anchor_array, Da.pos0, FindAngle(Da.pos0,Da.pos1)+90, TRUE, wDrawColorBlue ); + tempSegs_da.cnt = 1; break; case crvCmdFromCenter: - message( _("Radius=%s Angle=%0.3f"), FormatDistance(d), PutAngle(a) ); - tempSegs(1).u.c.center = pos0; - DrawArrowHeads( &tempSegs(2), pos, FindAngle(pos,pos0)+90, TRUE, wDrawColorBlack ); - tempSegs_da.cnt = 7; + message( _("Drag to Edge: Radius=%s Angle=%0.3f"), FormatDistance(d), PutAngle(a) ); + CreateEndAnchor(Da.pos0,anchor_array,Da.lock0); + DrawArrowHeadsArray( anchor_array, Da.pos1, FindAngle(Da.pos1,Da.pos0)+90, TRUE, wDrawColorBlue ); + tempSegs_da.cnt = 1; break; case crvCmdFromChord: - message( _("Length=%s Angle=%0.3f"), FormatDistance(d), PutAngle(a) ); - if ( d > mainD.scale*0.25 ) { - pos.x = (pos.x+pos0.x)/2.0; - pos.y = (pos.y+pos0.y)/2.0; - DrawArrowHeads( &tempSegs(1), pos, FindAngle(pos,pos0)+90, TRUE, wDrawColorBlack ); - tempSegs_da.cnt = 6; - } else { - tempSegs_da.cnt = 1; + if (Da.trk) message( _("Start locked: Drag out chord length=%s angle=%0.3f"), FormatDistance(d), PutAngle(a) ); + else message( _("Drag out chord length=%s angle=%0.3f"), FormatDistance(d), PutAngle(a) ); + Da.middle.x = (Da.pos1.x+Da.pos0.x)/2.0; + Da.middle.y = (Da.pos1.y+Da.pos0.y)/2.0; + if (track && Da.trk) { + ANGLE_T ea = GetTrkEndAngle(Da.trk,Da.ep); + Translate(&Da.middle,Da.middle,ea,FindDistance(Da.middle,Da.pos0)); } + CreateEndAnchor(Da.pos0,anchor_array,TRUE); + CreateEndAnchor(Da.pos1,anchor_array,FALSE); + if (!track || !Da.trk) + DrawArrowHeadsArray( anchor_array, Da.middle, FindAngle(Da.pos0,Da.pos1)+90, TRUE, wDrawColorBlue ); break; } return C_CONTINUE; case C_UP: + /* Note - no anchor reset - assumes run after Down/Move */ if (!Da.down) return C_CONTINUE; if (Da.trk) { angle1 = NormalizeAngle(GetTrkEndAngle(Da.trk, Da.ep)); - angle2 = NormalizeAngle(FindAngle(pos, pos0)-angle1); + angle2 = NormalizeAngle(FindAngle(pos, Da.pos0)-angle1); if (mode == crvCmdFromEP1) { if (angle2 > 90.0 && angle2 < 270.0) { - Translate( &pos, pos0, angle1, -FindDistance( pos0, pos )*cos(D2R(angle2)) ); + Translate( &pos, Da.pos0, angle1, -FindDistance( Da.pos0, pos )*cos(D2R(angle2)) ); Da.pos1 = pos; } else { ErrorMessage( MSG_TRK_TOO_SHORT, "Curved ", PutDim(0.0) ); return C_TERMINATE; } + } else if (mode == crvCmdFromTangent) { + DIST_T dp = FindDistance(Da.pos0, pos)*sin(D2R(angle2)); + Translate( &pos, Da.pos0, angle1-90.0, dp ); + Da.pos1 = pos; } else { - DIST_T dp = -FindDistance(pos0, pos)*sin(D2R(angle2)); + DIST_T dp = -FindDistance(Da.pos0, pos)*sin(D2R(angle2)); if (angle2 > 180.0) - Translate( &pos, pos0, angle1+90.0, dp ); + Translate( &pos, Da.pos0, angle1+90.0, dp ); else - Translate( &pos, pos0, angle1-90.0, dp ); + Translate( &pos, Da.pos0, angle1-90.0, dp ); Da.pos1 = pos; } + if (FindDistance(Da.pos0,Da.pos1)<minLength) { + ErrorMessage( MSG_TRK_TOO_SHORT, "Curved ", PutDim(FindDistance(Da.pos0,Da.pos1)) ); + return C_TERMINATE; + } } switch (mode) { case crvCmdFromEP1: - DrawArrowHeads( &tempSegs(1), pos, FindAngle(pos,pos0)+90, TRUE, drawColorRed ); - tempSegs_da.cnt = 6; - break; - case crvCmdFromChord: - tempSegs(1).color = drawColorRed; case crvCmdFromTangent: case crvCmdFromCenter: - tempSegs(2).color = drawColorRed; - tempSegs(3).color = drawColorRed; - tempSegs(4).color = drawColorRed; - tempSegs(5).color = drawColorRed; - tempSegs(6).color = drawColorRed; - break; + case crvCmdFromChord: + for (int i=0;i<(*anchor_array).cnt;i++) { + DYNARR_N(trkSeg_t,*anchor_array,i).color = drawColorRed; + } + break; } message( _("Drag on Red arrows to adjust curve") ); return C_CONTINUE; @@ -296,6 +410,7 @@ EXPORT STATUS_T CreateCurve( } + static STATUS_T CmdCurve( wAction_t action, coOrd pos ) { track_p t; @@ -310,38 +425,71 @@ static STATUS_T CmdCurve( wAction_t action, coOrd pos ) Da.state = -1; Da.pos0 = pos; tempSegs_da.cnt = 0; + segCnt = 0; STATUS_T rcode; - return CreateCurve( action, pos, TRUE, wDrawColorBlack, 0, curveMode, InfoMessage ); - - case C_TEXT: - if ( Da.state == 0 ) - return CreateCurve( action, pos, TRUE, wDrawColorBlack, 0, curveMode, InfoMessage ); - else - return C_CONTINUE; + DYNARR_RESET(trkSeg_t,anchors_da); + return CreateCurve( action, pos, TRUE, wDrawColorBlack, 0, curveMode, &anchors_da, InfoMessage ); case C_DOWN: - if ( Da.state == -1 ) { - //SnapPos( &pos ); - Da.pos0 = pos; + if (Da.state == -1) { + BOOL_T found = FALSE; + if (curveMode != crvCmdFromCenter ) { + if (((MyGetKeyState() & WKEY_ALT)==0) == magneticSnap) { + if ((t = OnTrack(&pos,FALSE,TRUE))!=NULL) { + EPINX_T ep = PickUnconnectedEndPointSilent(pos, t); + if (ep != -1) { + if (GetTrkGauge(t) != GetScaleTrackGauge(GetLayoutCurScale())) { + wBeep(); + InfoMessage(_("Track is different gauge")); + return C_CONTINUE; + } + pos = GetTrkEndPos(t, ep); + found = TRUE; + } + } + } + } + if (!found) SnapPos( &pos ); + Da.pos0 = Da.pos1 = pos; Da.state = 0; - rcode = CreateCurve( action, pos, TRUE, wDrawColorBlack, 0, curveMode, InfoMessage ); + rcode = CreateCurve( action, pos, TRUE, wDrawColorBlack, 0, curveMode, &anchors_da, InfoMessage ); + segCnt = tempSegs_da.cnt ; if (!Da.down) Da.state = -1; return rcode; //Da.pos0 = pos; - } else { - tempSegs_da.cnt = segCnt; - return C_CONTINUE; } + //This is where the user could adjust - if we allow that? + tempSegs_da.cnt = segCnt; + return C_CONTINUE; + + + case wActionMove: + if ((Da.state<0) && (curveMode != crvCmdFromCenter)) { + DYNARR_RESET(trkSeg_t,anchors_da); + if (((MyGetKeyState() & WKEY_ALT)==0) == magneticSnap) { + if ((t=OnTrack(&pos,FALSE,TRUE))!= NULL) { + if (GetTrkGauge(t) == GetScaleTrackGauge(GetLayoutCurScale())) { + EPINX_T ep = PickUnconnectedEndPointSilent(pos, t); + if (ep != -1) { + pos = GetTrkEndPos(t, ep); + CreateEndAnchor(pos,&anchors_da,FALSE); + } + } + } + } + } + return C_CONTINUE; case C_MOVE: if (Da.state<0) return C_CONTINUE; - mainD.funcs->options = wDrawOptTemp; - DrawSegs( &mainD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); if ( Da.state == 0 ) { Da.pos1 = pos; - rc = CreateCurve( action, pos, TRUE, wDrawColorBlack, 0, curveMode, InfoMessage ); + rc = CreateCurve( action, pos, TRUE, wDrawColorBlack, 0, curveMode, &anchors_da, InfoMessage ); + segCnt = tempSegs_da.cnt ; } else { + DYNARR_RESET(trkSeg_t,anchors_da); // SnapPos( &pos ); + tempSegs_da.cnt = segCnt; if (Da.trk) PlotCurve( curveMode, Da.pos0, Da.pos1, pos, &Da.curveData, FALSE ); else PlotCurve( curveMode, Da.pos0, Da.pos1, pos, &Da.curveData, TRUE ); if (Da.curveData.type == curveTypeStraight) { @@ -349,11 +497,14 @@ static STATUS_T CmdCurve( wAction_t action, coOrd pos ) tempSegs(0).u.l.pos[0] = Da.pos0; tempSegs(0).u.l.pos[1] = Da.curveData.pos1; tempSegs_da.cnt = 1; + segCnt = 1; InfoMessage( _("Straight Track: Length=%s Angle=%0.3f"), FormatDistance(FindDistance( Da.pos0, Da.curveData.pos1 )), PutAngle(FindAngle( Da.pos0, Da.curveData.pos1 )) ); + DrawArrowHeadsArray(&anchors_da,Da.curveData.pos1,FindAngle(Da.pos0, Da.curveData.pos1)+90,TRUE,wDrawColorRed); } else if (Da.curveData.type == curveTypeNone) { tempSegs_da.cnt = 0; + segCnt = 0; InfoMessage( _("Back") ); } else if (Da.curveData.type == curveTypeCurve) { tempSegs(0).type = SEG_CRVTRK; @@ -362,6 +513,7 @@ static STATUS_T CmdCurve( wAction_t action, coOrd pos ) tempSegs(0).u.c.a0 = Da.curveData.a0; tempSegs(0).u.c.a1 = Da.curveData.a1; tempSegs_da.cnt = 1; + segCnt = 1; d = D2R(Da.curveData.a1); if (d < 0.0) d = 2*M_PI+d; @@ -375,80 +527,101 @@ static STATUS_T CmdCurve( wAction_t action, coOrd pos ) InfoMessage( _("Curved Track: Radius=%s Angle=%0.3f Length=%s"), FormatDistance(Da.curveData.curveRadius), Da.curveData.a1, FormatDistance(Da.curveData.curveRadius*d) ); + coOrd pos1; + Translate(&pos1,Da.curveData.curvePos,Da.curveData.a0+Da.curveData.a1,Da.curveData.curveRadius); + if (curveMode == crvCmdFromEP1 || curveMode == crvCmdFromChord) + DrawArrowHeadsArray(&anchors_da,pos,FindAngle(Da.curveData.curvePos,pos),TRUE,wDrawColorRed); + else if (curveMode == crvCmdFromTangent || curveMode == crvCmdFromCenter) { + CreateEndAnchor(Da.curveData.pos2,&anchors_da,FALSE); + DrawArrowHeadsArray(&anchors_da,Da.curveData.pos2,FindAngle(Da.curveData.curvePos,Da.curveData.pos2)+90,TRUE,wDrawColorRed); + } + CreateEndAnchor(Da.curveData.curvePos,&anchors_da,TRUE); } } - DrawSegs( &mainD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); mainD.funcs->options = 0; return rc; - - + case C_TEXT: + if ( Da.state == 0 ) + return CreateCurve( action, pos, TRUE, wDrawColorBlack, 0, curveMode, &anchors_da, InfoMessage ); + /*no break*/ case C_UP: if (Da.state<0) return C_CONTINUE; - mainD.funcs->options = wDrawOptTemp; - DrawSegs( &mainD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); - if (Da.state == 0) { + if (Da.state == 0 && ((curveMode != crvCmdFromChord) || (curveMode == crvCmdFromChord && !Da.trk))) { SnapPos( &pos ); Da.pos1 = pos; + if ((d = FindDistance(Da.pos0,Da.pos1))<minLength) { + ErrorMessage( MSG_TRK_TOO_SHORT, "Curved ", PutDim(fabs(minLength-d)) ); + return C_TERMINATE; + } Da.state = 1; - CreateCurve( action, pos, TRUE, wDrawColorBlack, 0, curveMode, InfoMessage ); - DrawSegs( &mainD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); + CreateCurve( action, pos, TRUE, wDrawColorBlack, 0, curveMode, &anchors_da, InfoMessage ); + tempSegs_da.cnt = 1; mainD.funcs->options = 0; segCnt = tempSegs_da.cnt; InfoMessage( _("Drag on Red arrows to adjust curve") ); return C_CONTINUE; - } else { - mainD.funcs->options = 0; - tempSegs_da.cnt = 0; - Da.state = -1; - if (Da.curveData.type == curveTypeStraight) { - if ((d=FindDistance( Da.pos0, Da.curveData.pos1 )) <= minLength) { - ErrorMessage( MSG_TRK_TOO_SHORT, "Curved ", PutDim(fabs(minLength-d)) ); - return C_TERMINATE; - } - UndoStart( _("Create Straight Track"), "newCurve - straight" ); - t = NewStraightTrack( Da.pos0, Da.curveData.pos1 ); - if (Da.trk) { - EPINX_T ep = PickUnconnectedEndPoint(Da.pos0, t); - if (ep != -1) ConnectTracks(Da.trk, Da.ep, t, ep); - } - UndoEnd(); - } else if (Da.curveData.type == curveTypeCurve) { - if ((d= Da.curveData.curveRadius * Da.curveData.a1 *2.0*M_PI/360.0) <= minLength) { - ErrorMessage( MSG_TRK_TOO_SHORT, "Curved ", PutDim(fabs(minLength-d)) ); - return C_TERMINATE; - } - UndoStart( _("Create Curved Track"), "newCurve - curve" ); - t = NewCurvedTrack( Da.curveData.curvePos, Da.curveData.curveRadius, - Da.curveData.a0, Da.curveData.a1, 0 ); - if (Da.trk) { - EPINX_T ep = PickUnconnectedEndPoint(Da.pos0, t); - if (ep != -1) ConnectTracks(Da.trk, Da.ep, t, ep); - } - UndoEnd(); - } else { - return C_ERROR; + } else if ((curveMode == crvCmdFromChord && Da.state == 0 && Da.trk)) { + pos = Da.middle; + if ((d = FindDistance(Da.pos0,Da.pos1))<minLength) { + ErrorMessage( MSG_TRK_TOO_SHORT, "Curved ", PutDim(fabs(minLength-d)) ); + return C_TERMINATE; + } + PlotCurve( curveMode, Da.pos0, Da.pos1, Da.middle, &Da.curveData, TRUE ); + } + mainD.funcs->options = 0; + tempSegs_da.cnt = 0; + segCnt = 0; + Da.state = -1; + DYNARR_RESET(trkSeg_t,anchors_da); // No More anchors for this one + if (Da.curveData.type == curveTypeStraight) { + if ((d = FindDistance( Da.pos0, Da.curveData.pos1 )) < minLength) { + ErrorMessage( MSG_TRK_TOO_SHORT, "Curved ", PutDim(fabs(minLength-d)) ); + return C_TERMINATE; + } + UndoStart( _("Create Straight Track"), "newCurve - straight" ); + t = NewStraightTrack( Da.pos0, Da.curveData.pos1 ); + if (Da.trk && !(MyGetKeyState() & WKEY_SHIFT)) { + EPINX_T ep = PickUnconnectedEndPoint(Da.pos0, t); + if (ep != -1) ConnectTracks(Da.trk, Da.ep, t, ep); + } + UndoEnd(); + } else if (Da.curveData.type == curveTypeCurve) { + if ((d = Da.curveData.curveRadius * Da.curveData.a1 *2.0*M_PI/360.0) < minLength) { + ErrorMessage( MSG_TRK_TOO_SHORT, "Curved ", PutDim(fabs(minLength-d)) ); + return C_TERMINATE; + } + UndoStart( _("Create Curved Track"), "newCurve - curve" ); + t = NewCurvedTrack( Da.curveData.curvePos, Da.curveData.curveRadius, + Da.curveData.a0, Da.curveData.a1, 0 ); + if (Da.trk && !(MyGetKeyState() & WKEY_SHIFT)) { + EPINX_T ep = PickUnconnectedEndPoint(Da.pos0, t); + if (ep != -1) ConnectTracks(Da.trk, Da.ep, t, ep); } - DrawNewTrack( t ); - return C_TERMINATE; + UndoEnd(); + } else { + return C_ERROR; } + DrawNewTrack( t ); + return C_TERMINATE; case C_REDRAW: if ( Da.state >= 0 ) { - mainD.funcs->options = wDrawOptTemp; - DrawSegs( &mainD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); + DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); mainD.funcs->options = 0; } + if (anchors_da.cnt) + DrawSegs( &tempD, zero, 0.0, &anchors(0), anchors_da.cnt, trackGauge, wDrawColorBlack ); return C_CONTINUE; case C_CANCEL: if (Da.state == 1) { - mainD.funcs->options = wDrawOptTemp; - DrawSegs( &mainD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); - mainD.funcs->options = 0; tempSegs_da.cnt = 0; Da.trk = NULL; } + DYNARR_RESET(trkSeg_t,anchors_da); + DYNARR_RESET(trkSeg_t,tempSegs_da); Da.state = -1; + segCnt = 0; return C_CONTINUE; } @@ -581,7 +754,6 @@ static void ComputeHelix( static void HelixCancel( wWin_p win ) { wHide( helixW ); - Reset(); } @@ -610,30 +782,30 @@ static STATUS_T CmdCircleCommon( wAction_t action, coOrd pos, BOOL_T helix ) case C_START: if (helix) { if (helixW == NULL) - helixW = ParamCreateDialog( &helixPG, MakeWindowTitle(_("Helix")), NULL, NULL, HelixCancel, TRUE, NULL, 0, ComputeHelix ); - ParamLoadControls( &helixPG ); - ParamGroupRecord( &helixPG ); - ComputeHelix( NULL, 6, NULL ); - wShow( helixW ); - memset( h_orders, 0, sizeof h_orders ); + helixW = ParamCreateDialog(&helixPG, MakeWindowTitle(_("Helix")), NULL, NULL, HelixCancel, TRUE, NULL, 0, ComputeHelix); + ParamLoadControls(&helixPG); + ParamGroupRecord(&helixPG); + ComputeHelix(NULL, 6, NULL); + wShow(helixW); + memset(h_orders, 0, sizeof h_orders); h_clock = 0; } else { - ParamLoadControls( &circleRadiusPG ); - ParamGroupRecord( &circleRadiusPG ); - switch ( circleMode ) { + ParamLoadControls(&circleRadiusPG); + ParamGroupRecord(&circleRadiusPG); + switch (circleMode) { case circleCmdFixedRadius: controls[0] = circleRadiusPLs[0].control; controls[1] = NULL; labels[0] = N_("Circle Radius"); - InfoSubstituteControls( controls, labels ); + InfoSubstituteControls(controls, labels); break; case circleCmdFromTangent: - InfoSubstituteControls( NULL, NULL ); - InfoMessage( _("Click on Circle Edge") ); + InfoSubstituteControls(NULL, NULL); + InfoMessage(_("Click on Circle Edge")); break; case circleCmdFromCenter: - InfoSubstituteControls( NULL, NULL ); - InfoMessage( _("Click on Circle Center") ); + InfoSubstituteControls(NULL, NULL); + InfoMessage(_("Click on Circle Center")); break; } } @@ -641,98 +813,95 @@ static STATUS_T CmdCircleCommon( wAction_t action, coOrd pos, BOOL_T helix ) return C_CONTINUE; case C_DOWN: - DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); + DYNARR_SET(trkSeg_t, tempSegs_da, 1); tempSegs_da.cnt = 0; if (helix) { if (helixRadius <= 0.0) { - ErrorMessage( MSG_RADIUS_GTR_0 ); + ErrorMessage(MSG_RADIUS_GTR_0); return C_ERROR; } if (helixTurns <= 0) { - ErrorMessage( MSG_HELIX_TURNS_GTR_0 ); + ErrorMessage(MSG_HELIX_TURNS_GTR_0); return C_ERROR; } - ParamLoadData( &helixPG ); + ParamLoadData(&helixPG); } else { - ParamLoadData( &circleRadiusPG ); - switch( circleMode ) { + ParamLoadData(&circleRadiusPG); + switch (circleMode) { case circleCmdFixedRadius: if (circleRadius <= 0.0) { - ErrorMessage( MSG_RADIUS_GTR_0 ); + ErrorMessage(MSG_RADIUS_GTR_0); return C_ERROR; } break; case circleCmdFromTangent: - InfoSubstituteControls( NULL, NULL ); - InfoMessage( _("Drag to Center") ); + InfoSubstituteControls(NULL, NULL); + InfoMessage(_("Drag to Center")); break; case circleCmdFromCenter: - InfoSubstituteControls( NULL, NULL ); - InfoMessage( _("Drag to Edge") ); + InfoSubstituteControls(NULL, NULL); + InfoMessage(_("Drag to Edge")); break; } } - SnapPos( &pos ); + SnapPos(&pos); tempSegs(0).u.c.center = pos0 = pos; tempSegs(0).color = wDrawColorBlack; tempSegs(0).width = 0; return C_CONTINUE; case C_MOVE: - DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); - SnapPos( &pos ); + SnapPos(&pos); tempSegs(0).u.c.center = pos; - if ( !helix ) { - switch ( circleMode ) { + if (!helix) { + switch (circleMode) { case circleCmdFixedRadius: break; case circleCmdFromCenter: tempSegs(0).u.c.center = pos0; - circleRadius = FindDistance( tempSegs(0).u.c.center, pos ); - InfoMessage( _("Radius=%s"), FormatDistance(circleRadius) ); + circleRadius = FindDistance(tempSegs(0).u.c.center, pos); + InfoMessage(_("Radius=%s"), FormatDistance(circleRadius)); break; case circleCmdFromTangent: - circleRadius = FindDistance( tempSegs(0).u.c.center, pos0 ); - InfoMessage( _("Radius=%s"), FormatDistance(circleRadius) ); + circleRadius = FindDistance(tempSegs(0).u.c.center, pos0); + InfoMessage(_("Radius=%s"), FormatDistance(circleRadius)); break; } } tempSegs(0).type = SEG_CRVTRK; - tempSegs(0).u.c.radius = helix?helixRadius:circleRadius; + tempSegs(0).u.c.radius = helix ? helixRadius : circleRadius; tempSegs(0).u.c.a0 = 0.0; tempSegs(0).u.c.a1 = 360.0; tempSegs_da.cnt = 1; - DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); return C_CONTINUE; case C_UP: - DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); - if (helixRadius > mapD.size.x && helixRadius > mapD.size.y) { - ErrorMessage( MSG_RADIUS_TOO_BIG ); - return C_ERROR; - } - if (circleRadius > mapD.size.x && circleRadius > mapD.size.y) { - ErrorMessage( MSG_RADIUS_TOO_BIG ); - return C_ERROR; - } - if ( helix ) { + if (helix) { + if (helixRadius > mapD.size.x || helixRadius > mapD.size.y) { + ErrorMessage(MSG_RADIUS_TOO_BIG); + return C_ERROR; + } if (helixRadius > 10000) { - ErrorMessage( MSG_RADIUS_GTR_10000 ); + ErrorMessage(MSG_RADIUS_GTR_10000); return C_ERROR; } - UndoStart( _("Create Helix Track"), "newHelix" ); - t = NewCurvedTrack( tempSegs(0).u.c.center, helixRadius, 0.0, 0.0, helixTurns ); + UndoStart(_("Create Helix Track"), "newHelix"); + t = NewCurvedTrack(tempSegs(0).u.c.center, helixRadius, 0.0, 0.0, helixTurns); } else { - if ( circleRadius <= 0 ) { - ErrorMessage( MSG_RADIUS_GTR_0 ); + if (circleRadius > mapD.size.x || circleRadius > mapD.size.y) { + ErrorMessage(MSG_RADIUS_TOO_BIG); + return C_ERROR; + } + if (circleRadius <= 0) { + ErrorMessage(MSG_RADIUS_GTR_0); return C_ERROR; } if ((circleRadius > 100000) || (helixRadius > 10000)) { - ErrorMessage( MSG_RADIUS_GTR_10000 ); + ErrorMessage(MSG_RADIUS_GTR_10000); return C_ERROR; } - UndoStart( _("Create Circle Track"), "newCircle" ); - t = NewCurvedTrack( tempSegs(0).u.c.center, circleRadius, 0.0, 0.0, 0 ); + UndoStart(_("Create Circle Track"), "newCircle"); + t = NewCurvedTrack(tempSegs(0).u.c.center, circleRadius, 0.0, 0.0, 0); } UndoEnd(); DrawNewTrack(t); @@ -779,19 +948,21 @@ static STATUS_T CmdHelix( wAction_t action, coOrd pos ) #include "bitmaps/curve3.xpm" #include "bitmaps/curve4.xpm" #include "bitmaps/bezier.xpm" +#include "bitmaps/cornu.xpm" #include "bitmaps/circle1.xpm" #include "bitmaps/circle2.xpm" #include "bitmaps/circle3.xpm" EXPORT void InitCmdCurve( wMenu_p menu ) { + AddMenuButton( menu, CmdCornu, "cmdCornu", _("Cornu Curve"), wIconCreatePixMap(cornu_xpm), LEVEL0_50, IC_STICKY|IC_POPUP2|IC_WANT_MOVE, ACCL_CORNU, (void*)cornuCmdCreateTrack); ButtonGroupBegin( _("Curve Track"), "cmdCircleSetCmd", _("Curve Tracks") ); - AddMenuButton( menu, CmdCurve, "cmdCurveEndPt", _("Curve from End-Pt"), wIconCreatePixMap( curve1_xpm ), LEVEL0_50, IC_STICKY|IC_POPUP2, ACCL_CURVE1, (void*)0 ); - AddMenuButton( menu, CmdCurve, "cmdCurveTangent", _("Curve from Tangent"), wIconCreatePixMap( curve2_xpm ), LEVEL0_50, IC_STICKY|IC_POPUP2, ACCL_CURVE2, (void*)1 ); - AddMenuButton( menu, CmdCurve, "cmdCurveCenter", _("Curve from Center"), wIconCreatePixMap( curve3_xpm ), LEVEL0_50, IC_STICKY|IC_POPUP2, ACCL_CURVE3, (void*)2 ); - AddMenuButton( menu, CmdCurve, "cmdCurveChord", _("Curve from Chord"), wIconCreatePixMap( curve4_xpm ), LEVEL0_50, IC_STICKY|IC_POPUP2, ACCL_CURVE4, (void*)3 ); - AddMenuButton( menu, CmdBezCurve, "cmdBezier", _("Bezier Curve"), wIconCreatePixMap(bezier_xpm), LEVEL0_50, IC_STICKY|IC_POPUP2, ACCL_BEZIER, (void*)bezCmdCreateTrack ); + AddMenuButton( menu, CmdCurve, "cmdCurveEndPt", _("Curve from End-Pt"), wIconCreatePixMap( curve1_xpm ), LEVEL0_50, IC_STICKY|IC_POPUP2|IC_WANT_MOVE, ACCL_CURVE1, (void*)0 ); + AddMenuButton( menu, CmdCurve, "cmdCurveTangent", _("Curve from Tangent"), wIconCreatePixMap( curve2_xpm ), LEVEL0_50, IC_STICKY|IC_POPUP2|IC_WANT_MOVE, ACCL_CURVE2, (void*)1 ); + AddMenuButton( menu, CmdCurve, "cmdCurveCenter", _("Curve from Center"), wIconCreatePixMap( curve3_xpm ), LEVEL0_50, IC_STICKY|IC_POPUP2|IC_WANT_MOVE, ACCL_CURVE3, (void*)2 ); + AddMenuButton( menu, CmdCurve, "cmdCurveChord", _("Curve from Chord"), wIconCreatePixMap( curve4_xpm ), LEVEL0_50, IC_STICKY|IC_POPUP2|IC_WANT_MOVE, ACCL_CURVE4, (void*)3 ); + AddMenuButton( menu, CmdBezCurve, "cmdBezier", _("Bezier Curve"), wIconCreatePixMap(bezier_xpm), LEVEL0_50, IC_STICKY|IC_POPUP2|IC_WANT_MOVE, ACCL_BEZIER, (void*)bezCmdCreateTrack ); ButtonGroupEnd(); ButtonGroupBegin( _("Circle Track"), "cmdCurveSetCmd", _("Circle Tracks") ); @@ -816,7 +987,7 @@ EXPORT void InitCmdCurve( wMenu_p menu ) void InitCmdHelix(wMenu_p menu) { AddMenuButton(menu, CmdHelix, "cmdHelix", _("Helix"), NULL, LEVEL0_50, - IC_STICKY|IC_POPUP2, ACCL_HELIX, NULL); + IC_STICKY|IC_INITNOTSTICKY|IC_POPUP2, ACCL_HELIX, NULL); ParamRegister(&helixPG); RegisterChangeNotification(ChangeHelixW); } |