summaryrefslogtreecommitdiff
path: root/app/bin/trkseg.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/bin/trkseg.c')
-rw-r--r--app/bin/trkseg.c599
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;
+}
+