diff options
Diffstat (limited to 'app/bin/trkseg.c')
-rw-r--r-- | app/bin/trkseg.c | 599 |
1 files changed, 480 insertions, 119 deletions
diff --git a/app/bin/trkseg.c b/app/bin/trkseg.c index 972463f..9517a09 100644 --- a/app/bin/trkseg.c +++ b/app/bin/trkseg.c @@ -1,5 +1,5 @@ -/** \file trkseg.c - * Modification and drawing of track segments +/* + * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/bin/trkseg.c,v 1.2 2006-05-30 16:11:55 m_fischer Exp $ */ /* XTrkCad - Model Railroad CAD @@ -20,18 +20,44 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <track.h> #include <time.h> #include <ctype.h> +#include <math.h> #include <stdarg.h> #include "track.h" +#include <common.h> +#include <cbezier.h> +#include <string.h> + +#include <tbezier.h> + #include "cjoin.h" +#include "fileio.h" +#include "param.h" +#include "track.h" +#include "utility.h" +#include "misc.h" + /***************************************************************************** * * TRACK SEGMENTS * + * Notes: Segments are used + * 1. as temporary elements during editing operations + * 2. as a means of grouping primitives for compounds + * 3. as the way of drawing and operating on Bezier curves + * + * They are stored as dynamic arrays which can be displayed and operated on as sets. + * */ + +/* + * Build a Segment that has a radius and passes through two points. This uses the knowledge + * that the center of curve is always on an orthogonal line through the bisection of a chord. + */ EXPORT void ComputeCurvedSeg( trkSeg_p s, DIST_T radius, @@ -66,7 +92,7 @@ EXPORT coOrd GetSegEndPt( ANGLE_T * angleR ) { coOrd pos; - ANGLE_T angle, a, a0, a1; + ANGLE_T angle, a, a0, a1 = 0.0; DIST_T r; POS_T x0, y0, x1, y1; @@ -114,7 +140,12 @@ EXPORT coOrd GetSegEndPt( case SEG_JNTTRK: pos = GetJointSegEndPos( segPtr->u.j.pos, segPtr->u.j.angle, segPtr->u.j.l0, segPtr->u.j.l1, segPtr->u.j.R, segPtr->u.j.L, segPtr->u.j.negate, segPtr->u.j.flip, segPtr->u.j.Scurve, ep, &angle ); break; - default: + case SEG_BEZTRK: + case SEG_BEZLIN: + if (ep ==1) pos = segPtr->u.b.pos[3]; //For Bezier, use the End Points of the overall curve + else pos = segPtr->u.b.pos[0]; + break; + default: AbortProg("GetSegCntPt(%c)", segPtr->type ); } if ( angleR ) @@ -123,7 +154,7 @@ EXPORT coOrd GetSegEndPt( } /** - * Caclulate the bounding box for a string. + * Calculate the bounding box for a string. * * \param coOrd IN position of text * \param angle IN text angle @@ -131,9 +162,7 @@ EXPORT coOrd GetSegEndPt( * \param fs IN size of font * \param loR OUT bottom left corner * \param hiR OUT top right corner - * \return describe the return value */ - EXPORT void GetTextBounds( coOrd pos, ANGLE_T angle, @@ -142,29 +171,44 @@ EXPORT void GetTextBounds( coOrd * loR, coOrd * hiR ) { + coOrd size; - POS_T descent; + POS_T descent = 0.0; coOrd lo, hi; coOrd p[4]; + coOrd lastL; int i; - DrawTextSize2( &mainD, str, NULL, fs, FALSE, &size, &descent ); - + DrawMultiLineTextSize(&mainD, str, NULL, fs, FALSE, &size, &lastL); // set up the corners of the rectangle p[0].x = p[3].x = 0.0; p[1].x = p[2].x = size.x; - p[0].y = p[1].y = -descent; + DrawTextSize2(&mainD, "A", NULL, fs, FALSE, &size, &descent); + p[0].y = p[1].y = lastL.y - descent; p[2].y = p[3].y = size.y; lo = hi = zero; // rotate each point - for ( i=1; i<4; i++ ) { - Rotate( &p[i], zero, angle ); - if ( p[i].x < lo.x ) lo.x = p[i].x; - if ( p[i].y < lo.y ) lo.y = p[i].y; - if ( p[i].x > hi.x ) hi.x = p[i].x; - if ( p[i].y > hi.y ) hi.y = p[i].y; + for (i=0; i<4; i++) + { + Rotate(&p[i], zero, angle); + + if (p[i].x < lo.x) { + lo.x = p[i].x; + } + + if (p[i].y < lo.y) { + lo.y = p[i].y; + } + + if (p[i].x > hi.x) { + hi.x = p[i].x; + } + + if (p[i].y > hi.y) { + hi.y = p[i].y; + } } // now recaclulate the corners @@ -178,7 +222,7 @@ EXPORT void GetTextBounds( static void Get1SegBounds( trkSeg_p segPtr, coOrd xlat, ANGLE_T angle, coOrd *lo, coOrd *hi ) { int inx; - coOrd p0, p1, pc; + coOrd p0, p1, pBez[4], pc; ANGLE_T a0, a1; coOrd width; DIST_T radius; @@ -266,15 +310,31 @@ static void Get1SegBounds( trkSeg_p segPtr, coOrd xlat, ANGLE_T angle, coOrd *lo break; case SEG_FILCRCL: REORIGIN( p0, segPtr->u.c.center, angle, xlat ) - lo->x = p0.x - segPtr->u.c.radius; - hi->x = p0.x + segPtr->u.c.radius; - lo->y = p0.y - segPtr->u.c.radius; - hi->y = p0.y + segPtr->u.c.radius; + lo->x = p0.x - fabs(segPtr->u.c.radius); + hi->x = p0.x + fabs(segPtr->u.c.radius); + lo->y = p0.y - fabs(segPtr->u.c.radius); + hi->y = p0.y + fabs(segPtr->u.c.radius); break; case SEG_TEXT: REORIGIN( p0, segPtr->u.t.pos, angle, xlat ) GetTextBounds( p0, angle+segPtr->u.t.angle, segPtr->u.t.string, segPtr->u.t.fontSize, lo, hi ); break; + case SEG_BEZLIN: + case SEG_BEZTRK: //Bezier control arms form a "tent" around the curve + REORIGIN( pBez[0], segPtr->u.b.pos[0], angle, xlat ) + REORIGIN( pBez[1], segPtr->u.b.pos[1], angle, xlat ) + REORIGIN( pBez[2], segPtr->u.b.pos[2], angle, xlat ) + REORIGIN( pBez[3], segPtr->u.b.pos[3], angle, xlat ) + lo->x = hi->x = pBez[0].x; + lo->y = hi->y = pBez[0].y; + for (int i=1;i<4;i++) { + lo->x = lo->x>pBez[i].x?pBez[i].x:lo->x; + lo->y = lo->y>pBez[i].y?pBez[i].y:lo->y; + hi->x = hi->x<pBez[i].x?pBez[i].x:hi->x; + hi->y = hi->y<pBez[i].y?pBez[i].y:hi->y; + } + width.x = width.y = segPtr->width/2.0; + break; default: ; } @@ -379,6 +439,14 @@ EXPORT void MoveSegs( s->u.j.pos.x += orig.x; s->u.j.pos.y += orig.y; break; + case SEG_BEZTRK: + case SEG_BEZLIN: + for (inx=0;inx<4;inx++) { + s->u.b.pos[inx].x +=orig.x; + s->u.b.pos[inx].y +=orig.y; + } + FixUpBezierSeg(s->u.b.pos,s,s->type == SEG_BEZTRK); + break; } } } @@ -423,11 +491,18 @@ EXPORT void RotateSegs( Rotate( &s->u.j.pos, orig, angle ); s->u.j.angle = NormalizeAngle( s->u.j.angle+angle ); break; - } + case SEG_BEZLIN: + case SEG_BEZTRK: + Rotate( &s->u.b.pos[0], orig, angle ); + Rotate( &s->u.b.pos[1], orig, angle ); + Rotate( &s->u.b.pos[2], orig, angle ); + Rotate( &s->u.b.pos[3], orig, angle ); + FixUpBezierSeg(s->u.b.pos,s,s->type == SEG_BEZTRK); + break; + } } } - EXPORT void FlipSegs( wIndex_t segCnt, trkSeg_p segs, @@ -468,12 +543,21 @@ EXPORT void FlipSegs( for (inx=0; inx<s->u.p.cnt; inx++) { s->u.p.pts[inx].y = -s->u.p.pts[inx].y; } + MyFree(pts); break; case SEG_JNTTRK: s->u.j.pos.y = - s->u.j.pos.y; s->u.j.angle = NormalizeAngle( 180.0 - s->u.j.angle ); s->u.j.negate = ! s->u.j.negate; break; + case SEG_BEZTRK: + case SEG_BEZLIN: + s->u.b.pos[0].y = -s->u.b.pos[0].y; + s->u.b.pos[1].y = -s->u.b.pos[1].y; + s->u.b.pos[2].y = -s->u.b.pos[2].y; + s->u.b.pos[3].y = -s->u.b.pos[3].y; + FixUpBezierSeg(s->u.b.pos,s,s->type == SEG_BEZTRK); + break; } } } @@ -529,6 +613,20 @@ EXPORT void RescaleSegs( s->u.j.l0 *= scale_w; s->u.j.l1 *= scale_w; break; + case SEG_BEZTRK: + case SEG_BEZLIN: + s->u.b.pos[0].y *= scale_y; + s->u.b.pos[0].x *= scale_x; + s->u.b.pos[1].x *= scale_x; + s->u.b.pos[1].y *= scale_y; + s->u.b.pos[2].y *= scale_y; + s->u.b.pos[2].x *= scale_x; + s->u.b.pos[3].x *= scale_x; + s->u.b.pos[3].y *= scale_y; + FixUpBezierSeg(s->u.b.pos,s,s->type == SEG_BEZTRK); + + break; + } } } @@ -556,10 +654,20 @@ EXPORT void CloneFilledDraw( } else { memcpy( newPts, sp->u.p.pts, sp->u.p.cnt * sizeof *(coOrd*)0 ); } + //if (sp->u.p.pts) Can't do this a pts could be pointing at static + // free(sp->u.p.pts); sp->u.p.pts = newPts; break; case SEG_TEXT: - sp->u.t.string = MyStrdup( sp->u.t.string ); + sp->u.t.string = strdup( sp->u.t.string); + break; + case SEG_BEZTRK: + case SEG_BEZLIN: + sp->bezSegs.cnt = 0; + if (sp->bezSegs.ptr) MyFree(sp->bezSegs.ptr); + sp->bezSegs.ptr = NULL; + sp->bezSegs.max = 0; + FixUpBezierSeg(sp->u.b.pos,sp,sp->type == SEG_BEZTRK); break; default: break; @@ -583,8 +691,8 @@ EXPORT void FreeFilledDraw( sp->u.p.pts = NULL; break; case SEG_TEXT: - if ( sp->u.t.string ) - MyFree( sp->u.t.string ); + if (sp->u.t.string) + MyFree(sp->u.t.string); sp->u.t.string = NULL; break; default: @@ -593,6 +701,13 @@ EXPORT void FreeFilledDraw( } } +/* + * DistanceSegs + * + * Find the closest point on the Segs to the point pos. + * Return the distance to the point, the point on the curve and the index of the segment that contains it. + * + */ EXPORT DIST_T DistanceSegs( coOrd orig, @@ -606,6 +721,7 @@ EXPORT DIST_T DistanceSegs( coOrd p0, p1, p2, pt, lo, hi; BOOL_T found = FALSE; wIndex_t inx, lin; + segProcData_t segProcData2; p0 = *pos; Rotate( &p0, orig, -angle ); p0.x -= orig.x; @@ -645,27 +761,41 @@ EXPORT DIST_T DistanceSegs( } } break; + case SEG_BEZTRK: + case SEG_BEZLIN: + dd = 100000.0; + pt = p0; + for (int i = 0;i<segPtr->bezSegs.cnt;i++) { + segProcData2.distance.pos1 = pt; + SegProc(SEGPROC_DISTANCE,&DYNARR_N(trkSeg_t,segPtr->bezSegs,i),&segProcData2); + if (segProcData2.distance.dd<dd) { + dd = segProcData2.distance.dd; + p1 = segProcData2.distance.pos1; + } + } + break; case SEG_TEXT: /*GetTextBounds( segPtr->u.t.pos, angle+segPtr->u.t.angle, segPtr->u.t.string, segPtr->u.t.fontSize, &lo, &hi );*/ - GetTextBounds( zero, 0, segPtr->u.t.string, segPtr->u.t.fontSize, &lo, &hi ); - Rotate( &p0, segPtr->u.t.pos, segPtr->u.t.angle ); + GetTextBounds( zero, 0, segPtr->u.t.string, segPtr->u.t.fontSize, &lo, &hi ); //lo and hi are relative to seg origin p0.x -= segPtr->u.t.pos.x; p0.y -= segPtr->u.t.pos.y; - if ( p0.x < hi.x && p0.y < hi.y ) { - DIST_T dx, dy; + Rotate( &p0, zero, -segPtr->u.t.angle ); + if (p0.x > lo.x && p0.x < hi.x && p0.y >lo.y && p0.y < hi.y) { //Within rectangle - therefore small dist hi.x /= 2.0; hi.y /= 2.0; - p0.x -= hi.x; - p0.y -= hi.y; - dx = fabs(p0.x/hi.x); - dy = fabs(p0.y/hi.y); - if ( dx > dy ) - dd = dx; - else - dd = dy; - dd *= 0.25*mainD.scale; - /*printf( "dx=%0.4f dy=%0.4f dd=%0.3f\n", dx, dy, dd );*/ + dd = 0.1*FindDistance(hi, p0)/FindDistance(lo,hi); // Proportion to mean that the closer we to the center or the smaller the target in overlapping cases, the more likely we pick it + break; } + hi.x /= 2.0; // rough center of rectangle + hi.y /= 2.0; + if (fabs((p0.x-hi.x)/hi.x)<fabs((p0.y-hi.y)/hi.y)) { // Proportionally closer to x + if (p0.x > hi.x) dd = (p0.x - hi.x); + else dd = fabs(p0.x-hi.x); + } else { // Closer to y + if (p0.y > hi.y) dd = (p0.y - hi.y); + else dd = fabs(p0.y-hi.y); + } + /*printf( "dx=%0.4f dy=%0.4f dd=%0.3f\n", dx, dy, dd );*/ /* if ( p0.x >= lo.x && p0.x <= hi.x && p0.y >= lo.y && p0.y <= hi.y ) { @@ -698,22 +828,35 @@ EXPORT DIST_T DistanceSegs( return d; } - +/* + * Get the angle at a point on the segments closest to pos1 + * Optionally return the index of the segment and the distance to that point + * + */ EXPORT ANGLE_T GetAngleSegs( wIndex_t segCnt, trkSeg_p segPtr, - coOrd pos, - wIndex_t * segInxR ) + coOrd * pos1, // Now IN/OUT OUT = + wIndex_t * segInxR, + DIST_T * dist, + BOOL_T * seg_backwards, + wIndex_t * subSegInxR, + BOOL_T * negative_radius) { wIndex_t inx; ANGLE_T angle = 0.0; coOrd p0; DIST_T d, dd; segProcData_t segProcData; + coOrd pos2 = * pos1; + BOOL_T negative = FALSE; + BOOL_T backwards = FALSE; + if (subSegInxR) *subSegInxR = -1; - DistanceSegs( zero, 0.0, segCnt, segPtr, &pos, &inx ); + d = DistanceSegs( zero, 0.0, segCnt, segPtr, &pos2, &inx ); // + if (dist) * dist = d; segPtr += inx; - segProcData.getAngle.pos = pos; + segProcData.getAngle.pos = pos2; switch ( segPtr->type ) { case SEG_STRTRK: case SEG_STRLIN: @@ -728,18 +871,28 @@ EXPORT ANGLE_T GetAngleSegs( case SEG_FILCRCL: CurveSegProc( SEGPROC_GETANGLE, segPtr, &segProcData ); angle = segProcData.getAngle.angle; + negative = segProcData.getAngle.negative_radius; + backwards = segProcData.getAngle.backwards; break; case SEG_JNTTRK: JointSegProc( SEGPROC_GETANGLE, segPtr, &segProcData ); angle = segProcData.getAngle.angle; break; + case SEG_BEZTRK: + case SEG_BEZLIN: + BezierSegProc( SEGPROC_GETANGLE, segPtr, &segProcData ); + angle = segProcData.getAngle.angle; + negative = segProcData.getAngle.negative_radius; + backwards = segProcData.getAngle.backwards; + if (subSegInxR) *subSegInxR = segProcData.getAngle.bezSegInx; + break; case SEG_POLY: case SEG_FILPOLY: - p0 = pos; + p0 = pos2; dd = LineDistance( &p0, segPtr->u.p.pts[segPtr->u.p.cnt-1], segPtr->u.p.pts[0] ); angle = FindAngle( segPtr->u.p.pts[segPtr->u.p.cnt-1], segPtr->u.p.pts[0] ); for ( inx=0; inx<segPtr->u.p.cnt-1; inx++ ) { - p0 = pos; + p0 = pos2; d = LineDistance( &p0, segPtr->u.p.pts[inx], segPtr->u.p.pts[inx+1] ); if ( d < dd ) { dd = d; @@ -754,6 +907,10 @@ EXPORT ANGLE_T GetAngleSegs( AbortProg( "GetAngleSegs(%d)", segPtr->type ); } if ( segInxR ) *segInxR = inx; + if (seg_backwards) *seg_backwards = backwards; + if (negative_radius) *negative_radius = negative; + + * pos1 = pos2; return angle; } @@ -970,12 +1127,17 @@ EXPORT BOOL_T ReadSegs( void ) BOOL_T rc=FALSE; trkSeg_p s; trkEndPt_p e; - unsigned long rgb; + long rgb; int i; DIST_T elev0, elev1; BOOL_T hasElev; + BOOL_T isPolyV2; + BOOL_T improvedEnds; + FLOAT_T ignoreFloat; char type; - long option; + char * plain_text; + long option, option2; + BOOL_T subsegs = FALSE; descriptionOff = zero; tempSpecial[0] = '\0'; @@ -984,12 +1146,22 @@ EXPORT BOOL_T ReadSegs( void ) DYNARR_RESET( trkEndPt_t, tempEndPts_da ); pathCnt = 0; while ( (cp = GetNextLine()) != NULL ) { - while (isspace((unsigned char)*cp)) cp++; + while (isspace(*cp)) cp++; hasElev = FALSE; + improvedEnds = FALSE; if ( strncmp( cp, "END", 3 ) == 0 ) { rc = TRUE; + subsegs = FALSE; break; } + if ( strncmp(cp, "SUBSEGS", 7) == 0) { + subsegs = TRUE; + continue; + } + if (strncmp (cp, "SUBSEND", 7) == 0) { + subsegs = FALSE; + continue; + } if ( *cp == '\n' || *cp == '#' ) { continue; } @@ -999,13 +1171,20 @@ EXPORT BOOL_T ReadSegs( void ) cp++; hasElev = TRUE; } + isPolyV2 = FALSE; + if (*cp == '4') { + cp++; + hasElev = TRUE; + isPolyV2 = TRUE; + improvedEnds = TRUE; + } switch (type) { case SEG_STRLIN: case SEG_TBLEDGE: DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 ); s = &tempSegs(tempSegs_da.cnt-1); s->type = type; - if ( !GetArgs( cp, hasElev?"uwpfpf":"uwpYpY", + if ( !GetArgs( cp, hasElev?"lwpfpf":"lwpYpY", &rgb, &s->width, &s->u.l.pos[0], &elev0, &s->u.l.pos[1], &elev1 ) ) { rc = FALSE; break; @@ -1018,7 +1197,7 @@ EXPORT BOOL_T ReadSegs( void ) DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 ); s = &tempSegs(tempSegs_da.cnt-1); s->type = type; - if ( !GetArgs( cp, hasElev?"uwpfpfl":"uwpYpYZ", + if ( !GetArgs( cp, hasElev?"lwpfpfl":"lwpYpYZ", &rgb, &s->width, &s->u.l.pos[0], &elev0, &s->u.l.pos[1], &elev1, &option ) ) { rc = FALSE; break; @@ -1033,7 +1212,7 @@ EXPORT BOOL_T ReadSegs( void ) DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 ); s = &tempSegs(tempSegs_da.cnt-1); s->type = SEG_CRVLIN; - if ( !GetArgs( cp, hasElev?"uwfpfff":"uwfpYff", + if ( !GetArgs( cp, hasElev?"lwfpfff":"lwfpYff", &rgb, &s->width, &s->u.c.radius, &s->u.c.center, @@ -1048,20 +1227,27 @@ EXPORT BOOL_T ReadSegs( void ) DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 ); s = &tempSegs(tempSegs_da.cnt-1); s->type = SEG_STRTRK; - if ( !GetArgs( cp, hasElev?"uwpfpf":"uwpYpY", + s->bezSegs.max = 0; + s->bezSegs.cnt = 0; + s->bezSegs.ptr = NULL; + if ( !GetArgs( cp, hasElev?"lwpfpf":"lwpYpY", &rgb, &s->width, &s->u.l.pos[0], &elev0, &s->u.l.pos[1], &elev1 ) ) { rc = FALSE; break; } + rgb = 0; s->color = wDrawFindColor( rgb ); break; case SEG_CRVTRK: DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 ); s = &tempSegs(tempSegs_da.cnt-1); s->type = SEG_CRVTRK; - if ( !GetArgs( cp, hasElev?"uwfpfff":"uwfpYff", + s->bezSegs.max = 0; + s->bezSegs.cnt = 0; + s->bezSegs.ptr = NULL; + if ( !GetArgs( cp, hasElev?"lwfpfff":"lwfpYff", &rgb, &s->width, &s->u.c.radius, &s->u.c.center, @@ -1070,13 +1256,14 @@ EXPORT BOOL_T ReadSegs( void ) rc = FALSE; break; } + rgb = 0; s->color = wDrawFindColor( rgb ); break; case SEG_JNTTRK: DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 ); s = &tempSegs(tempSegs_da.cnt-1); s->type = SEG_JNTTRK; - if ( !GetArgs( cp, hasElev?"uwpffffffl":"uwpYfffffl", + if ( !GetArgs( cp, hasElev?"lwpffffffl":"lwpYfffffl", &rgb, &s->width, &s->u.j.pos, &elev0, @@ -1092,13 +1279,51 @@ EXPORT BOOL_T ReadSegs( void ) s->u.j.negate = ( option&1 )!=0; s->u.j.flip = ( option&2 )!=0; s->u.j.Scurve = ( option&4 )!=0; + rgb = 0; s->color = wDrawFindColor( rgb ); break; + case SEG_BEZTRK: + DYNARR_APPEND( trkSeg_t, tempSegs_da, 10); + s = &tempSegs(tempSegs_da.cnt-1); + s->type=SEG_BEZTRK; + s->bezSegs.max=0; + s->bezSegs.ptr= NULL; + s->bezSegs.cnt=0; + if ( !GetArgs( cp, "lwpppp", + &rgb, &s->width, + &s->u.b.pos[0], + &s->u.b.pos[1], + &s->u.b.pos[2], + &s->u.b.pos[3])) { + rc = FALSE; + break; + } + rgb = 0; + s->color = wDrawFindColor( rgb ); + break; + case SEG_BEZLIN: + DYNARR_APPEND( trkSeg_t, tempSegs_da, 10); + s = &tempSegs(tempSegs_da.cnt-1); + s->type=SEG_BEZLIN; + s->bezSegs.max=0; + s->bezSegs.ptr= NULL; + s->bezSegs.cnt=0; + if ( !GetArgs( cp, "lwpppp", + &rgb, &s->width, + &s->u.b.pos[0], + &s->u.b.pos[1], + &s->u.b.pos[2], + &s->u.b.pos[3])) { + rc = FALSE; + break; + } + s->color = wDrawFindColor( rgb ); + break; case SEG_FILCRCL: DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 ); s = &tempSegs(tempSegs_da.cnt-1); s->type = SEG_FILCRCL; - if ( !GetArgs( cp, hasElev?"uwfpf":"uwfpY", + if ( !GetArgs( cp, hasElev?"lwfpf":"lwfpY", &rgb, &s->width, &s->u.c.radius, &s->u.c.center, @@ -1115,11 +1340,20 @@ EXPORT BOOL_T ReadSegs( void ) DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 ); s = &tempSegs(tempSegs_da.cnt-1); s->type = type; - if ( !GetArgs( cp, "uwd", - &rgb, &s->width, - &s->u.p.cnt ) ) { - rc = FALSE; - /*??*/break; + if (isPolyV2) { + if ( !GetArgs( cp, "lwdd", + &rgb, &s->width, + &s->u.p.cnt, &s->u.p.polyType) ) { + rc = FALSE; + /*??*/break; + } + } else { + if ( !GetArgs( cp, "lwd", + &rgb, &s->width, + &s->u.p.cnt) ) { + rc = FALSE; + /*??*/break; + } } s->color = wDrawFindColor( rgb ); s->u.p.pts = (coOrd*)MyMalloc( s->u.p.cnt * sizeof *(coOrd*)NULL ); @@ -1138,10 +1372,14 @@ EXPORT BOOL_T ReadSegs( void ) s = &tempSegs(tempSegs_da.cnt-1); s->type = type; s->u.t.fontP = NULL; - if ( !GetArgs( cp, "upf0fq", &rgb, &s->u.t.pos, &s->u.t.angle, &s->u.t.fontSize, &s->u.t.string ) ) { + char * expandedText; + if ( !GetArgs( cp, "lpf0fq", &rgb, &s->u.t.pos, &s->u.t.angle, &s->u.t.fontSize, &expandedText ) ) { rc = FALSE; /*??*/break; } + plain_text = ConvertFromEscapedText(expandedText); + s->u.t.string = plain_text; + MyFree(expandedText); s->color = wDrawFindColor( rgb ); break; case SEG_UNCEP: @@ -1150,8 +1388,8 @@ EXPORT BOOL_T ReadSegs( void ) e = &tempEndPts(tempEndPts_da.cnt-1); if (type == SEG_CONEP) { if ( !GetArgs( cp, "dc", &e->index, &cp ) ) { - rc = FALSE; - /*??*/break; + rc = FALSE; + /*??*/break; } } else { e->index = -1; @@ -1165,6 +1403,27 @@ EXPORT BOOL_T ReadSegs( void ) e->elev.u.height = 0.0; e->elev.doff = zero; e->option = 0; + if (improvedEnds) { //E4 and T4 + if (!GetArgs( cp, "lpc", &option, &e->elev.doff, &cp )) { + rc = FALSE; + /*??*/break; + } + switch (option&ELEV_MASK) { + case ELEV_STATION: + GetArgs( cp, "qc", &e->elev.u.name, &cp); + break; + default: + GetArgs( cp, "fc", &e->elev.u.height, &cp); //First height + } + DIST_T height2; + if (!GetArgs( cp, "flLlc", &height2, &option2, &e->elev.option, &e->option, &cp ) ) { + rc = FALSE; + break; + } + if (option2) e->elev.option |= ELEV_VISIBLE; + GetArgs(cp, "fc", &ignoreFloat, &cp); + break; + } if ( cp != NULL ) { if (paramVersion < 7) { GetArgs( cp, "dfp", &e->elev.option, &e->elev.u.height, &e->elev.doff, &cp ); @@ -1188,7 +1447,7 @@ EXPORT BOOL_T ReadSegs( void ) } break; case SEG_PATH: - while (isspace((unsigned char)*cp)) cp++; + while (isspace(*cp)) cp++; if (*cp == '\"') cp++; while ( *cp != '\"') AppendPath((signed char)*cp++); AppendPath(0); @@ -1220,55 +1479,34 @@ EXPORT BOOL_T ReadSegs( void ) } } AppendPath( 0 ); - -#ifdef LATER - if ( logTable(log_readTracks).level >= 4 ) { - for (s=&tempSegs(0); s<&tempSegs(tempSegs_da.cnt); s++) { - switch (s->type) { - case SEG_STRTRK: - case SEG_STRLIN: - case SEG_DIMLIN: - case SEG_BENCH: - case SEG_TBLEDGE: - LogPrintf( "seg[%d] = %c [%0.3f %0.3f] [%0.3f %0.3f]\n", - tempSegs_da.cnt, s->type, - s->u.l.pos[0].x, s->u.l.pos[0].y, - s->u.l.pos[1].x, s->u.l.pos[1].y ); - break; - case SEG_CRVTRK: - case SEG_CRVLIN: - LogPrintf( "seg[%d] = %c R=%0.3f A0=%0.3f A1=%0.3f [%0.3f %0.3f]\n", - tempSegs_da.cnt, s->type, - s->u.c.radius, - s->u.c.center.x, s->u.c.center.y, - s->u.c.a0, s->u.c.a1 ); - break; - case SEG_JNTTRK: - LogPrintf( "seg[%d] = %c\n", - tempSegs_da.cnt, s->type ); - break; - } - } - } -#endif return rc; } - EXPORT BOOL_T WriteSegs( FILE * f, wIndex_t segCnt, trkSeg_p segs ) { + return WriteSegsEnd(f,segCnt,segs,TRUE); +} + + +EXPORT BOOL_T WriteSegsEnd( + FILE * f, + wIndex_t segCnt, + trkSeg_p segs, BOOL_T writeEnd) + +{ int i, j; BOOL_T rc = TRUE; long option; + char * escaped_text; for ( i=0; i<segCnt; i++ ) { switch ( segs[i].type ) { case SEG_STRTRK: - rc &= fprintf( f, "\t%c %ld %0.6f %0.6f %0.6f %0.6f %0.6f\n", - segs[i].type, wDrawGetRGB(segs[i].color), segs[i].width, + rc &= fprintf( f, "\t%c 0 %0.6f %0.6f %0.6f %0.6f %0.6f\n", + segs[i].type, segs[i].width, segs[i].u.l.pos[0].x, segs[i].u.l.pos[0].y, segs[i].u.l.pos[1].x, segs[i].u.l.pos[1].y ) > 0; break; @@ -1294,16 +1532,16 @@ EXPORT BOOL_T WriteSegs( BenchOutputOption(segs[i].u.l.option) ) > 0; break; case SEG_CRVTRK: - rc &= fprintf( f, "\t%c %ld %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f\n", - segs[i].type, wDrawGetRGB(segs[i].color), segs[i].width, + rc &= fprintf( f, "\t%c 0 %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f\n", + segs[i].type, segs[i].width, segs[i].u.c.radius, segs[i].u.c.center.x, segs[i].u.c.center.y, segs[i].u.c.a0, segs[i].u.c.a1 ) > 0; break; case SEG_JNTTRK: option = (segs[i].u.j.negate?1:0) + (segs[i].u.j.flip?2:0) + (segs[i].u.j.Scurve?4:0); - rc &= fprintf( f, "\t%c %ld %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %ld\n", - segs[i].type, wDrawGetRGB(segs[i].color), segs[i].width, + rc &= fprintf( f, "\t%c 0 %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %ld\n", + segs[i].type, segs[i].width, segs[i].u.j.pos.x, segs[i].u.j.pos.y, segs[i].u.j.angle, segs[i].u.j.l0, @@ -1312,12 +1550,25 @@ EXPORT BOOL_T WriteSegs( segs[i].u.j.L, option )>0; break; + case SEG_BEZTRK: + case SEG_BEZLIN: + rc &= fprintf( f, "\t%c3 0 %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f\n", + segs[i].type, segs[i].width, + segs[i].u.l.pos[0].x, segs[i].u.l.pos[0].y, + segs[i].u.l.pos[1].x, segs[i].u.l.pos[1].y, + segs[i].u.l.pos[2].x, segs[i].u.l.pos[2].y, + segs[i].u.l.pos[3].x, segs[i].u.l.pos[3].y ) > 0; + rc &= fprintf(f,"\tSUBSEGS\n"); + rc &= WriteSegsEnd(f,segs[i].bezSegs.cnt,segs[i].bezSegs.ptr,FALSE); + rc &= fprintf(f,"\tSUBSEND\n"); + break; case SEG_CRVLIN: rc &= fprintf( f, "\t%c3 %ld %0.6f %0.6f %0.6f %0.6f 0 %0.6f %0.6f\n", segs[i].type, wDrawGetRGB(segs[i].color), segs[i].width, segs[i].u.c.radius, segs[i].u.c.center.x, segs[i].u.c.center.y, segs[i].u.c.a0, segs[i].u.c.a1 ) > 0; + break; case SEG_FILCRCL: rc &= fprintf( f, "\t%c3 %ld %0.6f %0.6f %0.6f %0.6f 0\n", @@ -1327,22 +1578,24 @@ EXPORT BOOL_T WriteSegs( break; case SEG_POLY: case SEG_FILPOLY: - rc &= fprintf( f, "\t%c3 %ld %0.6f %d\n", + rc &= fprintf( f, "\t%c4 %ld %0.6f %d %d \n", segs[i].type, wDrawGetRGB(segs[i].color), segs[i].width, - segs[i].u.p.cnt ) > 0; + segs[i].u.p.cnt, segs[i].u.p.polyType ) > 0; for ( j=0; j<segs[i].u.p.cnt; j++ ) rc &= fprintf( f, "\t\t%0.6f %0.6f 0\n", segs[i].u.p.pts[j].x, segs[i].u.p.pts[j].y ) > 0; break; case SEG_TEXT: /* 0pf0fq */ + escaped_text = ConvertToEscapedText(segs[i].u.t.string); rc &= fprintf( f, "\t%c %ld %0.6f %0.6f %0.6f 0 %0.6f \"%s\"\n", segs[i].type, wDrawGetRGB(segs[i].color), segs[i].u.t.pos.x, segs[i].u.t.pos.y, segs[i].u.t.angle, - segs[i].u.t.fontSize, PutTitle(segs[i].u.t.string) ) > 0; + segs[i].u.t.fontSize, escaped_text ) > 0; + MyFree(escaped_text); break; } } - rc &= fprintf( f, "\tEND\n" )>0; + if (writeEnd) rc &= fprintf( f, "\tEND\n" )>0; return rc; } @@ -1354,20 +1607,27 @@ EXPORT void SegProc( { switch (segPtr->type) { case SEG_STRTRK: + case SEG_STRLIN: StraightSegProc( cmd, segPtr, data ); break; case SEG_CRVTRK: + case SEG_CRVLIN: CurveSegProc( cmd, segPtr, data ); break; case SEG_JNTTRK: JointSegProc( cmd, segPtr, data ); break; - default: + case SEG_BEZTRK: + case SEG_BEZLIN: + BezierSegProc( cmd, segPtr, data); + break; + default: AbortProg( "SegProg( %d )", segPtr->type ); break; } } + /* * Draw Segs @@ -1456,6 +1716,10 @@ EXPORT void DrawDimLine( DrawLine( d, p, p1, 0, color ); } +/* + * Display the array of segments. + * Note that Bezier segments in particular contain sub-arrays of Curve and Straight segments. + */ EXPORT void DrawSegsO( drawCmd_p d, track_p trk, @@ -1468,13 +1732,12 @@ EXPORT void DrawSegsO( long options ) { wIndex_t i, j; - coOrd p0, p1, c; + coOrd p0, p1, p2, p3, c; ANGLE_T a0; wDrawColor color1, color2; DIST_T factor = d->dpi/d->scale; trkSeg_p tempPtr; - static dynArr_t tempPts_da; -#define tempPts(N) DYNARR_N( coOrd, tempPts_da, N ) + long option; wFontSize_t fs; @@ -1503,13 +1766,33 @@ EXPORT void DrawSegsO( REORIGIN( p0, segPtr->u.j.pos, angle, orig ); DrawJointTrack( d, p0, NormalizeAngle(segPtr->u.j.angle+angle), segPtr->u.j.l0, segPtr->u.j.l1, segPtr->u.j.R, segPtr->u.j.L, segPtr->u.j.negate, segPtr->u.j.flip, segPtr->u.j.Scurve, trk, -1, -1, trackGauge, color1, options ); break; - } + case SEG_BEZTRK: + REORIGIN(p0, segPtr->u.b.pos[0], angle, orig); + REORIGIN(p1, segPtr->u.b.pos[1], angle, orig); + REORIGIN(p2, segPtr->u.b.pos[2], angle, orig); + REORIGIN(p3, segPtr->u.b.pos[3], angle, orig); + tempPtr = segPtr->bezSegs.ptr; + for(int j=0;j<segPtr->bezSegs.cnt;j++,tempPtr++) { //Loop through sub parts (only Trks supported) + if (tempPtr->type == SEG_CRVTRK) { + a0 = NormalizeAngle(tempPtr->u.c.a0 + angle); + REORIGIN( c, tempPtr->u.c.center, angle, orig ); + DrawCurvedTies( d, trk, c, fabs(tempPtr->u.c.radius), a0, tempPtr->u.c.a1, color ); + } + if (tempPtr->type == SEG_STRTRK) { + REORIGIN( p0, tempPtr->u.l.pos[0], angle, orig ) + REORIGIN( p1, tempPtr->u.l.pos[1], angle, orig ) + DrawStraightTies( d, trk, p0, p1, color ); + } + } + break; + } continue; } switch (segPtr->type) { case SEG_STRTRK: case SEG_CRVTRK: case SEG_JNTTRK: + case SEG_BEZTRK: case SEG_TEXT: break; default: @@ -1593,24 +1876,79 @@ EXPORT void DrawSegsO( FALSE, (wDrawWidth)floor(segPtr->width*factor+0.5), color1 ); } break; + case SEG_BEZTRK: + case SEG_BEZLIN: + if (segPtr->type == SEG_BEZTRK) { + if (color1 == wDrawColorBlack) + color1 = normalColor; + if ( segPtr->color == wDrawColorWhite ) + break; + } + REORIGIN(p0, segPtr->u.b.pos[0], angle, orig); + REORIGIN(p1, segPtr->u.b.pos[1], angle, orig); + REORIGIN(p2, segPtr->u.b.pos[2], angle, orig); + REORIGIN(p3, segPtr->u.b.pos[3], angle, orig); + + for(int j=0;j<segPtr->bezSegs.cnt;j++) { //Loop through sub Segs + tempPtr = &DYNARR_N(trkSeg_t,segPtr->bezSegs,j); + switch (tempPtr->type) { + case SEG_CRVTRK: + case SEG_CRVLIN: + a0 = NormalizeAngle(tempPtr->u.c.a0 + angle); + REORIGIN( c, tempPtr->u.c.center, angle, orig ); + if (tempPtr->type == SEG_CRVTRK) { + if (color1 == wDrawColorBlack) color1 = normalColor; + if ( tempPtr->color == wDrawColorWhite ) break; + p0.x = p0.y = p1.x = p1.y = 0; + DrawCurvedTrack( d, + c, + fabs(tempPtr->u.c.radius), + a0, tempPtr->u.c.a1, + p0, p1, + NULL, trackGauge, color1, options ); + } else if (tempPtr->type == SEG_CRVLIN) { + DrawArc( d, c, fabs(tempPtr->u.c.radius), a0, tempPtr->u.c.a1, + FALSE, (wDrawWidth)floor(tempPtr->width*factor+0.5), color1 ); + } + break; + case SEG_STRTRK: + if (color1 == wDrawColorBlack) color1 = normalColor; + if ( tempPtr->color == wDrawColorWhite ) break; + REORIGIN(p0,tempPtr->u.l.pos[0], angle, orig); + REORIGIN(p1,tempPtr->u.l.pos[1], angle, orig); + DrawStraightTrack( d, + p0, p1, + FindAngle(p0, p1 ), + NULL, trackGauge, color1, options ); + break; + case SEG_STRLIN: + REORIGIN(p0,tempPtr->u.l.pos[0], angle, orig); + REORIGIN(p1,tempPtr->u.l.pos[1], angle, orig); + DrawLine( d, p0, p1, (wDrawWidth)floor(tempPtr->width*factor+0.5), color1 ); + break; + } + } + break; case SEG_JNTTRK: REORIGIN( p0, segPtr->u.j.pos, angle, orig ); DrawJointTrack( d, p0, NormalizeAngle(segPtr->u.j.angle+angle), segPtr->u.j.l0, segPtr->u.j.l1, segPtr->u.j.R, segPtr->u.j.L, segPtr->u.j.negate, segPtr->u.j.flip, segPtr->u.j.Scurve, NULL, -1, -1, trackGauge, color1, options ); break; case SEG_TEXT: REORIGIN( p0, segPtr->u.t.pos, angle, orig ) - DrawString( d, p0, NormalizeAngle(angle+segPtr->u.t.angle), segPtr->u.t.string, segPtr->u.t.fontP, segPtr->u.t.fontSize, color1 ); + DrawMultiString( d, p0, segPtr->u.t.string, segPtr->u.t.fontP, segPtr->u.t.fontSize, color1, NormalizeAngle(angle + segPtr->u.t.angle), NULL, NULL ); break; case SEG_FILPOLY: if ( (d->options&DC_GROUP) == 0 && d->funcs != &tempSegDrawFuncs ) { /* Note: if we call tempSegDrawFillPoly we get a nasty bug /+ because we don't make a private copy of p.pts */ - DYNARR_SET( coOrd, tempPts_da, segPtr->u.p.cnt ); - for ( j=0; j<segPtr->u.p.cnt; j++ ) { - REORIGIN( tempPts(j), segPtr->u.p.pts[j], angle, orig ) + coOrd *tempPts = malloc(sizeof(coOrd)*segPtr->u.p.cnt); +// coOrd tempPts[segPtr->u.p.cnt]; + for (j=0;j<segPtr->u.p.cnt;j++) { + REORIGIN( tempPts[j], segPtr->u.p.pts[j], angle, orig ); } - DrawFillPoly( d, segPtr->u.p.cnt, &tempPts(0), color1 ); + DrawFillPoly( d, segPtr->u.p.cnt, tempPts, color1 ); + free(tempPts); break; } /* else fall thru */ case SEG_POLY: @@ -1646,6 +1984,9 @@ EXPORT void DrawSegsO( } +/* + * Draw Segments without setting DTS_ options. + */ EXPORT void DrawSegs( drawCmd_p d, @@ -1659,4 +2000,24 @@ EXPORT void DrawSegs( DrawSegsO( d, NULL, orig, angle, segPtr, segCnt, trackGauge, color, 0 ); } +/* + * Free dynamic storage added to each of an array of Track Segments. + */ +EXPORT void CleanSegs(dynArr_t * seg_p) { + if (seg_p->cnt ==0) return; + for (int i=0;i<seg_p->cnt;i++) { + trkSeg_t t = DYNARR_N(trkSeg_t,* seg_p,i); + if (t.type == SEG_BEZLIN || t.type == SEG_BEZTRK) { + if (t.bezSegs.ptr) MyFree(t.bezSegs.ptr); + t.bezSegs.cnt = 0; + t.bezSegs.max = 0; + t.bezSegs.ptr = NULL; + } + } + seg_p->cnt = 0; + if (seg_p->ptr) MyFree(seg_p->ptr); + seg_p->ptr = NULL; + seg_p->max = 0; +} + |