/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "ccurve.h" #include "cbezier.h" #include "compound.h" #include "cundo.h" #include "drawgeom.h" #include "fileio.h" #include "param.h" #include "track.h" #include "common-ui.h" static long drawGeomCurveMode; #define contextSegs(N) DYNARR_N( trkSeg_t, context->Segs_da, N ) static dynArr_t points_da; static dynArr_t anchors_da; static dynArr_t select_da; #define points(N) DYNARR_N( pts_t, points_da, N ) #define point_selected(N) DYNARR_N( wBool_t, select_da, N) #define anchors(N) DYNARR_N( trkSeg_t, anchors_da, N) static void EndPoly( drawContext_t * context, int cnt, wBool_t open) { trkSeg_p segPtr; track_p trk; pts_t * pts; int inx; if (context->State==0 || cnt == 0) { return; } if ( cnt < 3 ) { DYNARR_RESET( trkSeg_t, tempSegs_da ); ErrorMessage( MSG_POLY_SHAPES_3_SIDES ); return; } pts = (pts_t*)MyMalloc( (cnt) * sizeof (pts_t) ); for ( inx=0; inxtype = ( (context->Op == OP_POLY || context->Op == OP_POLYLINE )? SEG_POLY:SEG_FILPOLY ); segPtr->u.p.cnt = cnt; segPtr->u.p.pts = pts; segPtr->u.p.angle = 0.0; segPtr->u.p.orig = zero; segPtr->u.p.polyType = open?POLYLINE:FREEFORM; UndoStart( _("Create Lines"), "newDraw" ); trk = MakeDrawFromSeg( zero, 0.0, segPtr ); DrawNewTrack( trk ); DYNARR_RESET( trkSeg_t, tempSegs_da ); } static void DrawGeomOk( BOOL_T started ) { track_p trk; int inx; if (tempSegs_da.cnt <= 0) { return; } if (!started) { UndoStart( _("Create Lines"), "newDraw" ); } for ( inx=0; inxState == 2) { if ((context->Op >= OP_CURVE1) && (context->Op <= OP_CURVE4)) { if (context->ArcData.type == curveTypeCurve) { ANGLE_T a = FindAngle(context->ArcData.curvePos,*p); if (IsClose(FindDistance(context->ArcData.curvePos, *p)-context->ArcData.curveRadius) && (a>=context->ArcData.a0) && (a<=context->ArcData.a0+context->ArcData.a1)) { Translate(p,context->ArcData.curvePos,a,context->ArcData.curveRadius); return TRUE; } } else { if (IsClose(LineDistance(p,tempSegs(0).u.l.pos[0],tempSegs(0).u.l.pos[1]))) { return TRUE; } } } else if ( (context->Op >=OP_LINE) && (context->Op <= OP_BENCH)) { if (IsClose(LineDistance(p,tempSegs(0).u.l.pos[0],tempSegs(0).u.l.pos[1]))) { return TRUE; } } } return FALSE; } /** * Create and draw a graphics primitive (lines, arc, circle). The complete handling of mouse * movements and clicks during the editing process is done here. * * \param action IN mouse action * \param pos IN position of mouse pointer * \param context IN/OUT parameters for drawing op * \return next command state * * Note - Poly supports both clicking points and/or dragging sides. Close is space or enter. * Note - This routine will be recalled to C_UPDATE the last action if the State is 2 and the user updates the dialog * */ STATUS_T DrawGeomMouse( wAction_t action, coOrd pos, drawContext_t *context) { // static int lastValid = FALSE; static BOOL_T locked; static coOrd pos0, pos0x, pos1, lastPos, movePos; trkSeg_p segPtr; pts_t *pts; int inx; static int segCnt; DIST_T d; ANGLE_T a1,a2; static ANGLE_T line_angle; // BOOL_T createTrack; switch (action&0xFF) { case C_UPDATE: if (context->State == 0 ) { return C_TERMINATE; } DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); if (context->Op != OP_POLY && context->Op != OP_FILLPOLY && context->Op != OP_POLYLINE && context->State == 1) { return C_TERMINATE; } switch (context->Op) { case OP_CIRCLE1: case OP_CIRCLE2: case OP_CIRCLE3: case OP_FILLCIRCLE1: case OP_FILLCIRCLE2: case OP_FILLCIRCLE3: tempSegs(0).u.c.radius = context->radius; break; case OP_CURVE1: case OP_CURVE2: case OP_CURVE3: case OP_CURVE4: if (context->ArcData.type == curveTypeCurve) { if (tempSegs(0).u.c.radius != context->radius) { coOrd end; Translate(&end,context->ArcData.curvePos,context->ArcData.a0, context->ArcData.curveRadius); tempSegs(0).u.c.radius = context->radius; Translate(&tempSegs(0).u.c.center,end,context->ArcData.a0+180,context->radius); context->ArcData.curvePos = tempSegs(0).u.c.center; context->ArcData.curveRadius = tempSegs(0).u.c.radius; } tempSegs(0).u.c.a1 = context->angle; context->ArcData.a1 = tempSegs(0).u.c.a1; Translate(&context->ArcData.pos1,context->ArcData.curvePos,context->ArcData.a0, context->ArcData.curveRadius); Translate(&context->ArcData.pos2,context->ArcData.curvePos, context->ArcData.a0+context->ArcData.a1,context->ArcData.curveRadius); } else { Translate(&tempSegs(0).u.l.pos[1],tempSegs(0).u.l.pos[0],context->angle, context->length); } break; case OP_LINE: case OP_BENCH: case OP_TBLEDGE: a1 = FindAngle(pos0,pos1); Translate(&tempSegs(0).u.l.pos[1],tempSegs(0).u.l.pos[0],context->angle, context->length); lastPos = pos1 = tempSegs(0).u.l.pos[1]; context->angle = NormalizeAngle(context->angle); break; case OP_BOX: case OP_FILLBOX: pts = tempSegs(0).u.p.pts; a1 = FindAngle(pts[0].pt,pts[1].pt); Translate(&pts[1].pt,pts[0].pt,a1,context->length); a2 = FindAngle(pts[0].pt,pts[3].pt); Translate(&pts[2].pt,pts[1].pt,a2,context->width); Translate(&pts[3].pt,pts[0].pt,a2,context->width); break; case OP_POLY: case OP_FILLPOLY: case OP_POLYLINE: DYNARR_SET( trkSeg_t, tempSegs_da, segCnt ); if (segCnt>1) { ANGLE_T an = FindAngle(tempSegs(segCnt-2).u.l.pos[0], tempSegs(segCnt-2).u.l.pos[1]); an = an+context->angle; Translate(&tempSegs(segCnt-1).u.l.pos[1],tempSegs(segCnt-1).u.l.pos[0],an, context->length); } else { Translate(&tempSegs(0).u.l.pos[1],tempSegs(0).u.l.pos[0],context->angle, context->length); } pos1 = lastPos = tempSegs(segCnt-1).u.l.pos[1]; context->angle = fabs(context->angle); if (context->angle >180) { context->angle = context->angle - 180.0; } break; default: break; } context->Changed = TRUE; //Update made MainRedraw(); DYNARR_RESET( trkSeg_t, anchors_da ); return C_CONTINUE; case C_START: context->State = 0; context->Changed = FALSE; segCnt = 0; CleanSegs(&tempSegs_da); DYNARR_RESET( trkSeg_t, tempSegs_da ); DYNARR_RESET( trkSeg_t, anchors_da ); locked = FALSE; if (!magneticSnap) { InfoMessage(_("+Alt for Magnetic Snap")); } else { InfoMessage(_("+Alt to inhibit Magnetic Snap")); } wSetCursor(mainD.d,defaultCursor); movePos = zero; context->UndoStarted = FALSE; return C_CONTINUE; case wActionMove: locked = FALSE; wSetCursor(mainD.d,defaultCursor); if ((context->State == 0 && context->Op != OP_FILLCIRCLE2 && context->Op != OP_CIRCLE2) || context->State ==2 || (context->State == 1 && (context->Op == OP_POLY || context->Op == OP_FILLPOLY || context->Op == OP_POLYLINE))) { DYNARR_RESET( trkSeg_t, anchors_da ); wSetCursor(mainD.d,defaultCursor); switch (context->Op) { //Snap pos to nearest line for lines and some curves case OP_CURVE1: case OP_CURVE2: case OP_CURVE3: case OP_CURVE4: case OP_CIRCLE2: case OP_CIRCLE3: case OP_FILLCIRCLE2: case OP_FILLCIRCLE3: case OP_LINE: case OP_DIMLINE: case OP_BENCH: case OP_TBLEDGE: case OP_BOX: case OP_FILLBOX: case OP_POLY: case OP_FILLPOLY: case OP_POLYLINE:; if (((MyGetKeyState() & WKEY_ALT)==0) == magneticSnap ) { coOrd p = pos; track_p t; if (((t=OnTrack(&p,FALSE,FALSE))!=NULL) && (IsClose(FindDistance(p,pos))) ) { if (context->Op == OP_DIMLINE ) { CreateEndAnchor(p,FALSE); // wSetCursor(mainD.d,wCursorNone); movePos = p; locked = TRUE; } else if (!IsTrack(t)) { CreateEndAnchor(p,FALSE); // wSetCursor(mainD.d,wCursorNone); movePos = p; locked = TRUE; } } } if (!locked && SnapPos(&pos)) { CreateEndAnchor(pos,FALSE); // wSetCursor(mainD.d,wCursorNone); movePos = pos; locked = TRUE; } break; default: ; } } return C_CONTINUE; case wActionRDown: case wActionLDown: DYNARR_RESET( trkSeg_t, anchors_da ); wSetCursor(mainD.d,defaultCursor); if (context->State == 2) { DYNARR_SET( trkSeg_t, tempSegs_da, segCnt ); if ((context->Op == OP_POLY || context->Op == OP_FILLPOLY || context->Op == OP_POLYLINE)) { EndPoly(context, segCnt, context->Op==OP_POLYLINE); } else { DrawGeomOk(TRUE); } context->UndoStarted = FALSE; segCnt = 0; DYNARR_RESET( trkSeg_t, anchors_da ); context->State = 0; TryCheckPoint(); } DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); context->Started = TRUE; line_angle = 90.0; if ((context->Op == OP_CURVE1 && context->State != 2) || (context->Op == OP_CURVE2 && context->State == 0) || (context->Op == OP_CURVE3 && context->State != 0) || (context->Op == OP_CURVE4 && context->State != 2) || (context->Op == OP_CIRCLE2 && context->State != 0) || (context->Op == OP_CIRCLE3 && context->State == 0) || (context->Op == OP_FILLCIRCLE2 && context->State != 0) || (context->Op == OP_FILLCIRCLE3 && context->State == 0) || (context->Op == OP_LINE) || (context->Op == OP_DIMLINE) || (context->Op == OP_BENCH) || (context->Op == OP_TBLEDGE) || (context->Op == OP_BOX) || (context->Op == OP_FILLBOX) || (context->Op == OP_POLY) || (context->Op == OP_POLYLINE) || (context->Op == OP_FILLPOLY) ) { if (locked) { pos = movePos; } } if ((context->Op == OP_CURVE1 || context->Op == OP_CURVE2 || context->Op == OP_CURVE3 || context->Op == OP_CURVE4) && context->State == 1) { ; } else { pos0 = pos; pos1 = pos; } switch (context->Op) { case OP_LINE: case OP_DIMLINE: case OP_BENCH: switch (context->Op) { case OP_LINE: tempSegs(0).type = SEG_STRLIN; tempSegs(0).color = lineColor; break; case OP_DIMLINE: tempSegs(0).type = SEG_DIMLIN; tempSegs(0).color = wDrawColorBlack; break; case OP_BENCH: tempSegs(0).type = SEG_BENCH; tempSegs(0).color = benchColor; break; } tempSegs(0).lineWidth = lineWidth; tempSegs(0).u.l.pos[0] = tempSegs(0).u.l.pos[1] = pos; if ( context->Op == OP_BENCH || context->Op == OP_DIMLINE ) { tempSegs(0).u.l.option = context->benchOption; } else { tempSegs(0).u.l.option = 0; } context->message( _("Drag next point, +Alt reverse Magnetic Snap or +Ctrl lock to 90 deg") ); break; case OP_TBLEDGE: OnTableEdgeEndPt( NULL, &pos ); tempSegs(0).type = SEG_TBLEDGE; tempSegs(0).color = wDrawColorBlack; tempSegs(0).lineWidth = (mainD.scale<=16)?(3/context->D->dpi*context->D->scale) :0; tempSegs(0).u.l.pos[0] = tempSegs(0).u.l.pos[1] = pos; tempSegs(0).u.l.option = 0; context->message( _("Drag next point, +Alt reverse Magnetic Snap, or +Ctrl to lock to 90 degrees") ); break; case OP_CURVE1: case OP_CURVE2: case OP_CURVE3: case OP_CURVE4: if (context->State == 0) { switch ( context->Op ) { case OP_CURVE1: drawGeomCurveMode = crvCmdFromEP1; break; case OP_CURVE2: drawGeomCurveMode = crvCmdFromTangent; break; case OP_CURVE3: drawGeomCurveMode = crvCmdFromCenter; break; case OP_CURVE4: drawGeomCurveMode = crvCmdFromChord; break; } CreateCurve( C_START, pos, FALSE, lineColor, lineWidth, drawGeomCurveMode, &anchors_da, context->message ); CreateCurve( C_DOWN, pos, FALSE, lineColor, lineWidth, drawGeomCurveMode, &anchors_da, context->message ); } break; case OP_CIRCLE1: case OP_CIRCLE2: case OP_CIRCLE3: case OP_FILLCIRCLE1: case OP_FILLCIRCLE2: case OP_FILLCIRCLE3: tempSegs(0).type = SEG_CRVLIN; tempSegs(0).color = lineColor; if ( context->Op >= OP_CIRCLE1 && context->Op <= OP_CIRCLE3 ) { tempSegs(0).lineWidth = lineWidth; } else { tempSegs(0).lineWidth = 0; } tempSegs(0).u.c.a0 = 0; tempSegs(0).u.c.a1 = 360; tempSegs(0).u.c.radius = 0; tempSegs(0).u.c.center = pos; context->message( _("Drag to set radius") ); context->State = 1; break; case OP_FILLBOX: lineWidth = 0; /* no break */ case OP_BOX: DYNARR_SET( trkSeg_t, tempSegs_da, 4 ); for ( inx=0; inx<4; inx++ ) { tempSegs(inx).type = SEG_STRLIN; tempSegs(inx).color = lineColor; tempSegs(inx).lineWidth = lineWidth; tempSegs(inx).u.l.pos[0] = tempSegs(inx).u.l.pos[1] = pos; } context->message( _("Drag set box size") ); break; case OP_POLY: case OP_FILLPOLY: case OP_POLYLINE: DYNARR_SET( trkSeg_t, tempSegs_da, segCnt ); wBool_t first_spot = FALSE; if (segCnt == 1 && tempSegs(0).type == SEG_CRVLIN) { coOrd start; start = tempSegs(0).u.c.center; tempSegs(0).type = SEG_STRLIN; tempSegs(0).u.l.pos[0] = start; first_spot=TRUE; } else { DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 ); } segPtr = &tempSegs(tempSegs_da.cnt-1); segPtr->type = SEG_STRLIN; segPtr->color = lineColor; segPtr->lineWidth = (context->Op==OP_POLY || context->Op==OP_POLYLINE ? lineWidth : 0); //End if over start if ( segCnt>2 && IsClose(FindDistance(tempSegs(0).u.l.pos[0], pos ))) { segPtr->u.l.pos[0] = tempSegs(segCnt-1).u.l.pos[1]; segPtr->u.l.pos[1] = tempSegs(0).u.l.pos[0]; EndPoly(context, tempSegs_da.cnt, context->Op==OP_POLYLINE); DYNARR_RESET(pts_t, points_da); DYNARR_RESET(trkSeg_t,tempSegs_da); context->State = 0; segCnt = 0; return C_TERMINATE; } if (!first_spot) { if ( tempSegs_da.cnt == 1) { segPtr->u.l.pos[0] = pos; } else { segPtr->u.l.pos[0] = segPtr[-1].u.l.pos[1]; } } segPtr->u.l.pos[1] = pos; context->State = 1; segCnt = tempSegs_da.cnt; context->message(_("+Alt - reverse Magnetic Snap or +Ctrl - lock to 90 deg")); break; } return C_CONTINUE; case wActionRDrag: case wActionLDrag: DYNARR_RESET(trkSeg_t, anchors_da ); coOrd p = pos1 = pos; BOOL_T locked = FALSE, poslocked = FALSE; if ((context->Op == OP_CURVE1 && context->State == 1) || (context->Op == OP_CURVE2 && context->State == 0) || (context->Op == OP_CURVE4 && context->State != 1) || (context->Op == OP_CIRCLE2 && context->State != 0) || (context->Op == OP_CIRCLE3 && context->State == 0) || (context->Op == OP_FILLCIRCLE2 && context->State != 0) || (context->Op == OP_FILLCIRCLE3 && context->State == 0) || (context->Op == OP_BOX ) || (context->Op == OP_FILLBOX ) || (context->Op == OP_DIMLINE ) || (context->Op == OP_TBLEDGE) || (context->Op == OP_LINE ) || (context->Op == OP_BENCH) || (context->Op == OP_POLY) || (context->Op == OP_POLYLINE) || (context->Op == OP_FILLPOLY) ) { if ( ( (MyGetKeyState() & WKEY_ALT)==0) == magneticSnap) { p = pos; if ((OnTrack( &p, FALSE, FALSE )!=NULL) && (IsClose(FindDistance(p,pos)))) { poslocked = TRUE; pos1 = p; } } if (!poslocked) { //Set up poslock and pos1 for later p = pos; if (SnapPos(&p)) { poslocked = TRUE; pos1 = p; } } } switch (context->Op) { case OP_TBLEDGE: if ((MyGetKeyState() & WKEY_CTRL) == WKEY_CTRL) { //If +Ctrl, snap to table edge end p = pos; if (OnTableEdgeEndPt( NULL, &p )) { locked = TRUE; pos1 = p; } } /* no break */ case OP_LINE: case OP_DIMLINE: case OP_BENCH: if (!locked && ((MyGetKeyState() & WKEY_CTRL) == WKEY_CTRL )) { //If not found already +Ctl = Right Angle //Snap to Right-Angle from previous or from 0 DIST_T l = FindDistance(pos0, pos); ANGLE_T angle2 = NormalizeAngle(FindAngle(pos0, pos)-line_angle); int quad = (int)((angle2 + 45.0) / 90.0); if (tempSegs_da.cnt != 1 && (quad == 2)) { pos1 = pos0; } else if (quad == 1 || quad == 3) { if (tempSegs_da.cnt != 1) { l = fabs(l*cos(D2R(((quad==1)?line_angle+90.0:line_angle-90.0)-FindAngle(pos, pos0)))); } Translate( &pos1, pos0, NormalizeAngle(quad==1?line_angle+90.0:line_angle-90.0), l ); } else { if (tempSegs_da.cnt != 1) { l = fabs(l*cos(D2R(((quad==0 ||quad==4)?line_angle:line_angle+180.0)-FindAngle(pos,pos0)))); } Translate( &pos1, pos0, NormalizeAngle((quad==0 ||quad==4)?line_angle:line_angle+180.0), l ); } CreateLineAnchor(pos1,pos0); } DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); tempSegs(0).u.l.pos[1] = pos1; context->message( _("Length = %s, Angle = %0.2f"), FormatDistance(FindDistance( pos0, pos1 )), PutAngle(FindAngle( pos0, pos1 )) ); if (anchors_da.cnt == 0) { CreateEndAnchor(pos1, FALSE); } break; case OP_POLY: case OP_FILLPOLY: case OP_POLYLINE: if ((MyGetKeyState() & WKEY_CTRL) == WKEY_CTRL ) { coOrd last_point = zero; ANGLE_T last_angle; // ANGLE_T initial_angle; if (tempSegs_da.cnt == 1) { last_angle = 90.0; last_point = tempSegs(0).u.l.pos[0]; // initial_angle = 90.0; } else { last_point = tempSegs(tempSegs_da.cnt-2).u.l.pos[1]; last_angle = FindAngle(tempSegs(tempSegs_da.cnt-2).u.l.pos[0], tempSegs(tempSegs_da.cnt-2).u.l.pos[1]); // initial_angle = FindAngle(tempSegs(0).u.l.pos[0],tempSegs(0).u.l.pos[1]); } //Snap to Right-Angle from previous or from 0 DIST_T l = FindDistance(tempSegs(tempSegs_da.cnt-1).u.l.pos[0], pos); ANGLE_T angle2 = NormalizeAngle(FindAngle(tempSegs(tempSegs_da.cnt -1).u.l.pos[0], pos)-last_angle); int quad = (int)((angle2+45.0)/90.0); if (tempSegs_da.cnt != 1 && (quad == 2)) { pos = tempSegs(tempSegs_da.cnt-1).u.l.pos[0]; } else if (quad == 1 || quad == 3) { if (tempSegs_da.cnt != 1) { l = fabs(l*cos(D2R(((quad==1)?last_angle+90.0:last_angle-90.0)-FindAngle(pos, last_point)))); } Translate( &pos, tempSegs(tempSegs_da.cnt-1).u.l.pos[0], NormalizeAngle(quad==1?last_angle+90.0:last_angle-90.0), l ); } else { if (tempSegs_da.cnt != 1) { l = fabs(l*cos(D2R(((quad==0 ||quad==4)?last_angle:last_angle+180.0)-FindAngle(pos,last_point)))); } Translate( &pos, tempSegs(tempSegs_da.cnt-1).u.l.pos[0], NormalizeAngle((quad==0 ||quad==4)?last_angle:last_angle+180.0), l ); } CreateEndAnchor(pos,TRUE); if (FindDistance(pos,last_point)>0.0) { CreateLineAnchor(pos,last_point); } //If there is any point on this line that will give a 90 degree return to the first point, show it if (tempSegs_da.cnt > 1) { coOrd intersect; ANGLE_T an_this = FindAngle(tempSegs(tempSegs_da.cnt-2).u.l.pos[1],pos); if (FindIntersection(&intersect,tempSegs(0).u.l.pos[0],an_this+90.0, tempSegs(tempSegs_da.cnt-2).u.l.pos[1],an_this)) { ANGLE_T an_inter = FindAngle(tempSegs(tempSegs_da.cnt-2).u.l.pos[1],intersect); if (fabs(DifferenceBetweenAngles(an_inter,an_this))<90.0) { CreateSquareAnchor(intersect); d = FindDistance(intersect,pos); if (IsClose(d)) { pos = intersect; } } } } } else if (poslocked) { pos = pos1; } tempSegs(tempSegs_da.cnt-1).type = SEG_STRLIN; tempSegs(tempSegs_da.cnt-1).u.l.pos[1] = pos; context->message( _("Length = %s, Angle = %0.2f"), FormatDistance(FindDistance( tempSegs(tempSegs_da.cnt-1).u.l.pos[0], pos )), PutAngle(FindAngle( tempSegs(tempSegs_da.cnt-1).u.l.pos[0], pos )) ); segCnt = tempSegs_da.cnt; break; case OP_CURVE1: case OP_CURVE2: case OP_CURVE3: case OP_CURVE4: if (context->State == 0) { pos0x = pos1; CreateCurve( C_MOVE, pos, FALSE, lineColor, lineWidth, drawGeomCurveMode, &anchors_da, context->message ); } else { PlotCurve( drawGeomCurveMode, pos0, pos0x, pos1, &context->ArcData, FALSE, 0.0 ); DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); tempSegs(0).color = lineColor; tempSegs(0).lineWidth = lineWidth; if (context->ArcData.type == curveTypeStraight) { tempSegs(0).type = SEG_STRLIN; tempSegs(0).u.l.pos[0] = pos0; tempSegs(0).u.l.pos[1] = context->ArcData.pos1; CreateEndAnchor(pos0, FALSE); CreateEndAnchor(context->ArcData.pos1, FALSE); context->message( _("Straight Line: Length=%s Angle=%0.3f"), FormatDistance(FindDistance( pos0, context->ArcData.pos1 )), PutAngle(FindAngle( pos0, context->ArcData.pos1 )) ); } else if (context->ArcData.type == curveTypeNone) { DYNARR_RESET( trkSeg_t, tempSegs_da ); context->message( _("Back") ); } else if (context->ArcData.type == curveTypeCurve) { tempSegs(0).type = SEG_CRVLIN; tempSegs(0).u.c.center = context->ArcData.curvePos; tempSegs(0).u.c.radius = context->ArcData.curveRadius; tempSegs(0).u.c.a0 = context->ArcData.a0; tempSegs(0).u.c.a1 = context->ArcData.a1; d = D2R(context->ArcData.a1); if (d < 0.0) { d = 2*M_PI+d; } if ( d*context->ArcData.curveRadius > mapD.size.x+mapD.size.y ) { ErrorMessage( MSG_CURVE_TOO_LARGE ); DYNARR_RESET( trkSeg_t, tempSegs_da ); context->ArcData.type = curveTypeNone; return C_CONTINUE; } context->message( _("Curved Line: Radius=%s Angle=%0.3f Length=%s"), FormatDistance(context->ArcData.curveRadius), context->ArcData.a1, FormatDistance(context->ArcData.curveRadius*d) ); if (context->Op == OP_CURVE1 || context->Op == OP_CURVE4 ) { DrawArrowHeadsArray(&anchors_da,pos1,FindAngle(context->ArcData.curvePos,pos), TRUE,wDrawColorRed); } else if (context->Op == OP_CURVE2 || context->Op == OP_CURVE3 ) { CreateEndAnchor(context->ArcData.pos2,FALSE); DrawArrowHeadsArray(&anchors_da,context->ArcData.pos2, FindAngle(context->ArcData.curvePos,context->ArcData.pos2)+90,TRUE, wDrawColorRed); } CreateEndAnchor(context->ArcData.curvePos,TRUE); } } if (anchors_da.cnt == 0) { CreateEndAnchor(pos, FALSE); } break; case OP_CIRCLE1: case OP_FILLCIRCLE1: break; case OP_CIRCLE2: case OP_FILLCIRCLE2: tempSegs(0).u.c.center = pos1; if (context->State == 1 && locked) { CreateEndAnchor(pos1, FALSE); } else { wSetCursor(mainD.d,defaultCursor); } tempSegs(0).u.c.radius = FindDistance( pos0, pos1 ); context->message( _("Radius = %s"), FormatDistance(FindDistance( pos0, pos1 )) ); break; case OP_CIRCLE3: case OP_FILLCIRCLE3: if (context->State == 1) { CreateEndAnchor(pos0, TRUE); } wSetCursor(mainD.d,defaultCursor); tempSegs(0).u.c.radius = FindDistance( pos0, pos1 ); context->message( _("Radius = %s"), FormatDistance(FindDistance( pos0, pos1 )) ); break; case OP_BOX: case OP_FILLBOX: DYNARR_SET( trkSeg_t, tempSegs_da, 4 ); tempSegs(0).u.l.pos[1].x = tempSegs(1).u.l.pos[0].x = tempSegs(1).u.l.pos[1].x = tempSegs(2).u.l.pos[0].x = pos1.x; tempSegs(1).u.l.pos[1].y = tempSegs(2).u.l.pos[0].y = tempSegs(2).u.l.pos[1].y = tempSegs(3).u.l.pos[0].y = pos1.y; if (locked) { CreateEndAnchor(pos1,FALSE); } context->message( _("Width = %s, Height = %s"), FormatDistance(fabs(pos1.x - pos0.x)), FormatDistance(fabs(pos1.y - pos0.y)) ); break; } wSetCursor(mainD.d,wCursorNone); return C_CONTINUE; case wActionLUp: case wActionRUp: // lastValid = FALSE; // createTrack = FALSE; //Note - pos1 is last drag point wSetCursor(mainD.d,defaultCursor); if ((context->Op == OP_POLY) || (context->Op == OP_POLYLINE) || (context->Op == OP_FILLPOLY ) || (context->Op == OP_BOX) || (context->Op == OP_FILLBOX) ) { ; } else if (context->Op == OP_LINE || context->Op == OP_DIMLINE || context->Op == OP_BENCH || context->Op == OP_TBLEDGE ) { tempSegs(0).u.l.pos[1] = pos1; } else if ((context->Op>=OP_FILLCIRCLE1 && context->Op<=OP_FILLCIRCLE3) || (context->Op>=OP_CIRCLE1 && context->Op<=OP_CIRCLE3)) { ; } else { PlotCurve( drawGeomCurveMode, pos0, pos0x, pos1, &context->ArcData, FALSE, 0.0 ); if (context->ArcData.type == curveTypeStraight) { DYNARR_SET(trkSeg_t,tempSegs_da,1); tempSegs(0).type = SEG_STRLIN; tempSegs(0).u.l.pos[0] = pos0; tempSegs(0).u.l.pos[1] = context->ArcData.pos1; } else if (context->ArcData.type == curveTypeNone) { DYNARR_RESET(trkSeg_t,tempSegs_da); } else if (context->ArcData.type == curveTypeCurve) { DYNARR_SET(trkSeg_t,tempSegs_da,1); tempSegs(0).type = SEG_CRVLIN; tempSegs(0).u.c.center = context->ArcData.curvePos; tempSegs(0).u.c.radius = context->ArcData.curveRadius; tempSegs(0).u.c.a0 = context->ArcData.a0; tempSegs(0).u.c.a1 = context->ArcData.a1; } } switch ( context->Op ) { case OP_LINE: case OP_DIMLINE: case OP_BENCH: case OP_TBLEDGE: // lastValid = TRUE; lastPos = pos1; context->length = FindDistance(pos1,pos0); context->angle = FindAngle(pos0,pos1); context->State = 2; segCnt = tempSegs_da.cnt; break; case OP_CURVE1: case OP_CURVE2: case OP_CURVE3: case OP_CURVE4: if (context->State == 0) { context->State = 1; context->ArcAngle = FindAngle( pos0, pos1 ); pos0x = pos1; CreateCurve( C_UP, pos, FALSE, lineColor, lineWidth, drawGeomCurveMode, &anchors_da, context->message ); context->message( _("Drag on Red arrows to adjust curve") ); context->show = FALSE; return C_CONTINUE; } else { DYNARR_SET(trkSeg_t,tempSegs_da,1); if (context->ArcData.type == curveTypeCurve) { segPtr = &tempSegs(0); segPtr->type = SEG_CRVLIN; segPtr->color = lineColor; segPtr->lineWidth = lineWidth; segPtr->u.c.center = context->ArcData.curvePos; segPtr->u.c.radius = context->ArcData.curveRadius; segPtr->u.c.a0 = context->ArcData.a0; segPtr->u.c.a1 = context->ArcData.a1; context->radius = context->ArcData.curveRadius; context->angle = context->ArcData.a1; } else if (context->ArcData.type == curveTypeStraight) { segPtr = &tempSegs(0); segPtr->type = SEG_STRLIN; segPtr->color = lineColor; segPtr->lineWidth = lineWidth; segPtr->u.l.pos[0] = pos0; segPtr->u.l.pos[1] = pos1; context->radius = 0; context->length = FindDistance(pos0,pos1); context->angle = FindAngle(pos0,pos1); } // lastValid = TRUE; lastPos = pos1; context->State = 2; if (context->Op == OP_CURVE1 || context->Op == OP_CURVE4 ) { DrawArrowHeadsArray(&anchors_da,pos1,FindAngle(context->ArcData.curvePos,pos), TRUE,wDrawColorRed); } else if (context->Op == OP_CURVE2 || context->Op == OP_CURVE3 ) { CreateEndAnchor(context->ArcData.pos2,FALSE); DrawArrowHeadsArray(&anchors_da,context->ArcData.pos2, FindAngle(context->ArcData.curvePos,context->ArcData.pos2)+90,TRUE, wDrawColorRed); } CreateEndAnchor(context->ArcData.curvePos,TRUE); /*drawContext = context; DrawGeomOp( I2VP(context->Op) );*/ } break; case OP_CIRCLE1: case OP_CIRCLE2: case OP_CIRCLE3: case OP_FILLCIRCLE1: case OP_FILLCIRCLE2: case OP_FILLCIRCLE3: DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); if ( context->Op>=OP_FILLCIRCLE1 && context->Op<=OP_FILLCIRCLE3 ) { tempSegs(0).type = SEG_FILCRCL; } context->State = 2; context->radius = tempSegs(0).u.c.radius; break; case OP_BOX: case OP_FILLBOX: pts = (pts_t*)MyMalloc( 4 * sizeof (pts_t) ); for ( inx=0; inx<4; inx++ ) { pts[inx].pt = tempSegs(inx).u.l.pos[0]; pts[inx].pt_type = wPolyLineStraight; } DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); tempSegs(0).type = (context->Op == OP_FILLBOX)?SEG_FILPOLY:SEG_POLY; tempSegs(0).u.p.cnt = 4; tempSegs(0).u.p.pts = pts; tempSegs(0).u.p.angle = 0.0; tempSegs(0).u.p.orig = zero; tempSegs(0).u.p.polyType = RECTANGLE; /*drawContext = context; DrawGeomOp( I2VP(context->Op) );*/ context->length = FindDistance(pts[0].pt,pts[1].pt); context->width = FindDistance(pts[3].pt,pts[0].pt); context->State = 2; segCnt = tempSegs_da.cnt; break; case OP_POLY: case OP_FILLPOLY: case OP_POLYLINE: DYNARR_SET( trkSeg_t, tempSegs_da, segCnt ); DYNARR_RESET( trkSeg_t, anchors_da ); //End if close to start if ( segCnt>2 && IsClose(FindDistance(tempSegs(0).u.l.pos[0], pos))) { EndPoly(context, tempSegs_da.cnt, context->Op==OP_POLYLINE); DYNARR_RESET(pts_t, points_da); CleanSegs(&tempSegs_da); context->State = 0; segCnt = 0; return C_TERMINATE; } //If too short, remove last segment if (IsClose(FindDistance(tempSegs(segCnt-1).u.l.pos[0],pos))) { if (tempSegs_da.cnt>1) { --tempSegs_da.cnt; segCnt = tempSegs_da.cnt; wBeep(); } else { //First spot only tempSegs(0).color = wDrawColorRed; tempSegs(0).type = SEG_CRVLIN; tempSegs(0).u.c.a1 = 360; tempSegs(0).u.c.radius = tempD.scale*0.15/2; tempSegs(0).u.c.center = pos; segCnt = tempSegs_da.cnt; } return C_CONTINUE; } int text_inx = tempSegs_da.cnt-1; //tempSegs(tempSegs_da.cnt-1).u.l.pos[1] = pos; context->length = FindDistance(tempSegs(text_inx).u.l.pos[0], tempSegs(text_inx).u.l.pos[1]); if (text_inx>1) { ANGLE_T an = FindAngle(tempSegs(text_inx-1).u.l.pos[0], tempSegs(text_inx-1).u.l.pos[1]); context->angle = NormalizeAngle(FindAngle(tempSegs(text_inx).u.l.pos[0], tempSegs(text_inx).u.l.pos[1])-an); } else { context->angle = FindAngle(tempSegs(1).u.l.pos[0],tempSegs(1).u.l.pos[1]); } context->State = 1; context->index = text_inx; segCnt = tempSegs_da.cnt; return C_CONTINUE; } context->Started = FALSE; /*CheckOk();*/ if (context->State == 2 && IsCurCommandSticky()) { segCnt = tempSegs_da.cnt; UndoStart("Create Lines","Sticky Draw"); context->UndoStarted = TRUE; return C_CONTINUE; } DrawGeomOk(FALSE); context->State = 0; context->Changed = FALSE; context->message(""); return C_TERMINATE; case wActionText: DYNARR_RESET(trkSeg_t, anchors_da ); int key = (action>>8&0xFF); if ( key == 0x0D || key == ' ' || (key == 0x09 && ((MyGetKeyState() & (WKEY_SHIFT|WKEY_CTRL|WKEY_ALT)) != WKEY_SHIFT))) { //Tab continue if ((context->Op == OP_POLY) || (context->Op == OP_FILLPOLY) || (context->Op == OP_POLYLINE)) { DYNARR_SET( trkSeg_t, tempSegs_da, segCnt ); //If last segment wasn't just a point, add another starting on its end if (!IsClose(FindDistance(tempSegs(segCnt-1).u.l.pos[0], tempSegs(segCnt-1).u.l.pos[1]))) { DYNARR_APPEND(trkSeg_t,tempSegs_da,1); segPtr = &DYNARR_LAST( trkSeg_t, tempSegs_da ); segPtr->type = SEG_STRLIN; segPtr->u.l.pos[0] = segPtr[-1].u.l.pos[1]; segPtr->u.l.pos[1] = tempSegs(0).u.l.pos[0]; } EndPoly(context, tempSegs_da.cnt, context->Op == OP_POLYLINE); DYNARR_RESET(pts_t, points_da); DYNARR_RESET(trkSeg_t,tempSegs_da); } else { if (context->State == 2) { DYNARR_SET( trkSeg_t, tempSegs_da, segCnt ); DrawGeomOk(context->UndoStarted); context->UndoStarted = FALSE; } } context->State = 0; segCnt = 0; if (key == 0x0D) { return C_CONTINUE; } //Esc - go to Reset else { return C_TERMINATE; } //Space/Enter/Tab - end command } else if (key == 0x09 && ((MyGetKeyState() & (WKEY_SHIFT|WKEY_CTRL|WKEY_ALT)) == WKEY_SHIFT)) { //Tab plus shift - abandon context->State = 0; segCnt = 0; return C_TERMINATE; } return C_CONTINUE; case C_CONFIRM: if (context->State==2 && IsCurCommandSticky()) { DrawGeomOk(context->UndoStarted); } context->Changed = FALSE; return C_CONTINUE; case C_CANCEL: DYNARR_RESET(trkSeg_t, anchors_da ); DYNARR_RESET( trkSeg_t, tempSegs_da ); context->message( "" ); context->Changed = FALSE; context->State = 0; segCnt = 0; // lastValid = FALSE; return C_TERMINATE; case C_REDRAW: DrawSegsDA( &tempD, NULL, zero, 0.0, &tempSegs_da, trackGauge, wDrawColorBlack, 0 ); DrawSegsDA( &tempD, NULL, zero, 0.0, &anchors_da, 0.0, wDrawColorBlack, 0 ); return C_CONTINUE; case C_CMDMENU: return C_CONTINUE; default: return C_CONTINUE; } } static int polyInx; static int lineInx; static int curveInx; typedef enum {POLY_NONE, POLY_SELECTED, POLYPOINT_SELECTED} PolyState_e; static PolyState_e polyState = POLY_NONE; static coOrd rotate_origin; static ANGLE_T rotate_angle; //static dynArr_t origin_da; void static CreateCircleAnchor(wBool_t selected,coOrd center, DIST_T rad, ANGLE_T angle) { DYNARR_RESET(trkSeg_t,anchors_da); double d = tempD.scale*0.15; DYNARR_APPEND(trkSeg_t,anchors_da,2); anchors(0).type = (selected)?SEG_FILCRCL:SEG_CRVLIN; anchors(0).u.c.a1 = 360.0; anchors(0).color = wDrawColorBlue; anchors(0).u.c.radius = d/2; PointOnCircle(&anchors(0).u.c.center,center,rad,angle); } void static CreateLineAnchors(int index, coOrd p0, coOrd p1) { DYNARR_RESET(trkSeg_t,anchors_da); double d = tempD.scale*0.15; DYNARR_APPEND(trkSeg_t,anchors_da,2); anchors(0).type = (index ==0)?SEG_FILCRCL:SEG_CRVLIN; anchors(0).u.c.a1 = 360.0; anchors(0).color = wDrawColorBlue; anchors(0).u.c.radius = d/2; anchors(0).u.c.center = p0; DYNARR_APPEND(trkSeg_t,anchors_da,1); anchors(1).type = (index ==1)?SEG_FILCRCL:SEG_CRVLIN; anchors(1).u.c.a1 = 360.0; anchors(1).color = wDrawColorBlue; anchors(1).u.c.radius = d/2; anchors(1).u.c.center = p1; if (index>=0) { wSetCursor(mainD.d,wCursorNone); } } void static CreateBoxAnchors(int index, pts_t pt[4]) { DYNARR_RESET(trkSeg_t,anchors_da); // double d = tempD.scale*0.15; ANGLE_T a = FindAngle(pt[0].pt,pt[1].pt); ANGLE_T diag = FindAngle(pt[0].pt,pt[2].pt); if (index>=0) { wSetCursor(mainD.d,wCursorNone); } for (int i=0; i<4; i++) { DYNARR_SET(trkSeg_t,anchors_da,anchors_da.cnt+5); DrawArrowHeads(&DYNARR_N(trkSeg_t,anchors_da,anchors_da.cnt-5),pt[i].pt, (diag>a?45.0:-45.0)+a+(90.0*(i)),TRUE,i==index?wDrawColorRed:wDrawColorBlue); } coOrd pp; for (int i=0; i<4; i++) { pp.x = (i==3?((((pt[0].pt.x - pt[i].pt.x)/2))+pt[i].pt.x):(( pt[i+1].pt.x - pt[i].pt.x)/2)+pt[i].pt.x); pp.y = (i==3?((((pt[0].pt.y - pt[i].pt.y)/2))+pt[i].pt.y):(( pt[i+1].pt.y - pt[i].pt.y)/2)+pt[i].pt.y); DYNARR_SET(trkSeg_t,anchors_da,anchors_da.cnt+5); DrawArrowHeads(&DYNARR_N(trkSeg_t,anchors_da,anchors_da.cnt-5),pp,90.0*(i-1)+a, TRUE,i==index+5?wDrawColorRed:wDrawColorBlue); } } void static CreateOriginAnchor(coOrd origin, wBool_t trans_selected) { double d = tempD.scale*0.15; DYNARR_APPEND(trkSeg_t,anchors_da,2); int i = anchors_da.cnt-1; coOrd p0,p1; Translate(&p0,origin,0,d*4); Translate(&p1,origin,0,-d*4); anchors(i).type = SEG_STRLIN; anchors(i).u.l.pos[0] = p0; anchors(i).u.l.pos[1] = p1; anchors(i).color = trans_selected?wDrawColorAqua:wDrawColorBlue; anchors(i).lineWidth = 0; DYNARR_APPEND(trkSeg_t,anchors_da,1); Translate(&p0,origin,90,d*4); Translate(&p1,origin,90,-d*4); i = anchors_da.cnt-1; anchors(i).type = SEG_STRLIN; anchors(i).u.l.pos[0] = p0; anchors(i).u.l.pos[1] = p1; anchors(i).color = wDrawColorBlue; anchors(i).lineWidth = 0; if (trans_selected) { wSetCursor(mainD.d,wCursorNone); } } void static CreateCurveAnchors(int index, coOrd pm, coOrd pc, coOrd p0, coOrd p1) { DYNARR_RESET(trkSeg_t,anchors_da); double d = tempD.scale*0.15; DYNARR_APPEND(trkSeg_t,anchors_da,9); anchors(0).type = (index ==0)?SEG_FILCRCL:SEG_CRVLIN; anchors(0).u.c.a1 = 360.0; anchors(0).color = wDrawColorBlue; anchors(0).u.c.radius = d/2; anchors(0).u.c.center = p0; anchors(0).lineWidth = 0; DYNARR_APPEND(trkSeg_t,anchors_da,8); anchors(1).type = (index ==1)?SEG_FILCRCL:SEG_CRVLIN; anchors(1).u.c.a1 = 360.0; anchors(1).color = wDrawColorBlue; anchors(1).u.c.radius = d/2; anchors(1).u.c.center = p1; anchors(1).lineWidth = 0; DYNARR_SET(trkSeg_t,anchors_da,anchors_da.cnt+5); DrawArrowHeads(&DYNARR_N(trkSeg_t,anchors_da,anchors_da.cnt-5),pm,FindAngle(pm, pc),TRUE,index==2?wDrawColorAqua:wDrawColorBlue); if (index>=0) { wSetCursor(mainD.d,wCursorNone); } else { wSetCursor(mainD.d,defaultCursor); } } void static CreatePolyAnchors(int index) { DYNARR_RESET(trkSeg_t,anchors_da); double d = tempD.scale*0.15; for ( int inx=0; inx=0) { DYNARR_APPEND(trkSeg_t,anchors_da,1); int inx = anchors_da.cnt-1; anchors(inx).type = SEG_STRLIN; anchors(inx).u.l.pos[0] = points(index==0?points_da.cnt-1:index-1).pt; anchors(inx).u.l.pos[1] = points(index).pt; anchors(inx).color = wDrawColorBlue; anchors(inx).lineWidth = 0; DYNARR_APPEND(trkSeg_t,anchors_da,1); inx = anchors_da.cnt-1; int index0 = index==0?points_da.cnt-1:index-1; ANGLE_T an0 = FindAngle(points(index0).pt, points(index).pt); ANGLE_T an1 = FindAngle(points(index0==0?points_da.cnt-1:index0-1).pt, points(index0).pt); anchors(inx).type = SEG_CRVLIN; if (DifferenceBetweenAngles(an0,an1)<=0) { anchors(inx).u.c.a1 = DifferenceBetweenAngles(an0,an1)-180; anchors(inx).u.c.a0 = an0; } else { anchors(inx).u.c.a1 = 180-DifferenceBetweenAngles(an0,an1); anchors(inx).u.c.a0 = NormalizeAngle(180+an1); } anchors(inx).color = wDrawColorBlue; anchors(inx).u.c.radius = d; anchors(inx).u.c.center = points(index0).pt; } } void CreateMovingAnchor(coOrd pos,BOOL_T fill) { double d = tempD.scale*0.15; DYNARR_APPEND(trkSeg_t,anchors_da,1); int inx = anchors_da.cnt-1; anchors(inx).type = fill?SEG_FILCRCL:SEG_CRVLIN; anchors(inx).u.c.a0 = 0.0; anchors(inx).u.c.a1 = 360.0; anchors(inx).lineWidth = 0; anchors(inx).color = wDrawColorBlue; anchors(inx).u.c.radius = d/4; anchors(inx).u.c.center = pos; wSetCursor(mainD.d,wCursorNone); } /* * Modify Polygons. Polygons have a variable number of nodes. * * Each point has an anchor and selecting the node allows it to be moved * Selecting a point between nodes adds a node ready for dragging * The last selected node can be deleted * */ static STATUS_T DrawGeomPolyModify( wAction_t action, coOrd pos, drawModContext_t *context) { double d; static int selected_count; static int segInx; static int prev_inx; // static wDrawColor save_color; // static wBool_t drawnAngle; // static double currentAngle; // static double baseAngle; // static BOOL_T lock; switch ( action&0xFF ) { case C_START: // lock = FALSE; DistanceSegs( context->orig, context->angle, context->segCnt, context->segPtr, &pos, &segInx ); if (segInx == -1) { return C_ERROR; } if (context->type != SEG_POLY && context->type != SEG_FILPOLY) { return C_ERROR; } prev_inx = -1; polyState = POLY_SELECTED; polyInx = -1; //Copy points DYNARR_RESET( pts_t, points_da); DYNARR_RESET( wBool_t, select_da); for (int inx=0; inxsegPtr->u.p.cnt; inx++) { DYNARR_APPEND(pts_t, points_da,3); DYNARR_APPEND(wBool_t,select_da,3); REORIGIN( points(inx).pt, context->segPtr[segInx].u.p.pts[inx].pt, context->angle, context->orig ); points(inx).pt_type = context->segPtr[segInx].u.p.pts[inx].pt_type; point_selected(inx) = FALSE; } context->prev_inx = -1; context->max_inx = points_da.cnt-1; selected_count=0; rotate_origin = context->orig; rotate_angle = context->angle; context->p0 = points(0).pt; context->p1 = points(1).pt; //Show points DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); tempSegs(0).lineWidth = context->segPtr->lineWidth; // save_color = context->segPtr->color; tempSegs(0).color = wDrawColorRed; tempSegs(0).type = context->type; tempSegs(0).u.p.cnt = context->segPtr[segInx].u.p.cnt; tempSegs(0).u.p.angle = 0.0; tempSegs(0).u.p.orig = zero; tempSegs(0).u.p.polyType = context->segPtr[segInx].u.p.polyType; tempSegs(0).u.p.pts = &points(0); CreatePolyAnchors( -1); InfoMessage(_("Select points or use context menu")); ClrAllTrkBitsRedraw( TB_UNDRAWN, TRUE ); UndrawNewTrack( context->trk ); return C_CONTINUE; case wActionMove: DYNARR_RESET(trkSeg_t,anchors_da); CreatePolyAnchors(context->prev_inx); for (int i = 0; i ddm ) { dm = ddm; pm1 = pm0; pInx = inx; } } if (!IsClose(dm)) { return C_CONTINUE; } int inxm = pInx==0?points_da.cnt-1:pInx-1; dm = FindDistance( points(inxm).pt, pm1 ); DIST_T ddm = FindDistance( points(inxm).pt, points(pInx).pt ); if ( (dm > 0.25*ddm) && (dm < 0.75*ddm)) { CreateMovingAnchor(pm1,FALSE); } else { if (dm < FindDistance( points(pInx).pt, pm1 )) { CreateMovingAnchor(points(inxm).pt,TRUE); } else { CreateMovingAnchor(points(pInx).pt,TRUE); } } return C_CONTINUE; break; case C_DOWN: d = DIST_INF; polyInx = -1; coOrd p0; double dd; int inx; if ((MyGetKeyState() & (WKEY_SHIFT|WKEY_CTRL|WKEY_ALT)) != WKEY_SHIFT) { if (selected_count <2 ) { //Wipe out selection(s) if we don't have multiple already (i,e. move with >1 selected) for (int i=0; i dd ) { d = dd; polyInx = inx; } } if (!IsClose(d)) { //Not on/near object - de-select all points for (int i=0; iprev_inx = -1; return C_CONTINUE; //Not close to any line } polyState = POLYPOINT_SELECTED; inx = polyInx==0?points_da.cnt-1:polyInx-1; //Find if the point is to be added d = FindDistance( points(inx).pt, pos ); dd = FindDistance( points(inx).pt, points(polyInx).pt ); if ( d < 0.25*dd ) { polyInx = inx; } else if ( d > 0.75*dd ) { ; } else { if (selected_count == 0) { //Only add a new point if no points are already selected! DYNARR_APPEND(wBool_t,select_da,1); for (int i=0; ipolyInx; inx-- ) { points(inx) = points(inx-1); } points(polyInx).pt_type = wPolyLineStraight; tempSegs(0).u.p.cnt = points_da.cnt; context->max_inx = points_da.cnt-1; } } //If already selected (multiple points), not using shift (to add) select, and on object move to first point if (selected_count>0 && ((MyGetKeyState() & (WKEY_SHIFT|WKEY_CTRL|WKEY_ALT)) != WKEY_SHIFT)) { for (int i=0; i0 && selected_count < points_da.cnt-2) { for (int i=0; i=0) { if (first_inx == 0) { last_inx = points_da.cnt-1; } else { last_inx = first_inx-1; } // if (first_inx == points_da.cnt-1) { // next_inx = 0; // } else { // next_inx = first_inx+1; // } context->length = FindDistance(points(last_inx).pt,points(first_inx).pt); an1 = FindAngle(points(last_inx).pt,points(first_inx).pt); an0 = FindAngle(points(last_inx==0?(points_da.cnt-1):(last_inx-1)).pt, points(last_inx).pt); if (DifferenceBetweenAngles(an0,an1)<=0) { context->rel_angle = 180+DifferenceBetweenAngles(an0,an1); } else { context->rel_angle = 180-DifferenceBetweenAngles(an0,an1); } } else { } context->prev_inx = first_inx; context->p0 = points(0).pt; context->p1 = points(1).pt; //Show three anchors only CreatePolyAnchors(first_inx); return C_CONTINUE; case C_LDOUBLE: return C_CONTINUE; case C_MOVE: DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); if (polyState != POLYPOINT_SELECTED) { return C_CONTINUE; } //Moving with Point Selected if (polyInx<0) { return C_ERROR; } first_inx = -1; if (selected_count >0 && selected_count < points_da.cnt-2) { for (int i=0; i=0) { if (first_inx == 0) { last_inx = points_da.cnt-1; } else { last_inx = first_inx-1; } // if (first_inx == points_da.cnt-1) { // next_inx = 0; // } else { // next_inx = first_inx+1; // } //Lock to 90 degrees first/last point if ((MyGetKeyState() & (WKEY_SHIFT|WKEY_CTRL|WKEY_ALT)) == WKEY_CTRL ) { ANGLE_T last_angle; // ANGLE_T next_angle; coOrd last_point,next_point; if (first_inx == 0) { last_point = points(points_da.cnt-1).pt; last_angle = FindAngle(points(points_da.cnt-2).pt,last_point); } else if (first_inx == 1) { last_point = points(0).pt; last_angle = FindAngle(points(points_da.cnt-1).pt,last_point); } else { last_point = points(first_inx-1).pt; last_angle = FindAngle(points(first_inx-2).pt,last_point); } if (first_inx == points_da.cnt-1) { next_point = points(0).pt; // next_angle = FindAngle(next_point,points(1).pt); } else if (first_inx == points_da.cnt-2) { next_point = points(points_da.cnt-1).pt; // next_angle = FindAngle(next_point,points(0).pt); } else { next_point = points(first_inx+1).pt; // next_angle = FindAngle(next_point,points(first_inx+2).pt); } coOrd diff; diff.x = pos.x - points(polyInx).pt.x; diff.y = pos.y - points(polyInx).pt.y; coOrd pos_lock = points(first_inx).pt; pos_lock.x += diff.x; pos_lock.y += diff.y; //Snap to Right-Angle from previous or from 0 DIST_T l = FindDistance(last_point, pos_lock); ANGLE_T angle2 = NormalizeAngle(FindAngle(last_point, pos_lock)-last_angle); int quad = (int)((angle2+45.0)/90.0); if (tempSegs_da.cnt != 1 && (quad == 2)) { pos_lock = last_point; } else if (quad == 1 || quad == 3) { l = fabs(l*cos(D2R(((quad==1)?last_angle+90.0:last_angle-90.0)-FindAngle( pos_lock,last_point)))); Translate( &pos_lock, last_point, NormalizeAngle((quad==1)?last_angle+90.0:last_angle-90.0), l ); } else { l = fabs(l*cos(D2R(((quad==0 ||quad==4)?last_angle:last_angle+180.0)-FindAngle(pos_lock,last_point)))); Translate( &pos_lock, last_point, NormalizeAngle((quad==0 ||quad==4)?last_angle:last_angle+180.0), l ); } diff.x = pos_lock.x - points(first_inx).pt.x; diff.y = pos_lock.y - points(first_inx).pt.y; pos.x = points(polyInx).pt.x+diff.x; pos.y = points(polyInx).pt.y+diff.y; if (selected_count<2) { if (FindIntersection(&intersect,last_point,last_angle+90.0,next_point, last_angle+180.0)) { show_intersect = TRUE; } } d = FindDistance(intersect,pos_lock); if (IsClose(d)) { pos = intersect; } InfoMessage( _("Length = %s, Last angle = %0.2f"), FormatDistance(FindDistance(pos_lock,last_point)), PutAngle(FindAngle(pos_lock,last_point))); } else { SnapPos(&pos); } //If not using CTL and snap enabled } context->prev_inx = first_inx; coOrd diff; diff.x = pos.x - points(polyInx).pt.x; diff.y = pos.y - points(polyInx).pt.y; //points(polyInx) = pos; for (int i=0; i=0) { context->length = FindDistance(points(first_inx).pt,points(last_inx).pt); an1 = FindAngle(points(last_inx).pt,points(first_inx).pt); an0 = FindAngle(points(first_inx==0?(points_da.cnt-1):(first_inx-1)).pt, points(first_inx).pt); context->rel_angle = NormalizeAngle(180-(an1-an0)); } CreatePolyAnchors(first_inx); if (show_intersect) { CreateSquareAnchor(intersect); } context->p0 = points(0).pt; context->p1 = points(1).pt; return C_CONTINUE; case C_UP: context->prev_inx = -1; if (segInx == -1 || polyState != POLYPOINT_SELECTED) { return C_CONTINUE; //Didn't get a point selected/added } polyState = POLY_SELECTED; //Return to base state DYNARR_RESET( trkSeg_t, anchors_da ); CreatePolyAnchors(polyInx); //Show last selection prev_inx = polyInx; for (int i=0; i=0) { context->length = FindDistance(points(first_inx).pt,points(last_inx).pt); an1 = FindAngle(points(last_inx).pt,points(first_inx).pt); an0 = FindAngle(points(last_inx==0?(points_da.cnt-1):(last_inx-1)).pt, points(last_inx).pt); if (DifferenceBetweenAngles(an0,an1)<=0) { context->rel_angle = 180+DifferenceBetweenAngles(an0,an1); } else { context->rel_angle = 180-DifferenceBetweenAngles(an0,an1); } } context->prev_inx = first_inx; context->p0 = points(0).pt; context->p1 = points(1).pt; polyInx = -1; return C_CONTINUE; case C_UPDATE: if (context->prev_inx>=0) { int last_index = context->prev_inx==0?(points_da.cnt-1):(context->prev_inx-1); an0 = FindAngle(points(last_index==0?(points_da.cnt-1):(last_index-1)).pt, points(last_index).pt); an1 = FindAngle(points(last_index).pt,points(context->prev_inx).pt); if (DifferenceBetweenAngles(an0,an1)<=0) { an1 = NormalizeAngle(an0-(180-context->rel_angle)); } else { an1 = NormalizeAngle((180-context->rel_angle)+an0); } Translate(&points(prev_inx).pt,points(last_index).pt,an1,context->length); } context->rel_angle = fabs(context->rel_angle); if (context->rel_angle >180) { context->rel_angle = context->rel_angle - 180.0; } CreatePolyAnchors(prev_inx); context->p0 = points(0).pt; context->p1 = points(1).pt; break; case C_TEXT: DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); if (action>>8 == 'o') { //"o" -> origin mode MenuMode(I2VP(1)); InfoMessage("Move Origin Mode: Place Origin, p for Points, Enter or Esc"); return C_CONTINUE; } if (((prev_inx>=0 && tempSegs(0).u.p.polyType != POLYLINE) || ((tempSegs(0).u.p.polyType == POLYLINE) && (prev_inx>=1) && (prev_inx<=points_da.cnt-2)) ) && ((action>>8 == 's') || (action>>8 == 'v') || (action>>8 == 'r'))) { switch(action>>8) { case 's': points(context->prev_inx).pt_type = wPolyLineSmooth; return C_CONTINUE; case 'v': points(context->prev_inx).pt_type = wPolyLineStraight; return C_CONTINUE; case 'r': points(context->prev_inx).pt_type = wPolyLineRound; return C_CONTINUE; default:; } } if ((action>>8 == 'g') && (tempSegs(0).type == SEG_POLY) && (tempSegs(0).u.p.polyType == POLYLINE) ) { tempSegs(0).u.p.polyType = FREEFORM; context->subtype=FREEFORM; context->open = FALSE; CreatePolyAnchors( -1); return C_CONTINUE; } if ((action>>8 == 'l') && (tempSegs(0).type == SEG_POLY) && (tempSegs(0).u.p.polyType != POLYLINE)) { tempSegs(0).u.p.polyType = POLYLINE; context->subtype=POLYLINE; context->open = TRUE; CreatePolyAnchors( -1); return C_CONTINUE; } if ((action>>8 == 'f') && (tempSegs(0).type == SEG_POLY) && (tempSegs(0).u.p.polyType != POLYLINE )) { tempSegs(0).type = SEG_FILPOLY; context->type = SEG_FILPOLY; context->subtype=tempSegs(0).u.p.polyType; context->filled = TRUE; CreatePolyAnchors( -1); return C_CONTINUE; } if ((action>>8 == 'u') && (tempSegs(0).type == SEG_FILPOLY) ) { tempSegs(0).type = SEG_POLY; context->type = SEG_POLY; context->subtype=tempSegs(0).u.p.polyType; context->filled = FALSE; CreatePolyAnchors( -1); return C_CONTINUE; } //Delete or backspace deletes last selected index if (action>>8 == 127 || action>>8 == 8) { if (polyState == POLY_SELECTED && prev_inx >=0) { if (selected_count >1) { ErrorMessage( MSG_POLY_MULTIPLE_SELECTED ); return C_CONTINUE; } if (points_da.cnt <= 3) { ErrorMessage( MSG_POLY_SHAPES_3_SIDES ); return C_CONTINUE; } for (int i=0; i=prev_inx && imax_inx = points_da.cnt-1; } else { ErrorMessage( MSG_POLY_NOTHING_SELECTED ); } prev_inx = -1; context->prev_inx = -1; polyInx = -1; polyState = POLY_SELECTED; CreatePolyAnchors( -1); InfoMessage(_("Point Deleted")); return C_CONTINUE; } if (action>>8 != 32 && action>>8 != 13 && action>>8 !=9) { return C_CONTINUE; } if (action>>8 == 9 && (MyGetKeyState() & WKEY_SHIFT) != 0) { return C_TERMINATE; } /* no break */ case C_CONFIRM: case C_OK: case C_FINISH: //copy changes back into track if (polyState != POLY_SELECTED) { polyState = POLY_NONE; DYNARR_RESET(trkSeg_t,anchors_da); DYNARR_RESET(trkSeg_t,tempSegs_da); return C_TERMINATE; } //If ends overlap precisely remove last segment and close if >3 points DIST_T dist = FindDistance(points(0).pt,points(points_da.cnt-1).pt); if (IsClose(dist*4) && points_da.cnt>3 && tempSegs(0).u.p.polyType == POLYLINE) { tempSegs(0).u.p.polyType = FREEFORM; context->subtype=FREEFORM; context->open = FALSE; points_da.cnt--; select_da.cnt--; selected_count=0; tempSegs(0).u.p.cnt = points_da.cnt; context->max_inx = points_da.cnt-1; } pts_t * oldPts = context->segPtr[segInx].u.p.pts; void * newPts = (pts_t*)MyMalloc( points_da.cnt * sizeof (pts_t) ); context->segPtr[segInx].u.p.pts = newPts; context->segPtr[segInx].u.p.cnt = points_da.cnt; context->orig = rotate_origin; context->angle = rotate_angle; for (int i=0; iorig.x; pos.y -= context->orig.y; Rotate( &pos, zero, -context->angle ); context->segPtr[segInx].u.p.pts[i].pt = pos; context->segPtr[segInx].u.p.pts[i].pt_type = points(i).pt_type; } MyFree(oldPts); polyState = POLY_NONE; DYNARR_RESET(trkSeg_t,anchors_da); DYNARR_RESET(trkSeg_t,points_da); DYNARR_RESET(trkSeg_t,tempSegs_da); if ((action&0xFF)==C_CONFIRM) { return C_CONTINUE; } else { return C_TERMINATE; } case C_REDRAW: if (polyState == POLY_NONE) { return C_CONTINUE; } DrawSegsDA( &tempD, NULL, zero, 0.0, &tempSegs_da, trackGauge, wDrawColorBlack, 0 ); DrawSegsDA( &tempD, NULL, zero, 0.0, &anchors_da, trackGauge, wDrawColorBlack, 0 ); break; default: ; } return C_CONTINUE; } void BuildCircleContext(drawModContext_t * context,int segInx) { context->radius = fabs(context->segPtr[segInx].u.c.radius); REORIGIN( context->pc, context->segPtr[segInx].u.c.center, context->angle, context->orig ); PointOnCircle( &context->p0, context->segPtr[segInx].u.c.center, fabs(context->segPtr[segInx].u.c.radius), context->segPtr[segInx].u.c.a0 ); REORIGIN( context->p0, context->p0, context->angle, context->orig ); PointOnCircle( &context->p1, context->segPtr[segInx].u.c.center, fabs(context->segPtr[segInx].u.c.radius), context->segPtr[segInx].u.c.a0 + context->segPtr[segInx].u.c.a1); REORIGIN( context->p1, context->p1, context->angle, context->orig ); if (context->segPtr[segInx].u.c.a1<360) { context->arc_angle = context->segPtr[segInx].u.c.a1; PointOnCircle( &context->pm, context->segPtr[segInx].u.c.center, fabs(context->segPtr[segInx].u.c.radius), context->segPtr[segInx].u.c.a0 + (context->segPtr[segInx].u.c.a1/2)); REORIGIN( context->pm, context->pm, context->angle, context->orig ); coOrd cm; cm = context->pm; ANGLE_T a = FindAngle(context->p1,context->p0); Rotate(&cm,context->p1,-a ); context->disp = cm.x-context->p1.x; } else { context->pm = context->p0; context->disp = 0; context->arc_angle = 360.0; } } void CreateSelectedAnchor(coOrd pos) { double d = tempD.scale*0.15; DYNARR_APPEND(trkSeg_t,anchors_da,1); int inx = anchors_da.cnt-1; anchors(inx).type = SEG_FILCRCL; anchors(inx).u.c.a0 = 0.0; anchors(inx).u.c.a1 = 360.0; anchors(inx).color = wDrawColorBlue; anchors(inx).u.c.radius = d/2; anchors(inx).u.c.center = pos; } /* * Rotate Object Dialogs. * * Each Draw object has a rotation origin which all the points are offset from. * Formerly this has been set to the origin, but it doesn't have to be. By setting * to a point on the shape this allows assembly by aligning parts to a common point on a base object. * The angle is always set to zero when the Modify finishes but can be altered via Describe. * * First locate the origin, and then place a rotation arm which is (optionally) rotated about the origin. * Also supports whole object translate using translate anchor. **/ STATUS_T DrawGeomOriginMove( wAction_t action, coOrd pos, drawModContext_t * context) { switch ( action&0xFF ) { case C_START: context->state = MOD_ORIGIN; context->rotate_state = TRUE; context->rot_moved = TRUE; DYNARR_RESET(trkSeg_t,anchors_da); CreateOriginAnchor(context->rot_center,FALSE); if ((tempSegs(0).type == SEG_POLY || tempSegs(0).type == SEG_FILPOLY) && (context->prev_inx>=0)) { CreateSelectedAnchor(points(context->prev_inx).pt); } InfoMessage("Move Origin Mode: Place Origin, 0-4, c or l, Enter or Esc"); return C_CONTINUE; break; case wActionMove: CreateOriginAnchor(context->rot_center, FALSE); if ((tempSegs(0).type == SEG_POLY || tempSegs(0).type == SEG_FILPOLY) && (context->prev_inx>=0)) { CreateSelectedAnchor(points(context->prev_inx).pt); } return C_CONTINUE; break; case C_DOWN: if (context->state == MOD_ORIGIN || context->state == MOD_AFTER_ORIG) { context->state = MOD_ORIGIN; DYNARR_RESET(trkSeg_t,anchors_da); if (IsClose(FindDistance(pos,context->rot_center))) { pos = context->rot_center; } else { context->rot_center = pos; } CreateOriginAnchor(context->rot_center, TRUE); if ((tempSegs(0).type == SEG_POLY || tempSegs(0).type == SEG_FILPOLY) && (context->prev_inx>=0)) { CreateSelectedAnchor(points(context->prev_inx).pt); } } return C_CONTINUE; break; case C_MOVE: if (context->state == MOD_ORIGIN || context->state == MOD_AFTER_ORIG) { context->rot_center = pos; DYNARR_RESET(trkSeg_t,anchors_da); CreateOriginAnchor(context->rot_center, TRUE); if ((tempSegs(0).type == SEG_POLY || tempSegs(0).type == SEG_FILPOLY) && (context->prev_inx>=0)) { CreateSelectedAnchor(points(context->prev_inx).pt); } } return C_CONTINUE; break; case C_UP: DYNARR_RESET(trkSeg_t,anchors_da); if (context->state == MOD_ORIGIN) { context->state = MOD_AFTER_ORIG; } CreateOriginAnchor(context->rot_center,FALSE); if ((tempSegs(0).type == SEG_POLY || tempSegs(0).type == SEG_FILPOLY) && (context->prev_inx>=0)) { CreateSelectedAnchor(points(context->prev_inx).pt); } return C_CONTINUE; break; case C_UPDATE: DYNARR_RESET(trkSeg_t,anchors_da); if (context->state == MOD_AFTER_ORIG) { if (context->rot_center.x != context->rel_center.x && context->rot_center.y != context->rel_center.y ) { context->rel_center = context->rot_center; CreateOriginAnchor(context->rot_center, FALSE); if ((tempSegs(0).type == SEG_POLY || tempSegs(0).type == SEG_FILPOLY) && (context->prev_inx>=0)) { CreateSelectedAnchor(points(context->prev_inx).pt); } } } return C_CONTINUE; break; case C_TEXT: DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); if ((context->state == MOD_ORIGIN || context->state == MOD_AFTER_ORIG) && ((action>>8 >= '0' && action>>8 <= '1') || action>>8 == 'l' || action>>8 == 'm' || action>>8 == 'p')) { // 0,1,2,3,4 -> reset rot center if (action>>8 == '0') { context->rot_center = zero; } else if (action>>8 == '1') { context->rot_center = context->p0; } else if (action>>8 == '2') { context->rot_center = context->p1; } else if (tempSegs(0).type == SEG_POLY || tempSegs(0).type == SEG_FILPOLY) { if (action>>8 == '3' || action>>8 == '4') { context->rot_center = action>>8 == '3'?points(2).pt:points(3).pt; } else if (action>>8 == 'l') { //"l" - last selected if (context->prev_inx !=-1) { context->rot_center = points(context->prev_inx).pt; } } else if (action>>8 == 'm') { context->rot_center = FindCentroid(points_da.cnt,&points(0)); } } if (action>>8 == 'p') { //"p" - points mode MenuMode(I2VP(0)); return C_CONTINUE; } context->rel_center = context->rot_center; context->rot_angle = 0; DYNARR_RESET(trkSeg_t,anchors_da); context->state = MOD_AFTER_ORIG; CreateOriginAnchor(context->rot_center, FALSE); if ((tempSegs(0).type == SEG_POLY || tempSegs(0).type == SEG_FILPOLY) && (context->prev_inx>=0)) { CreateSelectedAnchor(points(context->prev_inx).pt); } return C_CONTINUE; } break; case C_FINISH: context->rotate_state = FALSE; context->state = MOD_STARTED; return C_CONTINUE; break; default: break; } return C_CONTINUE; } /* * Base Modify function for Draw objects. */ STATUS_T DrawGeomModify( wAction_t action, coOrd pos, drawModContext_t * context) { ANGLE_T a; coOrd p0, p1, pc, pm; static coOrd start_pos; static wIndex_t segInx; // static EPINX_T segEp; static ANGLE_T segA1; static int inx_line, inx_origin; // static int inx_other; static BOOL_T corner_mode; static BOOL_T polyMode; // static ANGLE_T original_angle; int inx, inx2; // int inx1; DIST_T d, d1, d2, dd; // coOrd * newPts = NULL; switch ( action&0xFF ) { case C_START: DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); if (!context->rotate_state && !context->rot_moved) { context->rot_center.x = context->orig.x; context->rot_center.y = context->orig.y; } context->state = MOD_STARTED; context->rotate_state = FALSE; context->last_inx=-1; lineInx = -1; curveInx = -1; segInx = -1; polyMode = FALSE; DistanceSegs( context->orig, context->angle, context->segCnt, context->segPtr, &pos, &segInx ); if (segInx == -1) { return C_ERROR; } context->type = context->segPtr[segInx].type; switch(context->type) { case SEG_TBLEDGE: case SEG_STRLIN: case SEG_DIMLIN: case SEG_BENCH: REORIGIN( p0, context->segPtr[segInx].u.l.pos[0], context->angle, context->orig ); REORIGIN( p1, context->segPtr[segInx].u.l.pos[1], context->angle, context->orig ); tempSegs(0).type = SEG_STRLIN; tempSegs(0).color = wDrawColorRed; tempSegs(0).u.l.pos[0] = p0; tempSegs(0).u.l.pos[1] = p1; tempSegs(0).lineWidth = 0; tempSegs(0).u.l.option = context->segPtr[segInx].u.l.option; context->p0 = p0; context->p1 = p1; CreateLineAnchors(-1,p0,p1); break; case SEG_CRVLIN: case SEG_FILCRCL: BuildCircleContext(context,segInx); tempSegs(0).type = SEG_CRVLIN; tempSegs(0).color = wDrawColorRed; tempSegs(0).u.c.center = context->pc; tempSegs(0).u.c.radius = context->radius; tempSegs(0).u.c.a0 = context->segPtr[segInx].u.c.a0; tempSegs(0).u.c.a1 = context->segPtr[segInx].u.c.a1; tempSegs(0).lineWidth = 0; if (tempSegs(0).u.c.a1<360.0) { CreateCurveAnchors(-1,context->pm,context->pc,context->p0,context->p1); } else { CreateCircleAnchor(FALSE,tempSegs(0).u.c.center,tempSegs(0).u.c.radius, FindAngle(tempSegs(0).u.c.center,pos)); } context->last_inx = 2; break; case SEG_POLY: case SEG_FILPOLY: if (context->segPtr[segInx].u.p.polyType !=RECTANGLE) { polyMode = TRUE; return DrawGeomPolyModify(action,pos,context); } else { tempSegs(0).type = SEG_POLY; tempSegs(0).color = wDrawColorRed; DYNARR_RESET( pts_t, points_da); for (int inx=0; inxsegPtr->u.p.cnt; inx++) { DYNARR_APPEND(pts_t, points_da,3); REORIGIN( points(inx).pt, context->segPtr[segInx].u.p.pts[inx].pt, context->angle, context->orig ); } tempSegs(0).u.p.pts = &points(0); tempSegs(0).u.p.cnt = points_da.cnt; tempSegs(0).lineWidth = 0; context->p0 = points(0).pt; CreateBoxAnchors(-1,&context->segPtr[segInx].u.p.pts[0]); context->p0 = points(0).pt; context->p1 = points(1).pt; } break; case SEG_TEXT: InfoMessage("Text can only be modified with Describe"); wBeep(); return C_ERROR; default: ; } InfoMessage("Points Mode - Select and drag Anchor Point"); return C_CONTINUE; break; case wActionMove: if (context->rotate_state) { return DrawGeomOriginMove(action,pos,context); } if (polyMode) { return DrawGeomPolyModify(action,pos,context); } DYNARR_RESET(trkSeg_t,anchors_da); wSetCursor(mainD.d,defaultCursor); switch( context->type) { case SEG_TBLEDGE: case SEG_STRLIN: case SEG_DIMLIN: case SEG_BENCH: DYNARR_RESET(trkSeg_t,anchors_da); CreateLineAnchors(lineInx,context->p0,context->p1); dd = FindDistance( context->p0, pos ); if ( IsClose(dd)) { CreateMovingAnchor(context->p0,TRUE); } else { dd = FindDistance( context->p1, pos ); if ( IsClose(dd)) { CreateMovingAnchor(context->p1,TRUE); } } break; case SEG_CRVLIN: case SEG_FILCRCL: DYNARR_RESET(trkSeg_t,anchors_da); if (tempSegs(0).u.c.a1 >= 360.0) { if (IsClose(FindDistance(context->pc,pos)-context->radius)) { coOrd p; Translate(&p,context->pc,FindAngle(context->pc,pos),context->radius); CreateMovingAnchor(p,TRUE); DYNARR_SET(trkSeg_t,anchors_da,anchors_da.cnt+5); DrawArrowHeads(&DYNARR_N(trkSeg_t,anchors_da,anchors_da.cnt-5),p, FindAngle(context->pc,pos),TRUE,wDrawColorBlue); } } else { CreateCurveAnchors(curveInx,context->pm,context->pc,context->p0,context->p1); dd = FindDistance( context->p0, pos ); if ( IsClose(dd)) { CreateMovingAnchor(context->p0,TRUE); } else { dd = FindDistance( context->p1, pos ); if ( IsClose(dd)) { CreateMovingAnchor(context->p1,TRUE); } else { dd = FindDistance( context->pm, pos ); if ( IsClose(dd)) { CreateMovingAnchor(context->pm,TRUE); } } } } break; case SEG_POLY: case SEG_FILPOLY:; CreateBoxAnchors(-1,&points(0)); break; default:; } return C_CONTINUE; break; case C_DOWN: DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); if (context->rotate_state) { return DrawGeomOriginMove(action,pos,context); } if (polyMode) { return DrawGeomPolyModify(action,pos,context); } corner_mode = FALSE; segInx = 0; context->state = MOD_STARTED; tempSegs(0).lineWidth = context->segPtr[segInx].lineWidth; tempSegs(0).color = context->segPtr[segInx].color; switch ( context->type ) { case SEG_TBLEDGE: case SEG_STRLIN: case SEG_DIMLIN: case SEG_BENCH: p0 = context->p0; p1 = context->p1; lineInx = -1; dd = FindDistance( p0, pos ); if ( IsClose(dd)) { lineInx = 0; } else { dd = FindDistance( p1, pos ); if ( IsClose(dd)) { lineInx = 1; } } if (lineInx < 0 ) { InfoMessage( _("Not close to end of line")); } else { if (context->type == SEG_TBLEDGE) { InfoMessage("End selected, drag to move +Ctl to lock to other edge end, +Shift lock to line"); } else { InfoMessage("End selected, drag to reposition +Shift lock to line"); } context->state = MOD_SELECTED_PT; } tempSegs(0).color = wDrawColorBlack; tempSegs(0).lineWidth = 0; tempSegs(0).type = context->type; tempSegs(0).u.l.pos[0] = p0; tempSegs(0).u.l.pos[1] = p1; tempSegs(0).u.l.option = context->segPtr[segInx].u.l.option; segA1 = FindAngle( p1, p0 ); CreateLineAnchors(lineInx,p0,p1); break; case SEG_CRVLIN: case SEG_FILCRCL: curveInx = -1; tempSegs(0).color = wDrawColorBlack; tempSegs(0).lineWidth = 0; tempSegs(0).type = context->type; tempSegs(0).u.c.center = context->pc; tempSegs(0).u.c.radius = context->radius; if (context->segPtr[segInx].u.c.a1 >= 360.0) { tempSegs(0).u.c.a0 = 0.0; tempSegs(0).u.c.a1 = 360.0; InfoMessage("Drag to Change Radius"); CreateCircleAnchor(TRUE,tempSegs(0).u.c.center,tempSegs(0).u.c.radius, FindAngle(tempSegs(0).u.c.center,pos)); } else { p0 = context->p0; p1 = context->p1; pm = context->pm; pc = context->pc; tempSegs(0).u.c.a0 = FindAngle(context->pc,context->p0); tempSegs(0).u.c.a1 = DifferenceBetweenAngles(FindAngle(context->pc,context->p0), FindAngle(context->pc,context->p1)); tempSegs(0).u.c.center = context->pc; tempSegs(0).u.c.radius = context->radius; curveInx = -1; dd = FindDistance( p0, pos ); if ( IsClose(dd)) { curveInx = 0; } else { dd = FindDistance( p1, pos ); if ( IsClose(dd)) { curveInx = 1; } else { dd = FindDistance( pm, pos ); if ( IsClose(dd)) { curveInx = 2; } } } if (curveInx < 0) { InfoMessage( _("Not close to ends or middle of mine, reselect")); return C_CONTINUE; } else { if (curveInx <2 ) { InfoMessage("Drag to move end, +Ctrl to lock to other objects"); } else { InfoMessage("Drag to change radius"); } } if (tempSegs(0).u.c.a1 < 360.0) { CreateCurveAnchors(curveInx,pm,pc,p0,p1); } } context->state = MOD_SELECTED_PT; break; case SEG_POLY: case SEG_FILPOLY: d = 10000; polyInx = 0; wSetCursor(mainD.d,wCursorNone); for ( inx=0; inx<4; inx++ ) { if (IsClose(FindDistance(pos,points(inx).pt))) { corner_mode = TRUE; polyInx = inx; break; } p0 = pos; dd = LineDistance( &p0, points( inx==0?3:inx-1).pt, points( inx ).pt ); if ( d > dd ) { d = dd; inx_line = inx; } } if (!corner_mode) { d1 = FindDistance( points(inx_line).pt, pos ); d2 = FindDistance( points(inx_line==0?3:inx_line-1).pt, pos ); if (d2state = MOD_SELECTED_PT; return C_CONTINUE; case SEG_TEXT: segInx = -1; return C_ERROR; default: CHECK( FALSE ); /* CHECKME */ } if ( FindDistance( p0, pos ) >= FindDistance( p1, pos ) ) { switch ( context->type ) { case SEG_TBLEDGE: case SEG_STRLIN: case SEG_DIMLIN: case SEG_BENCH: segA1 = NormalizeAngle( segA1 + 180.0 ); break; default: ; } } UndrawNewTrack( context->trk ); return C_CONTINUE; case C_MOVE: if (context->rotate_state) { return DrawGeomOriginMove(action,pos,context); } if (polyMode) { return DrawGeomPolyModify(action,pos,context); } if (context->state != MOD_SELECTED_PT) { return C_CONTINUE; } BOOL_T locked = FALSE; switch (tempSegs(0).type) { case SEG_TBLEDGE: if ( (MyGetKeyState() & WKEY_CTRL) == WKEY_CTRL ) { //Special Snap to Table End Point if Ctrl if (OnTableEdgeEndPt( NULL, &pos )) { locked = TRUE; } } /* No Break*/ case SEG_STRLIN: case SEG_DIMLIN: case SEG_BENCH: if (!locked) { if ((MyGetKeyState() & WKEY_SHIFT) != 0) { //Shift is on same line d = FindDistance( pos, tempSegs(0).u.l.pos[1-lineInx] ); Translate( &pos, tempSegs(0).u.l.pos[1-lineInx], segA1, d ); locked = TRUE; } else if (((MyGetKeyState() & WKEY_ALT) == 0) == magneticSnap ) { //M.S. Either on or Off if (OnTrack( &pos, FALSE, FALSE )!=NULL) { CreateEndAnchor(pos,TRUE); locked = TRUE; } } }; if (!locked) { if (SnapPos(&pos)) { locked = TRUE; } } break; default: break; } int prior_pnt, next_pnt, orig_pnt; ANGLE_T prior_angle, next_angle, line_angle; switch (tempSegs(0).type) { case SEG_TBLEDGE: case SEG_STRLIN: case SEG_DIMLIN: case SEG_BENCH: if (lineInx<0 || lineInx>1) { return C_CONTINUE; } tempSegs(0).u.l.pos[lineInx] = pos; InfoMessage( _("Length = %0.3f Angle = %0.3f"), FindDistance( tempSegs(0).u.l.pos[lineInx], tempSegs(0).u.l.pos[1-lineInx] ), FindAngle( tempSegs(0).u.l.pos[1-lineInx], tempSegs(0).u.l.pos[lineInx] ) ); context->p0 = tempSegs(0).u.l.pos[0]; context->p1 = tempSegs(0).u.l.pos[1]; p0 = context->p0; p1 = context->p1; CreateLineAnchors(lineInx, p0, p1); break; case SEG_CRVLIN: case SEG_FILCRCL: if (tempSegs(0).u.c.a1 >= 360.0) { tempSegs(0).u.c.radius = FindDistance( context->pc, pos ); CreateCircleAnchor(TRUE,tempSegs(0).u.c.center,tempSegs(0).u.c.radius, FindAngle(tempSegs(0).u.c.center,pos)); } else { if (context->state != MOD_SELECTED_PT) { return C_CONTINUE; } if (curveInx < 0 || curveInx > 2) { return C_CONTINUE; } wSetCursor(mainD.d,wCursorNone); p0 = context->p0; p1 = context->p1; pc = context->pc; pm = context->pm; if ( (MyGetKeyState() & WKEY_SHIFT) != 0) { //Preserve Radius, Change swept angle a = FindAngle( pc, pos ); if (curveInx==0) { tempSegs(0).u.c.a1 = NormalizeAngle(FindAngle(pc,p1)-a); tempSegs(0).u.c.a0 = a; } else if (curveInx ==1) { tempSegs(0).u.c.a1 = NormalizeAngle(a-tempSegs(0).u.c.a0); } PointOnCircle(&p0,pc,context->radius,tempSegs(0).u.c.a0); PointOnCircle(&p1,pc,context->radius,tempSegs(0).u.c.a0+tempSegs(0).u.c.a1); context->p0 = p0; context->p1 = p1; PointOnCircle(&pm,pc,context->radius,tempSegs(0).u.c.a0+(tempSegs(0).u.c.a1/2)); context->pm = pm; } else { if (curveInx == 0 || curveInx == 1) { p0 = context->p0; p1 = context->p1; /* Preserve Curve "Deflection" */ d = context->disp; // Original Deflection if (curveInx == 0) { context->p0 = p0 = pos; } else { context->p1 = p1 = pos; } coOrd posx; //Middle of chord posx.x = (p1.x-p0.x)/2.0+p0.x; posx.y = (p1.y-p0.y)/2.0+p0.y; //Middle of chord ANGLE_T a0 = FindAngle( p1, p0 ); DIST_T d0 = FindDistance( p0, p1 )/2.0; DIST_T r = 1000.0; if ( fabs(d) >= 0.01 ) { d2 = sqrt( d0*d0 + d*d )/2.0; r = d2*d2*2.0/d; if ( fabs(r) > 1000.0 ) { r = ((r > 0)? 1 : -1) *1000.0; } } else { r = ((r > 0) ? 1 : -1 ) *1000.0; } a0 -= 90.0; if (r<0) { coOrd pt = p0; p0 = p1; p1 = pt; a0 += 180.0; } context->radius = tempSegs(0).u.c.radius = fabs(r); Translate( &pc, posx, a0, fabs(r)-fabs(d) ); context->pc = tempSegs(0).u.c.center = pc; tempSegs(0).u.c.a0 = FindAngle(pc,p0); context->arc_angle = tempSegs(0).u.c.a1 = NormalizeAngle(FindAngle(pc, p1)-FindAngle(pc,p0)); PointOnCircle(&pm,pc,context->radius, tempSegs(0).u.c.a0+(tempSegs(0).u.c.a1/2.0)); context->pm = pm; } else { //Change radius using chord p0 = context->p0; p1 = context->p1; pm = context->pm; ANGLE_T a0 = FindAngle( p1, p0 ); DIST_T d0 = FindDistance( p0, p1 )/2.0; coOrd pos2 = pos; Rotate( &pos2, p1, -a0 ); pos2.x -= p1.x; DIST_T r = 1000.0; if ( fabs(pos2.x) >= 0.01 ) { d2 = sqrt( d0*d0 + pos2.x*pos2.x )/2.0; r = d2*d2*2.0/pos2.x; if ( fabs(r) > 1000.0 ) { r = ((r > 0) ? 1 : -1 ) *1000.0; } } else { r = ((r > 0) ? 1 : -1 ) *1000.0; } coOrd posx; //Middle of chord posx.x = (p1.x-p0.x)/2.0 + p0.x; posx.y = (p1.y-p0.y)/2.0 + p0.y; a0 -= 90.0; if (r<0) { coOrd pt = p0; p0 = p1; p1 = pt; a0 += 180.0; } Translate( &pc, posx, a0, fabs(r) - fabs(pos2.x) ); context->pc = tempSegs(0).u.c.center = pc; context->radius = tempSegs(0).u.c.radius = fabs(r); a0 = FindAngle( pc, p0 ); ANGLE_T a1 = FindAngle( pc, p1 ); tempSegs(0).u.c.a0 = a0; tempSegs(0).u.c.a1 = NormalizeAngle(a1-a0); PointOnCircle(&pm,pc,context->radius,a0+(NormalizeAngle(a1-a0)/2)); context->p0 = p0; context->p1 = p1; context->pm = pm; context->disp = pos2.x; } } if (tempSegs(0).u.c.a1 < 360.0) { CreateCurveAnchors(curveInx,pm,pc,p0,p1); } } break; case SEG_POLY: case SEG_FILPOLY: wSetCursor(mainD.d,wCursorNone); if (!corner_mode) { /* Constrain movement to be perpendicular */ d = FindDistance(start_pos, pos); line_angle = NormalizeAngle(FindAngle(points(inx_line).pt, points(inx_line==3?0:inx_line+1).pt)); a = FindAngle(pos,start_pos); Translate( &pos, start_pos, line_angle, - d*cos(D2R(line_angle-a))); } d = FindDistance(start_pos,pos); a = FindAngle(start_pos, pos); start_pos = pos; prior_pnt = (polyInx == 0)?3:polyInx-1; next_pnt = (polyInx == 3)?0:polyInx+1; orig_pnt = (prior_pnt == 0)?3:prior_pnt-1; Translate( &points(polyInx).pt, points(polyInx).pt, a, d); d = FindDistance(points(orig_pnt).pt,points(polyInx).pt); a = FindAngle(points(orig_pnt).pt,points(polyInx).pt); prior_angle = FindAngle(points(orig_pnt).pt,points(prior_pnt).pt); Translate( &points(prior_pnt).pt, points(orig_pnt).pt, prior_angle, d*cos(D2R(prior_angle-a))); next_angle = FindAngle(points(orig_pnt).pt,points(next_pnt).pt); Translate( &points(next_pnt).pt, points(orig_pnt).pt, next_angle, d*cos(D2R(next_angle-a))); if (!corner_mode) { pos.x = (points(inx_line).pt.x + points(inx_line==0?3:inx_line-1).pt.x)/2; pos.y = (points(inx_line).pt.y + points(inx_line==0?3:inx_line-1).pt.y)/2; DYNARR_SET(trkSeg_t,anchors_da,5); DrawArrowHeads( &anchors(0), pos, FindAngle(points(inx_line).pt, points(inx_line==0?3:inx_line-1).pt)+90, TRUE, wDrawColorRed ); InfoMessage( _("Drag to Move Edge")); } else { pos = points(polyInx).pt; DYNARR_SET(trkSeg_t,anchors_da,5); DrawArrowHeads( &anchors(0), pos, FindAngle(points(polyInx).pt, points(inx_origin).pt), TRUE, wDrawColorRed ); InfoMessage( _("Drag to Move Corner Point")); } context->p0 = points(0).pt; context->p1 = points(1).pt; break; default: ; } return C_CONTINUE; case C_UP: if (context->rotate_state) { return DrawGeomOriginMove(action, pos, context); } if (polyMode) { int rc; rc = DrawGeomPolyModify(action,pos,context); if (context->prev_inx != -1) { context->state = MOD_AFTER_PT; } return rc; } wSetCursor(mainD.d,defaultCursor); if (segInx == -1) { return C_CONTINUE; } switch (tempSegs(0).type) { case SEG_TBLEDGE: case SEG_STRLIN: case SEG_DIMLIN: case SEG_BENCH: p0 = context->p0; p1 = context->p1; context->abs_angle = FindAngle(p0,p1); context->length = FindDistance(p0,p1); CreateLineAnchors(lineInx,p0,p1); context->last_inx = lineInx; break; case SEG_CRVLIN: case SEG_FILCRCL: if ( (tempSegs(0).type == SEG_FILCRCL) || (tempSegs(0).u.c.a1 == 360.0 || tempSegs(0).u.c.a1 == 0.0) ) { context->radius = fabs(tempSegs(0).u.c.radius); context->arc_angle = 360.0; CreateCircleAnchor(FALSE,tempSegs(0).u.c.center,tempSegs(0).u.c.radius, FindAngle(tempSegs(0).u.c.center,pos)); } else { p0 = context->p0; p1 = context->p1; pc = context->pc; pm = context->pm; context->radius = fabs(tempSegs(0).u.c.radius); context->arc_angle = tempSegs(0).u.c.a1; CreateCurveAnchors(curveInx,pm,pc,p0,p1); a = FindAngle(p1,p0); Rotate(&pm,p1,-a); context->disp = pm.x-p1.x; } context->last_inx = curveInx; break; case SEG_POLY: case SEG_FILPOLY: CreateBoxAnchors(-1,tempSegs(0).u.p.pts); context->width = FindDistance(tempSegs(0).u.p.pts[0].pt, tempSegs(0).u.p.pts[1].pt); context->height = FindDistance(tempSegs(0).u.p.pts[1].pt, tempSegs(0).u.p.pts[2].pt); context->last_inx = polyInx; if (corner_mode) { context->last_inx +=5; } break; default: ; } context->state = MOD_AFTER_PT; curveInx = -1; lineInx = -1; polyInx = -1; InfoMessage("Enter/Space to Accept, ESC to Reject"); return C_CONTINUE; case C_UPDATE: if (context->rotate_state) { return DrawGeomOriginMove(action, pos, context); } if (polyMode) { return DrawGeomPolyModify(action,pos,context); } if (context->state == MOD_AFTER_PT) { switch (tempSegs(0).type) { case SEG_TBLEDGE: case SEG_STRLIN: case SEG_DIMLIN: case SEG_BENCH: context->abs_angle = NormalizeAngle(context->abs_angle); Translate(&tempSegs(0).u.l.pos[1],tempSegs(0).u.l.pos[0],context->abs_angle, context->length); CreateLineAnchors(context->last_inx,tempSegs(0).u.l.pos[0], tempSegs(0).u.l.pos[1]); context->p0 = tempSegs(0).u.l.pos[0]; context->p1 = tempSegs(0).u.l.pos[1]; break; case SEG_CRVLIN: case SEG_FILCRCL: if (tempSegs(0).u.c.a1 == 360.0 || tempSegs(0).u.c.a1 == 0.0) { tempSegs(0).u.c.a1 = 360.0; tempSegs(0).u.c.radius = context->radius; Translate(&p0,tempSegs(0).u.c.center,tempSegs(0).u.c.a0,tempSegs(0).u.c.radius); context->p0 = p0; context->p1 = p0; context->pm = p0; context->pc = tempSegs(0).u.c.center; break; } if (context->radius < 0) { //swap ends context->radius = fabs(context->radius); p1 = context->p0; p0 = context->p1; a = FindAngle(context->pc,context->pm); Translate(&pm,context->pm,a+180,2*context->disp); Translate(&pc,pm,a,context->radius); context->pm = pm; context->pc = pc; context->p0 = p0; context->p1 = p1; } else { pm = context->pm; pc = context->pc; p0 = context->p0; p1 = context->p1; } if (context->last_inx == 0) { p1 = context->p1; pc = context->pc; a = FindAngle(p1,pc); Translate(&pc,p1,a,context->radius); context->pc = pc; PointOnCircle( &p0, context->pc, context->radius, NormalizeAngle(a+180-context->arc_angle) ); context->p0 = p0; PointOnCircle( &pm, context->pc, context->radius, NormalizeAngle(a+180-(context->arc_angle/2))); context->pm = pm; } else if (context->last_inx == 1) { p0 = context->p0; pc = context->pc; a = FindAngle(p0,pc); Translate(&pc,p0,a,context->radius); context->pc = pc; PointOnCircle( &p1, context->pc, context->radius, NormalizeAngle(a+180+context->arc_angle) ); context->p1 = p1; PointOnCircle( &pm, context->pc, context->radius, NormalizeAngle(a+180+(context->arc_angle/2))); context->pm = pm; } else { // Middle if neither a = FindAngle(context->pm,context->pc); Translate(&pc,context->pm,a,context->radius); context->pc = pc; PointOnCircle( &p1, context->pc, context->radius, NormalizeAngle(FindAngle(context->pc,context->pm)+(context->arc_angle/2)) ); PointOnCircle( &p0, context->pc, context->radius, NormalizeAngle(FindAngle(context->pc,context->pm)-(context->arc_angle/2)) ); context->p1 = p1; context->p0 = p0; } a = FindAngle(p1,p0); Rotate(&pm,p1,-a); context->disp = pm.x-p1.x; tempSegs(0).u.c.center = context->pc; tempSegs(0).u.c.a0 = FindAngle(context->pc,context->p0); tempSegs(0).u.c.a1 = NormalizeAngle(FindAngle(context->pc, context->p1)-tempSegs(0).u.c.a0); if (tempSegs(0).u.c.a1 == 0.0) { tempSegs(0).u.c.a1 = 360.0; } tempSegs(0).u.c.radius = context->radius; CreateCurveAnchors(context->last_inx,context->pm,context->pc,context->p0, context->p1); break; case SEG_POLY: case SEG_FILPOLY: a = NormalizeAngle(FindAngle(points(0).pt,points(3).pt)); Translate( &points(3).pt, points(0).pt, a, context->height); Translate( &points(2).pt, points(1).pt, a, context->height); a = NormalizeAngle(FindAngle(points(0).pt,points(1).pt));; Translate( &points(1).pt, points(0).pt, a, context->width); Translate( &points(2).pt, points(3).pt, a, context->width); CreateBoxAnchors(context->last_inx,&points(0)); break; default: break; } } break; case wActionExtKey: if ((((action>>8)&0xFF)== wAccelKey_Del) && polyMode) { //Convert Del key to be BackSpace in PolyModify return DrawGeomPolyModify(C_TEXT+((int)(127<<8)),pos,context); } break; case C_TEXT: DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); if (context->rotate_state) { DrawGeomOriginMove(action, pos, context); } if (polyMode) { return DrawGeomPolyModify(action,pos,context); } if (action>>8 == 'o') { MenuMode(I2VP(1)); } if (context->subtype == RECTANGLE) { switch (action>>8) { case 'f': tempSegs(0).type = SEG_FILPOLY; context->type = SEG_FILPOLY; break; case 'u': tempSegs(0).type = SEG_POLY; context->type = SEG_POLY; break; } } if (action>>8 != 32 && action>>8 != 13) { return C_CONTINUE; } /* no break */ case C_CONFIRM: return C_CONTINUE; /* no break*/ case C_OK: case C_FINISH: UndoStart("Modify Draw", "OK"); UndoModify(context->trk); if (polyMode) { DrawGeomPolyModify(action,pos,context); context->segPtr[segInx].type = context->type; context->segPtr[segInx].u.p.polyType = context->subtype; if (context->segPtr[segInx].type == SEG_FILPOLY) { context->segPtr[segInx].u.p.polyType = FREEFORM; //Ensure Filled is closed } context->state = MOD_NONE; DrawNewTrack( context->trk ); DYNARR_RESET( trkSeg_t, tempSegs_da ); return C_TERMINATE; } //copy changes back into track context->orig.x = context->rot_center.x; context->orig.y = context->rot_center.y; context->rot_moved = FALSE; context->angle = 0.0; switch (tempSegs(0).type) { case SEG_TBLEDGE: case SEG_STRLIN: case SEG_DIMLIN: case SEG_BENCH: for (int i=0; i<2; i++) { pos = i==0?context->p0:context->p1; pos.x -= context->rot_center.x; pos.y -= context->rot_center.y; context->segPtr[segInx].u.l.pos[i] = pos; } break; case SEG_CRVLIN: case SEG_FILCRCL: pc = context->pc; pc.x -= context->rot_center.x; pc.y -= context->rot_center.y; context->segPtr[segInx].u.c.center = pc; p0 = context->p0; p0.x -= context->rot_center.x; p0.y -= context->rot_center.y; p1 = context->p1; p1.x -= context->rot_center.x; p1.y -= context->rot_center.y; context->segPtr[segInx].u.c.a0 = FindAngle(pc,p0); context->segPtr[segInx].u.c.a1 = NormalizeAngle(FindAngle(pc,p1)-FindAngle(pc, p0)); if (context->segPtr[segInx].u.c.a1 == 0) { context->segPtr[segInx].u.c.a1 = 360.0; } context->segPtr[segInx].u.c.radius = context->radius; break; case SEG_POLY: case SEG_FILPOLY: for (int i=0; i<4; i++) { pos = points(i).pt; pos.x -= context->rot_center.x; pos.y -= context->rot_center.y; context->segPtr[segInx].u.p.pts[i].pt = pos; } break; default: break; } context->state = MOD_NONE; context->rotate_state = FALSE; context->last_inx = -1; DYNARR_RESET(trkSeg_t,anchors_da); DYNARR_RESET( trkSeg_t, tempSegs_da ); DrawNewTrack( context->trk ); return C_TERMINATE; case C_REDRAW: if (polyMode) { return DrawGeomPolyModify(action,pos,context); } if (context->state == MOD_NONE) { return C_CONTINUE; } DrawSegsDA( &tempD, NULL, zero, 0.0, &tempSegs_da, trackGauge, wDrawColorBlack, 0 ); DrawSegsDA( &tempD, NULL, zero, 0.0, &anchors_da, trackGauge, wDrawColorBlack, 0 ); break; case C_CANCEL: context->state = MOD_NONE; context->rotate_state = FALSE; context->rot_moved = FALSE; polyMode = FALSE; DYNARR_RESET(trkSeg_t,anchors_da); DYNARR_RESET( trkSeg_t, tempSegs_da ); DrawNewTrack( context->trk ); break; default: ; } return C_CONTINUE; }