From d1a8285f818eb7e5c3d6a05709ea21a808490b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 19 Mar 2018 19:55:58 +0100 Subject: New upstream version 5.1.0 --- app/bin/drawgeom.c | 306 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 230 insertions(+), 76 deletions(-) (limited to 'app/bin/drawgeom.c') diff --git a/app/bin/drawgeom.c b/app/bin/drawgeom.c index 8ef31e8..6d4b237 100644 --- a/app/bin/drawgeom.c +++ b/app/bin/drawgeom.c @@ -17,14 +17,22 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include -#include "track.h" +#include + #include "ccurve.h" +#include "cbezier.h" #include "compound.h" +#include "cundo.h" #include "drawgeom.h" +#include "fileio.h" #include "i18n.h" +#include "messages.h" +#include "param.h" +#include "track.h" +#include "utility.h" -/*EXPORT drawContext_t * drawContext;*/ static long drawGeomCurveMode; #define contextSegs(N) DYNARR_N( trkSeg_t, context->Segs_da, N ) @@ -68,6 +76,7 @@ static void EndPoly( drawContext_t * context, int cnt ) segPtr->u.p.pts = pts; segPtr->u.p.angle = 0.0; segPtr->u.p.orig = zero; + segPtr->u.p.polyType = FREEFORM; UndoStart( _("Create Lines"), "newDraw" ); trk = MakeDrawFromSeg( zero, 0.0, segPtr ); DrawNewTrack( trk ); @@ -133,19 +142,38 @@ STATUS_T DrawGeomMouse( case wActionLDown: context->Started = TRUE; + if (context->State == 0) { //First Down only + switch (context->Op) { //Snap pos to nearest line end point if this is end and just shift is depressed for lines and some curves + case OP_LINE: + case OP_CURVE1: + if ((MyGetKeyState() & (WKEY_SHIFT|WKEY_CTRL|WKEY_ALT)) == WKEY_SHIFT ) { + coOrd p = pos; + track_p t; + if ((t=OnTrack(&p,FALSE,FALSE))) { + if (GetClosestEndPt(t,&p)) { + pos = p; + } + } + }; + break; + default: + ; + } + } if ((context->Op == OP_CURVE1 || context->Op == OP_CURVE2 || context->Op == OP_CURVE3 || context->Op == OP_CURVE4) && context->State == 1) { ; } else { - if ( (MyGetKeyState() & (WKEY_SHIFT|WKEY_CTRL|WKEY_ALT)) == WKEY_CTRL ) + if ( (MyGetKeyState() & (WKEY_SHIFT|WKEY_CTRL|WKEY_ALT)) == WKEY_CTRL ) // Control snaps to nearest track (not necessarily the end) OnTrack( &pos, FALSE, FALSE ); pos0 = pos; pos1 = pos; } + switch (context->Op) { case OP_LINE: case OP_DIMLINE: case OP_BENCH: - if ( lastValid && ( MyGetKeyState() & WKEY_SHIFT ) ) { + if ( lastValid && ( MyGetKeyState() & WKEY_CTRL ) ) { pos = pos0 = lastPos; } DYNARR_SET( trkSeg_t, tempSegs_da, 1 ); @@ -166,7 +194,7 @@ STATUS_T DrawGeomMouse( context->message( _("Drag to place next end point") ); break; case OP_TBLEDGE: - if ( lastValid && ( MyGetKeyState() & WKEY_SHIFT ) ) { + if ( lastValid && ( MyGetKeyState() & WKEY_CTRL ) ) { pos = pos0 = lastPos; } OnTableEdgeEndPt( NULL, &pos ); @@ -278,8 +306,8 @@ STATUS_T DrawGeomMouse( break; case OP_CURVE1: case OP_CURVE2: case OP_CURVE3: case OP_CURVE4: if (context->State == 0) { + CreateCurve( C_MOVE, pos, FALSE, context->Color, width, drawGeomCurveMode, context->message ); pos0x = pos; - CreateCurve( C_MOVE, pos, TRUE, context->Color, width, drawGeomCurveMode, context->message ); } else { PlotCurve( drawGeomCurveMode, pos0, pos0x, pos1, &context->ArcData, FALSE ); tempSegs(0).color = context->Color; @@ -346,6 +374,7 @@ STATUS_T DrawGeomMouse( else DrawSegs( context->D, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); context->D->funcs->options = oldOptions; + if (context->Op == OP_DIMLINE) MainRedraw(); //Wipe Out Text return C_CONTINUE; case wActionLUp: @@ -355,6 +384,45 @@ STATUS_T DrawGeomMouse( DrawSegs( context->D, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); lastValid = FALSE; createTrack = FALSE; + if ((context->State == 0 && (context->Op == OP_LINE )) || //first point release for line, + (context->State == 1 && context->Op == OP_CURVE1)) { //second point for curve from end + switch (context->Op) { //Snap pos to nearest line end point if this is on a line and just shift is depressed for lines and some curves + case OP_CURVE1: + case OP_LINE: + if ((MyGetKeyState() & (WKEY_SHIFT|WKEY_CTRL|WKEY_ALT)) == WKEY_SHIFT ) { + coOrd p = pos1; + track_p t; + if ((t=OnTrack(&p,FALSE,FALSE))) { + if (GetClosestEndPt(t,&p)) { + pos1 = p; + if (context->Op == OP_LINE) { + tempSegs(0).u.l.pos[1] = p; + } else { + PlotCurve( drawGeomCurveMode, pos0, pos0x, pos1, &context->ArcData, FALSE ); + 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; + tempSegs_da.cnt = 1; + } else if (context->ArcData.type == curveTypeNone) { + tempSegs_da.cnt = 0; + } 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; + tempSegs_da.cnt = 1; + } + } + } + } + }; + break; + default: + ; + } + } switch ( context->Op ) { case OP_LINE: case OP_DIMLINE: @@ -368,7 +436,7 @@ STATUS_T DrawGeomMouse( context->State = 1; context->ArcAngle = FindAngle( pos0, pos1 ); pos0x = pos1; - CreateCurve( C_UP, pos, TRUE, context->Color, width, drawGeomCurveMode, context->message ); + CreateCurve( C_UP, pos, FALSE, context->Color, width, drawGeomCurveMode, context->message ); DrawSegs( context->D, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); segCnt = tempSegs_da.cnt; context->message( _("Drag on Red arrows to adjust curve") ); @@ -417,17 +485,16 @@ STATUS_T DrawGeomMouse( break; case OP_BOX: case OP_FILLBOX: - if ( context->Op == OP_FILLBOX ) { - pts = (coOrd*)MyMalloc( 4 * sizeof *(coOrd*)NULL ); - for ( inx=0; inx<4; inx++ ) - pts[inx] = tempSegs(inx).u.l.pos[0]; - tempSegs(0).type = SEG_FILPOLY; - 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_da.cnt = 1; - } + pts = (coOrd*)MyMalloc( 4 * sizeof *(coOrd*)NULL ); + for ( inx=0; inx<4; inx++ ) + pts[inx] = tempSegs(inx).u.l.pos[0]; + 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; + tempSegs_da.cnt = 1; /*drawContext = context; DrawGeomOp( (void*)context->Op );*/ break; @@ -445,6 +512,7 @@ STATUS_T DrawGeomMouse( return C_TERMINATE; case wActionText: + if ( ((action>>8)&0xFF) == 0x0D || ((action>>8)&0xFF) == ' ' ) { EndPoly(context, segCnt); @@ -453,6 +521,7 @@ STATUS_T DrawGeomMouse( return C_TERMINATE; case C_CANCEL: + oldOptions = context->D->funcs->options; context->D->funcs->options |= wDrawOptTemp; DrawSegs( context->D, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); @@ -487,18 +556,21 @@ STATUS_T DrawGeomModify( { ANGLE_T a; coOrd p0, p1, pc; + static coOrd start_pos; static wIndex_t segInx; static EPINX_T segEp; static ANGLE_T segA1; - static int polyInx; - int inx; - DIST_T d, dd; + static int polyInx, inx_other, inx_line, inx_origin; + static BOOL_T corner_mode; + int inx, inx1, inx2; + DIST_T d, d1, d2, dd; coOrd * newPts; int mergePoints; - + tempSegs_da.cnt = 1; switch ( action ) { case C_DOWN: segInx = -1; + corner_mode = FALSE; DistanceSegs( orig, angle, segCnt, segPtr, &pos, &segInx ); if (segInx == -1) return C_ERROR; @@ -523,7 +595,7 @@ STATUS_T DrawGeomModify( REORIGIN( pc, segPtr[segInx].u.c.center, angle, orig ) tempSegs(0).type = segPtr[segInx].type; tempSegs(0).u.c.center = pc; - tempSegs(0).u.c.radius = segPtr[segInx].u.c.radius; + tempSegs(0).u.c.radius = fabs(segPtr[segInx].u.c.radius); if (segPtr[segInx].u.c.a1 >= 360.0) { tempSegs(0).u.c.a0 = 0.0; tempSegs(0).u.c.a1 = 360.0; @@ -531,8 +603,8 @@ STATUS_T DrawGeomModify( tempSegs(0).u.c.a0 = NormalizeAngle( segPtr[segInx].u.c.a0+angle ); tempSegs(0).u.c.a1 = segPtr[segInx].u.c.a1; segA1 = NormalizeAngle( segPtr[segInx].u.c.a0 + segPtr[segInx].u.c.a1 + angle ); - PointOnCircle( &p0, pc, segPtr[segInx].u.c.radius, segPtr[segInx].u.c.a0+angle ); - PointOnCircle( &p1, pc, segPtr[segInx].u.c.radius, segPtr[segInx].u.c.a0+segPtr[segInx].u.c.a1+angle ); + PointOnCircle( &p0, pc, fabs(segPtr[segInx].u.c.radius), segPtr[segInx].u.c.a0+angle ); + PointOnCircle( &p1, pc, fabs(segPtr[segInx].u.c.radius), segPtr[segInx].u.c.a0+segPtr[segInx].u.c.a1+angle ); } break; @@ -542,6 +614,7 @@ STATUS_T DrawGeomModify( tempSegs(0).u.p.cnt = segPtr[segInx].u.p.cnt; tempSegs(0).u.p.angle = 0.0; tempSegs(0).u.p.orig = zero; + tempSegs(0).u.p.polyType = segPtr[segInx].u.p.polyType; DYNARR_SET( coOrd, points_da, segPtr[segInx].u.p.cnt+1 ); tempSegs(0).u.p.pts = &points(0); d = 10000; @@ -557,28 +630,61 @@ STATUS_T DrawGeomModify( polyInx = inx; } } - inx = (polyInx==0?segPtr[segInx].u.p.cnt-1:polyInx-1); - d = FindDistance( points(inx), pos ); - dd = FindDistance( points(inx), points(polyInx) ); - if ( d < 0.25*dd ) { - polyInx = inx; - } else if ( d > 0.75*dd ) { - ; - } else { - tempSegs(0).u.p.cnt++; - for (inx=points_da.cnt-1; inx>polyInx; inx-- ) { - points(inx) = points(inx-1); + if (segPtr[segInx].u.p.polyType == RECTANGLE) { + d1 = FindDistance( points(polyInx), pos ); + d2 = FindDistance( points(polyInx==0?segPtr[segInx].u.p.cnt-1:polyInx-1), pos ); + if (d2 0.75*dd ) { + ; + } else { + tempSegs(0).u.p.cnt++; + for (inx=points_da.cnt-1; inx>polyInx; inx-- ) { + points(inx) = points(inx-1); + } /*fprintf( stderr, "Inserting vertix before %d\n", polyInx );*/ + } + points(polyInx) = pos; } - points(polyInx) = pos; p1=p0; break; - default: - ASSERT( FALSE ); /* CHECKME */ case SEG_TEXT: segInx = -1; return C_ERROR; + default: + ASSERT( FALSE ); /* CHECKME */ + } if ( FindDistance( p0, pos ) < FindDistance( p1, pos ) ) segEp = 0; @@ -586,7 +692,6 @@ STATUS_T DrawGeomModify( segEp = 1; switch ( segPtr[segInx].type ) { case SEG_TBLEDGE: - case SEG_STRLIN: case SEG_DIMLIN: case SEG_BENCH: @@ -596,7 +701,6 @@ STATUS_T DrawGeomModify( ; } } - tempSegs_da.cnt = 1; return C_CONTINUE; case C_MOVE: if (segInx == -1) @@ -608,6 +712,9 @@ STATUS_T DrawGeomModify( } else if ( (MyGetKeyState() & (WKEY_SHIFT|WKEY_CTRL|WKEY_ALT)) == WKEY_CTRL ) { OnTrack( &pos, FALSE, FALSE ); } + int prior_pnt, next_pnt, orig_pnt; + ANGLE_T prior_angle, next_angle, line_angle; + tempSegs_da.cnt = 1; switch (tempSegs(0).type) { case SEG_TBLEDGE: @@ -617,12 +724,6 @@ STATUS_T DrawGeomModify( tempSegs(0).u.l.pos[segEp] = pos; InfoMessage( _("Length = %0.3f Angle = %0.3f"), FindDistance( tempSegs(0).u.l.pos[segEp], tempSegs(0).u.l.pos[1-segEp] ), FindAngle( tempSegs(0).u.l.pos[1-segEp], tempSegs(0).u.l.pos[segEp] ) ); break; - pos.x -= orig.x; - pos.y -= orig.y; - pos.x -= orig.x; - pos.y -= orig.y; - Rotate( &pos, zero, -angle ); - Rotate( &pos, zero, -angle ); case SEG_CRVLIN: case SEG_FILCRCL: if (tempSegs(0).u.c.a1 >= 360.0) { @@ -639,12 +740,50 @@ STATUS_T DrawGeomModify( break; case SEG_POLY: case SEG_FILPOLY: - points(polyInx) = pos; + switch (tempSegs(0).u.p.polyType) { + case RECTANGLE: + if (!corner_mode) { + /* Constrain movement to be perpendicular */ + d = FindDistance(start_pos, pos); + line_angle = NormalizeAngle(FindAngle(points(inx_line),points(polyInx))-90); + 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), points(polyInx), a, d); + d = FindDistance(points(orig_pnt),points(polyInx)); + a = FindAngle(points(orig_pnt),points(polyInx)); + prior_angle = FindAngle(points(orig_pnt),points(prior_pnt)); + Translate( &points(prior_pnt), points(orig_pnt), prior_angle, d*cos(D2R(prior_angle-a))); + next_angle = FindAngle(points(orig_pnt),points(next_pnt)); + Translate( &points(next_pnt), points(orig_pnt), next_angle, d*cos(D2R(next_angle-a))); + if (!corner_mode) { + pos.x = (points(polyInx).x + points(inx_line).x)/2; + pos.y = (points(polyInx).y + points(inx_line).y)/2; + DrawArrowHeads( &tempSegs(1), pos, FindAngle(points(polyInx),points(inx_line))+90, TRUE, wDrawColorRed ); + tempSegs_da.cnt = 6; + InfoMessage( _("Drag to Move Edge")); + } else { + pos = points(polyInx); + DrawArrowHeads( &tempSegs(1), pos, FindAngle(points(polyInx),points(inx_origin)), TRUE, wDrawColorRed ); + tempSegs_da.cnt = 6; + InfoMessage( _("Drag to Move Corner Point")); + } + break; + default: + points(polyInx) = pos; + } + break; default: ; } - tempSegs_da.cnt = 1; + return C_CONTINUE; case C_UP: if (segInx == -1) @@ -664,7 +803,7 @@ STATUS_T DrawGeomModify( case SEG_CRVLIN: case SEG_FILCRCL: if ( tempSegs(0).u.c.a1 >= 360.0 ) { - segPtr[segInx].u.c.radius = tempSegs(0).u.c.radius; + segPtr[segInx].u.c.radius = fabs(tempSegs(0).u.c.radius); } else { a = FindAngle( tempSegs(0).u.c.center, pos ); a = NormalizeAngle( a-angle ); @@ -676,39 +815,54 @@ STATUS_T DrawGeomModify( break; case SEG_POLY: case SEG_FILPOLY: - mergePoints = FALSE; - if ( IsClose( FindDistance( pos, points( polyInx==0?tempSegs(0).u.p.cnt-1:polyInx-1 ) ) ) || - IsClose( FindDistance( pos, points( (polyInx==tempSegs(0).u.p.cnt-1)?0:polyInx+1 ) ) ) ) { - mergePoints = TRUE; - if (segPtr[segInx].u.p.cnt <= 3) { - ErrorMessage( MSG_POLY_SHAPES_3_SIDES ); - break; + switch(tempSegs(0).u.p.polyType) { + case RECTANGLE: + for (int i=0;i<4;i++) { + pos = points(i); + pos.x -= orig.x; + pos.y -= orig.y; + Rotate( &pos, zero, -angle ); + segPtr[segInx].u.p.pts[i] = pos; + } + break; + default: + mergePoints = FALSE; + if ( IsClose( FindDistance( pos, points( polyInx==0?tempSegs(0).u.p.cnt-1:polyInx-1 ) ) ) || + IsClose( FindDistance( pos, points( (polyInx==tempSegs(0).u.p.cnt-1)?0:polyInx+1 ) ) ) ) { + mergePoints = TRUE; + if (segPtr[segInx].u.p.cnt <= 3) { + ErrorMessage( MSG_POLY_SHAPES_3_SIDES ); + break; + } } - } - newPts = (coOrd*)MyMalloc( tempSegs(0).u.p.cnt * sizeof *(coOrd*)0 ); - memcpy( newPts, segPtr[segInx].u.p.pts, (segPtr[segInx].u.p.cnt) * sizeof *(coOrd*)0 ); - segPtr[segInx].u.p.pts = newPts; + coOrd * oldPts = segPtr[segInx].u.p.pts; + newPts = (coOrd*)MyMalloc( tempSegs(0).u.p.cnt * sizeof *(coOrd*)0 ); + memcpy( newPts, segPtr[segInx].u.p.pts, (segPtr[segInx].u.p.cnt) * sizeof *(coOrd*)0 ); + segPtr[segInx].u.p.pts = newPts; + MyFree(oldPts); - if ( tempSegs(0).u.p.cnt > segPtr[segInx].u.p.cnt ) { - ASSERT( tempSegs(0).u.p.cnt == segPtr[segInx].u.p.cnt+1 ); - for (inx=tempSegs(0).u.p.cnt-1; inx>polyInx; inx--) - segPtr[segInx].u.p.pts[inx] = segPtr[segInx].u.p.pts[inx-1]; - segPtr[segInx].u.p.cnt++; - } + + if ( tempSegs(0).u.p.cnt > segPtr[segInx].u.p.cnt ) { + ASSERT( tempSegs(0).u.p.cnt == segPtr[segInx].u.p.cnt+1 ); + for (inx=tempSegs(0).u.p.cnt-1; inx>polyInx; inx--) + segPtr[segInx].u.p.pts[inx] = segPtr[segInx].u.p.pts[inx-1]; + segPtr[segInx].u.p.cnt++; + } - pos = points(polyInx); - if ( mergePoints ) { - for (inx=polyInx+1; inx