summaryrefslogtreecommitdiff
path: root/app/bin/tcornu.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/bin/tcornu.c')
-rw-r--r--app/bin/tcornu.c377
1 files changed, 287 insertions, 90 deletions
diff --git a/app/bin/tcornu.c b/app/bin/tcornu.c
index 74a7a5e..dd09cfa 100644
--- a/app/bin/tcornu.c
+++ b/app/bin/tcornu.c
@@ -136,8 +136,8 @@ EXPORT char * CreateSegPathList(track_p trk) {
char * cp = "\0\0";
if (GetTrkType(trk) != T_CORNU) return cp;
struct extraData *xx = GetTrkExtraData(trk);
- if (xx->cornuData.cornuPath) free(xx->cornuData.cornuPath);
- xx->cornuData.cornuPath = malloc(xx->cornuData.arcSegs.cnt+2);
+ if (xx->cornuData.cornuPath) MyFree(xx->cornuData.cornuPath);
+ xx->cornuData.cornuPath = MyMalloc(xx->cornuData.arcSegs.cnt+2);
int j= 0;
for (int i = 0;i<xx->cornuData.arcSegs.cnt;i++,j++) {
xx->cornuData.cornuPath[j] = i+1;
@@ -178,17 +178,24 @@ static void ComputeCornuBoundingBox( track_p trk, struct extraData * xx )
DIST_T CornuDescriptionDistance(
coOrd pos,
- track_p trk )
+ track_p trk,
+ coOrd * dpos,
+ BOOL_T show_hidden,
+ BOOL_T * hidden)
{
struct extraData *xx = GetTrkExtraData(trk);
coOrd p1;
-
- if ( GetTrkType( trk ) != T_CORNU || ( GetTrkBits( trk ) & TB_HIDEDESC ) != 0 )
+ if (hidden) *hidden = FALSE;
+ if ( GetTrkType( trk ) != T_CORNU || ((( GetTrkBits( trk ) & TB_HIDEDESC ) != 0) && !show_hidden) )
return 100000;
- p1.x = xx->cornuData.pos[0].x + ((xx->cornuData.pos[1].x-xx->cornuData.pos[0].x)/2) + xx->cornuData.descriptionOff.x;
- p1.y = xx->cornuData.pos[0].y + ((xx->cornuData.pos[1].y-xx->cornuData.pos[0].y)/2) + xx->cornuData.descriptionOff.y;
-
+ coOrd offset = xx->cornuData.descriptionOff;
+
+ if (( GetTrkBits( trk ) & TB_HIDEDESC ) != 0) offset = zero;
+ p1.x = xx->cornuData.pos[0].x + ((xx->cornuData.pos[1].x-xx->cornuData.pos[0].x)/2) + offset.x;
+ p1.y = xx->cornuData.pos[0].y + ((xx->cornuData.pos[1].y-xx->cornuData.pos[0].y)/2) + offset.y;
+ if (hidden) *hidden = (GetTrkBits( trk ) & TB_HIDEDESC);
+ *dpos = p1;
return FindDistance( p1, pos );
}
@@ -211,8 +218,9 @@ static void DrawCornuDescription(
pos.x += xx->cornuData.descriptionOff.x;
pos.y += xx->cornuData.descriptionOff.y;
fp = wStandardFont( F_TIMES, FALSE, FALSE );
- sprintf( message, _("Cornu Curve: length=%0.3f min radius=%0.3f"),
- xx->cornuData.length, xx->cornuData.minCurveRadius);
+
+ sprintf( message, _("Cornu: len=%0.2f min_rad=%0.2f"),
+ xx->cornuData.length, (xx->cornuData.minCurveRadius>=10000.00)?0.0:xx->cornuData.minCurveRadius);
DrawBoxedString( BOX_BOX, d, pos, message, fp, (wFontSize_t)descriptionFontSize, color, 0.0 );
}
@@ -225,7 +233,6 @@ STATUS_T CornuDescriptionMove(
struct extraData *xx = GetTrkExtraData(trk);
static coOrd p0,p1;
static BOOL_T editState;
- wDrawColor color;
if (GetTrkType(trk) != T_CORNU) return C_TERMINATE;
@@ -234,24 +241,25 @@ STATUS_T CornuDescriptionMove(
switch (action) {
case C_DOWN:
+ DrawCornuDescription( trk, &mainD, wDrawColorWhite );
case C_MOVE:
case C_UP:
editState = TRUE;
p1 = pos;
- color = GetTrkColor( trk, &mainD );
xx->cornuData.descriptionOff.x = pos.x - p0.x;
xx->cornuData.descriptionOff.y = pos.y - p0.y;
- DrawCornuDescription( trk, &mainD, color );
if (action == C_UP) {
editState = FALSE;
+ wDrawColor color = GetTrkColor( trk, &mainD );
+ DrawCornuDescription( trk, &mainD, color );
}
- MainRedraw();
- MapRedraw();
return action==C_UP?C_TERMINATE:C_CONTINUE;
case C_REDRAW:
- if (editState)
- DrawLine( &mainD, p1, p0, 0, wDrawColorBlack );
+ if (editState) {
+ DrawCornuDescription( trk, &tempD, wDrawColorBlue );
+ DrawLine( &tempD, p1, p0, 0, wDrawColorBlue );
+ }
break;
}
@@ -365,18 +373,20 @@ static void UpdateCornu( track_p trk, int inx, descData_p descUpd, BOOL_T final
case R0:
if (GetTrkEndTrk(trk,0)) break;
updateEndPts = TRUE;
- xx->cornuData.r[0] = cornData.radius[0];
- Translate(&xx->cornuData.c[0],xx->cornuData.pos[0],NormalizeAngle(xx->cornuData.a[0]+90),xx->cornuData.r[0]);
+ xx->cornuData.r[0] = fabs(cornData.radius[0]);
+ Translate(&xx->cornuData.c[0],xx->cornuData.pos[0],NormalizeAngle(xx->cornuData.a[0]+90),cornData.radius[0]);
cornData.center[0] = xx->cornuData.c[0];
+ cornData.radius[0] = fabs(cornData.radius[0]);
cornuDesc[R0].mode |= DESC_CHANGE;
cornuDesc[C0].mode |= DESC_CHANGE;
break;
case R1:
if (GetTrkEndTrk(trk,1)) break;
updateEndPts = TRUE;
- xx->cornuData.r[1]= cornData.radius[1];
- Translate(&xx->cornuData.c[1],xx->cornuData.pos[1],NormalizeAngle(xx->cornuData.a[1]-90),xx->cornuData.r[1]);
+ xx->cornuData.r[1]= fabs(cornData.radius[1]);
+ Translate(&xx->cornuData.c[1],xx->cornuData.pos[1],NormalizeAngle(xx->cornuData.a[1]-90),cornData.radius[1]);
cornData.center[1] = xx->cornuData.c[1];
+ cornData.radius[1] = fabs(cornData.radius[1]);
cornuDesc[R1].mode |= DESC_CHANGE;
cornuDesc[C1].mode |= DESC_CHANGE;
break;
@@ -384,7 +394,7 @@ static void UpdateCornu( track_p trk, int inx, descData_p descUpd, BOOL_T final
case Z1:
ep = (inx==Z0?0:1);
UpdateTrkEndElev( trk, ep, GetTrkEndElevUnmaskedMode(trk,ep), cornData.elev[ep], NULL );
- ComputeElev( trk, 1-ep, FALSE, &cornData.elev[1-ep], NULL );
+ ComputeElev( trk, 1-ep, FALSE, &cornData.elev[1-ep], NULL, TRUE );
if ( cornData.length > minLength )
cornData.grade = fabs( (cornData.elev[0]-cornData.elev[1])/cornData.length )*100.0;
else
@@ -417,7 +427,7 @@ static void UpdateCornu( track_p trk, int inx, descData_p descUpd, BOOL_T final
ts[0] = GetTrkEndTrk(trk,0);
ts[1] = GetTrkEndTrk(trk,1);
SetUpCornuParmFromTracks(ts,&cp,xx);
- CallCornu(xx->cornuData.pos, tracks, NULL, &xx->cornuData.arcSegs, &cp);
+ CallCornu0(xx->cornuData.pos, xx->cornuData.c, xx->cornuData.a, xx->cornuData.r, &xx->cornuData.arcSegs, FALSE);
//FixUpCornu(xx->bezierData.pos, xx, IsTrack(trk));
ComputeCornuBoundingBox(trk, xx);
@@ -454,8 +464,8 @@ static void DescribeCornu( track_p trk, char * str, CSIZE_T len )
cornData.radius[0] = xx->cornuData.r[0];
cornData.radius[1] = xx->cornuData.r[1];
if (GetTrkType(trk) == T_CORNU) {
- ComputeElev( trk, 0, FALSE, &cornData.elev[0], NULL );
- ComputeElev( trk, 1, FALSE, &cornData.elev[1], NULL );
+ ComputeElev( trk, 0, FALSE, &cornData.elev[0], NULL, FALSE );
+ ComputeElev( trk, 1, FALSE, &cornData.elev[1], NULL, FALSE );
if ( cornData.length > minLength )
cornData.grade = fabs( (cornData.elev[0]-cornData.elev[1])/cornData.length )*100.0;
@@ -517,30 +527,16 @@ static void DrawCornu( track_p t, drawCmd_p d, wDrawColor color )
struct extraData *xx = GetTrkExtraData(t);
long widthOptions = DTS_LEFT|DTS_RIGHT;
- if (GetTrkWidth(t) == 2)
- widthOptions |= DTS_THICK2;
- if (GetTrkWidth(t) == 3)
- widthOptions |= DTS_THICK3;
-
-
- if ( ((d->funcs->options&wDrawOptTemp)==0) &&
+ if ( ((d->options&DC_SIMPLE)==0) &&
(labelWhen == 2 || (labelWhen == 1 && (d->options&DC_PRINT))) &&
labelScale >= d->scale &&
( GetTrkBits( t ) & TB_HIDEDESC ) == 0 ) {
DrawCornuDescription( t, d, color );
}
DIST_T scale2rail = (d->options&DC_PRINT)?(twoRailScale*2+1):twoRailScale;
- if ( tieDrawMode!=TIEDRAWMODE_NONE &&
- d!=&mapD &&
- (d->options&DC_TIES)!=0 &&
- d->scale<scale2rail/2 )
- DrawSegsO(d,t,zero,0.0,xx->cornuData.arcSegs.ptr,xx->cornuData.arcSegs.cnt, GetTrkGauge(t), color, widthOptions|DTS_TIES);
DrawSegsO(d,t,zero,0.0,xx->cornuData.arcSegs.ptr,xx->cornuData.arcSegs.cnt, GetTrkGauge(t), color, widthOptions);
- if ( (d->funcs->options & wDrawOptTemp) == 0 &&
- (d->options&DC_QUICK) == 0 ) {
- DrawEndPt( d, t, 0, color );
- DrawEndPt( d, t, 1, color );
- }
+ DrawEndPt( d, t, 0, color );
+ DrawEndPt( d, t, 1, color );
}
void FreeSubSegs(trkSeg_t* s) {
@@ -579,7 +575,7 @@ static BOOL_T WriteCornu( track_p t, FILE * f )
if ( ( GetTrkBits(t) & TB_HIDEDESC ) == 0 ) options |= 0x80;
rc &= fprintf(f, "%s %d %d %ld 0 0 %s %d %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f %0.6f \n",
"CORNU",GetTrkIndex(t), GetTrkLayer(t), (long)options,
- GetTrkScaleName(t), GetTrkVisible(t),
+ GetTrkScaleName(t), GetTrkVisible(t)|(GetTrkNoTies(t)?1<<2:0)|(GetTrkBridge(t)?1<<3:0),
xx->cornuData.pos[0].x, xx->cornuData.pos[0].y,
xx->cornuData.a[0],
xx->cornuData.r[0],
@@ -593,11 +589,10 @@ static BOOL_T WriteCornu( track_p t, FILE * f )
rc &= WriteEndPt( f, t, 1 );
}
rc &= WriteSegs( f, xx->cornuData.arcSegs.cnt, xx->cornuData.arcSegs.ptr );
- //rc &= fprintf(f, "\tEND\n" )>0;
return rc;
}
-static void ReadCornu( char * line )
+static BOOL_T ReadCornu( char * line )
{
struct extraData *xx;
track_p t;
@@ -613,12 +608,16 @@ static void ReadCornu( char * line )
if (!GetArgs( line+6, "dLl00sdpffppffp",
&index, &layer, &options, scale, &visible, &p0, &a0, &r0, &c0, &p1, &a1, &r1, &c1 ) ) {
- return;
+ return FALSE;
}
+ if ( !ReadSegs() )
+ return FALSE;
t = NewTrack( index, T_CORNU, 0, sizeof *xx );
xx = GetTrkExtraData(t);
- SetTrkVisible(t, visible);
+ SetTrkVisible(t, visible&2);
+ SetTrkNoTies(t, visible&4);
+ SetTrkBridge(t, visible&8);
SetTrkScale(t, LookupScale(scale));
SetTrkLayer(t, layer );
SetTrkWidth(t, (int)(options&0x0F));
@@ -632,10 +631,10 @@ static void ReadCornu( char * line )
xx->cornuData.c[1] = c1;
xx->cornuData.r[1] = r1;
xx->cornuData.descriptionOff.x = xx->cornuData.descriptionOff.y = 0.0;
- ReadSegs();
FixUpCornu0(xx->cornuData.pos,xx->cornuData.c,xx->cornuData.a, xx->cornuData.r, xx);
ComputeCornuBoundingBox(t,xx);
SetEndPts(t,2);
+ return TRUE;
}
static void MoveCornu( track_p trk, coOrd orig )
@@ -667,6 +666,9 @@ static void RescaleCornu( track_p trk, FLOAT_T ratio )
for (int i=0;i<2;i++) {
xx->cornuData.pos[i].x *= ratio;
xx->cornuData.pos[i].y *= ratio;
+ xx->cornuData.c[i].x *= ratio;
+ xx->cornuData.c[i].y *= ratio;
+ xx->cornuData.r[i] *= ratio;
}
RebuildCornu(trk);
@@ -689,13 +691,63 @@ void GetCornuParmsNear(track_p t, int sel, coOrd * pos2, coOrd * center, ANGLE_T
coOrd pos = *pos2;
double dd = DistanceCornu(t, &pos); //Pos adjusted to be on curve
int inx;
+ *radius = 0.0;
+ *angle2 = 0.0;
+ *center = zero;
wBool_t back,neg;
ANGLE_T angle = GetAngleSegs(xx->cornuData.arcSegs.cnt,(trkSeg_t *)(xx->cornuData.arcSegs.ptr),&pos,&inx,NULL,&back,NULL,&neg);
+ if (inx == -1) {
+ return; //Error in GetAngle
+ }
+
trkSeg_p segPtr = &DYNARR_N(trkSeg_t, xx->cornuData.arcSegs, inx);
- GetAngleSegs(segPtr->bezSegs.cnt,(trkSeg_t *)(segPtr->bezSegs.ptr),&pos,&inx,NULL,&back,NULL,&neg);
- segPtr = &DYNARR_N(trkSeg_t, segPtr->bezSegs, inx);
+ if (segPtr->type == SEG_BEZTRK) {
+ GetAngleSegs(segPtr->bezSegs.cnt,(trkSeg_t *)(segPtr->bezSegs.ptr),&pos,&inx,NULL,&back,NULL,&neg);
+ if (inx ==-1) return;
+ segPtr = &DYNARR_N(trkSeg_t, segPtr->bezSegs, inx);
+ }
+
+ if (segPtr->type == SEG_STRTRK) {
+ *radius = 0.0;
+ *center = zero;
+ } else if (segPtr->type == SEG_CRVTRK) {
+ *center = segPtr->u.c.center;
+ *radius = fabs(segPtr->u.c.radius);
+ }
+ if (sel)
+ angle = NormalizeAngle(angle+(neg==back?0:180));
+ else
+ angle = NormalizeAngle(angle+(neg==back?180:0));
+ *angle2 = angle;
+ *pos2 = pos;
+}
+
+void GetCornuParmsTemp(dynArr_t * array_p, int sel, coOrd * pos2, coOrd * center, ANGLE_T * angle2, DIST_T * radius ) {
+
+ coOrd pos = *pos2;
+ int inx;
+ wBool_t back,neg;
+ *radius = 0.0;
+ *center = zero;
+ *angle2 = 0.0;
+
+ ANGLE_T angle = GetAngleSegs(array_p->cnt,(trkSeg_p)array_p->ptr,&pos,&inx,NULL,&back,NULL,&neg);
+
+ if (inx==-1) return;
+
+ trkSeg_p segPtr = &DYNARR_N(trkSeg_t, *array_p, inx);
+
+ if (segPtr->type == SEG_BEZTRK) {
+
+ GetAngleSegs(segPtr->bezSegs.cnt,(trkSeg_t *)(segPtr->bezSegs.ptr),&pos,&inx,NULL,&back,NULL,&neg);
+
+ if (inx ==-1) return;
+
+ segPtr = &DYNARR_N(trkSeg_t, segPtr->bezSegs, inx);
+
+ }
if (segPtr->type == SEG_STRTRK) {
*radius = 0.0;
@@ -734,9 +786,14 @@ static BOOL_T SplitCornu( track_p trk, coOrd pos, EPINX_T ep, track_p *leftover,
ANGLE_T angle = GetAngleSegs(xx->cornuData.arcSegs.cnt,(trkSeg_t *)(xx->cornuData.arcSegs.ptr),&pos,&inx,NULL,&back,NULL,&neg);
+ if (inx == -1) return FALSE;
+
trkSeg_p segPtr = &DYNARR_N(trkSeg_t, xx->cornuData.arcSegs, inx);
GetAngleSegs(segPtr->bezSegs.cnt,(trkSeg_t *)(segPtr->bezSegs.ptr),&pos,&inx,NULL,&back,NULL,&neg);
+
+ if (inx == -1) return FALSE;
+
segPtr = &DYNARR_N(trkSeg_t, segPtr->bezSegs, inx);
if (segPtr->type == SEG_STRTRK) {
@@ -767,6 +824,7 @@ static BOOL_T SplitCornu( track_p trk, coOrd pos, EPINX_T ep, track_p *leftover,
}
trk1 = NewCornuTrack(new.pos,new.center,new.angle,new.radius,NULL,0);
+ //Copy elevation details from old ep to new ep 0/1
if (trk1==NULL) {
wBeep();
InfoMessage(_("Cornu Create Failed for p1[%0.3f,%0.3f] p2[%0.3f,%0.3f], c1[%0.3f,%0.3f] c2[%0.3f,%0.3f], a1=%0.3f a2=%0.3f, r1=%s r2=%s"),
@@ -779,20 +837,26 @@ static BOOL_T SplitCornu( track_p trk, coOrd pos, EPINX_T ep, track_p *leftover,
UndoEnd();
return FALSE;
}
+ DIST_T height;
+ int opt;
+ GetTrkEndElev(trk,ep,&opt,&height);
+ UpdateTrkEndElev( trk1, ep, opt, height, (opt==ELEV_STATION)?GetTrkEndElevStation(trk,ep):NULL );
UndoModify(trk);
xx->cornuData.pos[ep] = pos;
xx->cornuData.a[ep] = NormalizeAngle(new.angle[1-ep]+180);
xx->cornuData.r[ep] = new.radius[1-ep];
xx->cornuData.c[ep] = new.center[1-ep];
+ //Wipe out old elevation for ep1
RebuildCornu(trk);
SetTrkEndPoint(trk, ep, xx->cornuData.pos[ep], xx->cornuData.a[ep]);
+ UpdateTrkEndElev( trk, ep, ELEV_NONE, 0, NULL);
*leftover = trk1;
- *ep0 = 1-ep;
- *ep1 = ep;
+ *ep0 = 1-ep; //Which end is for new on pos?
+ *ep1 = ep; //Which end is for old trk?
return TRUE;
}
@@ -801,8 +865,12 @@ BOOL_T MoveCornuEndPt ( track_p *trk, EPINX_T *ep, coOrd pos, DIST_T d0 ) {
track_p trk2;
if (SplitTrack(*trk,pos,*ep,&trk2,TRUE)) {
struct extraData *xx = GetTrkExtraData(*trk);
- if (trk2) DeleteTrack(trk2,TRUE);
+ if (trk2) {
+ UndrawNewTrack( trk2 );
+ DeleteTrack(trk2,TRUE);
+ }
SetTrkEndPoint( *trk, *ep, *ep?xx->cornuData.pos[1]:xx->cornuData.pos[0], *ep?xx->cornuData.a[1]:xx->cornuData.a[0] );
+ DrawNewTrack( *trk );
return TRUE;
}
return FALSE;
@@ -923,7 +991,8 @@ static BOOL_T EnumerateCornu( track_p trk )
if (trk != NULL) {
struct extraData *xx = GetTrkExtraData(trk);
DIST_T d;
- d = xx->cornuData.length;
+ d = max(CornuOffsetLength(xx->cornuData.arcSegs,-GetTrkGauge(trk)/2.0),
+ CornuOffsetLength(xx->cornuData.arcSegs,GetTrkGauge(trk)/2.0));
ScaleLengthIncrement( GetTrkScale(trk), d );
}
return TRUE;
@@ -1004,29 +1073,63 @@ static BOOL_T MergeCornu(
DrawNewTrack( trk3 );
UndoEnd();
-
return TRUE;
}
-BOOL_T GetBezierSegmentsFromCornu(track_p trk, dynArr_t * segs) {
+BOOL_T GetBezierSegmentsFromCornu(track_p trk, dynArr_t * segs, BOOL_T track) {
struct extraData * xx = GetTrkExtraData(trk);
for (int i=0;i<xx->cornuData.arcSegs.cnt;i++) {
- DYNARR_APPEND(trkSeg_t, * segs, 10);
+ trkSeg_p p = (trkSeg_t *) xx->cornuData.arcSegs.ptr+i;
+ if (p->type == SEG_BEZTRK) {
+ if (track) {
+ DYNARR_APPEND(trkSeg_t, * segs, 10);
+ trkSeg_p segPtr = &DYNARR_N(trkSeg_t,* segs,segs->cnt-1);
+ segPtr->type = SEG_BEZTRK;
+ segPtr->color = wDrawColorBlack;
+ segPtr->width = 0;
+ if (segPtr->bezSegs.ptr) MyFree(segPtr->bezSegs.ptr);
+ segPtr->bezSegs.cnt = 0;
+ segPtr->bezSegs.max = 0;
+ segPtr->bezSegs.ptr = NULL;
+ for (int j=0;j<4;j++) segPtr->u.b.pos[j] = p->u.b.pos[j];
+ FixUpBezierSeg(segPtr->u.b.pos,segPtr,TRUE);
+ } else {
+ for (int j=0;j<p->bezSegs.cnt;j++) {
+ trkSeg_p bez_p = &DYNARR_N(trkSeg_t,p->bezSegs,j);
+ DYNARR_APPEND(trkSeg_t, * segs, 10);
+ trkSeg_p segPtr = &DYNARR_LAST(trkSeg_t,* segs);
+ if (bez_p->type == SEG_CRVTRK) segPtr->type = SEG_CRVLIN;
+ if (bez_p->type == SEG_STRTRK) segPtr->type = SEG_STRLIN;
+ segPtr->u = bez_p->u;
+ segPtr->width = bez_p->width;
+ segPtr->color = bez_p->color;
+ }
+ }
+ } else if (p->type == SEG_STRTRK) {
+ DYNARR_APPEND(trkSeg_t, * segs, 1);
+ trkSeg_p segPtr = &DYNARR_N(trkSeg_t,* segs,segs->cnt-1);
+ segPtr->type = track?SEG_STRTRK:SEG_STRLIN;
+ segPtr->color = wDrawColorBlack;
+ segPtr->width = 0;
+ for (int j=0;j<2;j++) segPtr->u.l.pos[i] = p->u.l.pos[i];
+ segPtr->u.l.angle = p->u.l.angle;
+ segPtr->u.l.option = 0;
+ } else if (p->type == SEG_CRVTRK) {
+ DYNARR_APPEND(trkSeg_t, * segs, 1);
trkSeg_p segPtr = &DYNARR_N(trkSeg_t,* segs,segs->cnt-1);
- segPtr->type = SEG_BEZTRK;
+ segPtr->type = track?SEG_CRVTRK:SEG_CRVLIN;
segPtr->color = wDrawColorBlack;
segPtr->width = 0;
- if (segPtr->bezSegs.ptr) MyFree(segPtr->bezSegs.ptr);
- segPtr->bezSegs.cnt = 0;
- segPtr->bezSegs.max = 0;
- segPtr->bezSegs.ptr = NULL;
- trkSeg_p p = (trkSeg_t *) xx->cornuData.arcSegs.ptr+i;
- for (int j=0;j<4;j++) segPtr->u.b.pos[j] = p->u.b.pos[j];
- FixUpBezierSeg(segPtr->u.b.pos,segPtr,TRUE);
+ segPtr->u.c.a0 = p->u.c.a0;
+ segPtr->u.c.a1 = p->u.c.a1;
+ segPtr->u.c.center = p->u.c.center;
+ segPtr->u.c.radius = p->u.c.radius;
+ }
}
return TRUE;
}
+
static DIST_T GetLengthCornu( track_p trk )
{
struct extraData *xx = GetTrkExtraData(trk);
@@ -1052,6 +1155,7 @@ static BOOL_T GetParamsCornu( int inx, track_p trk, coOrd pos, trackParams_t * p
params->track_angle = GetAngleSegs( //Find correct Segment and nearest point in it
xx->cornuData.arcSegs.cnt,xx->cornuData.arcSegs.ptr,
&pos, &segInx, &d , &back, &segInx2, &negative );
+ if (segInx ==-1) return FALSE;
trkSeg_p segPtr = &DYNARR_N(trkSeg_t,xx->cornuData.arcSegs,segInx);
if (negative != back) params->track_angle = NormalizeAngle(params->track_angle+180); //Cornu is in reverse
if (segPtr->type == SEG_STRTRK) {
@@ -1079,13 +1183,16 @@ static BOOL_T GetParamsCornu( int inx, track_p trk, coOrd pos, trackParams_t * p
params->cornuCenter[i] = xx->cornuData.c[i];
}
params->len = xx->cornuData.length;
- if ( inx == PARAMS_PARALLEL ) {
- params->ep = 0;
- } else if (inx == PARAMS_CORNU) {
+ if ( inx == PARAMS_NODES ) {
+ return FALSE;
+ } else if ((inx == PARAMS_CORNU) || (inx == PARAMS_1ST_JOIN) || (inx == PARAMS_2ND_JOIN) ) {
params->ep = PickEndPoint( pos, trk);
} else {
params->ep = PickUnconnectedEndPointSilent( pos, trk );
+
}
+ if (params->ep == -1) return FALSE;
+
if (params->ep>=0) {
params->angle = GetTrkEndAngle(trk,params->ep);
}
@@ -1108,7 +1215,7 @@ static BOOL_T QueryCornu( track_p trk, int query )
return TRUE;
break;
case Q_EXCEPTION:
- return xx->cornuData.minCurveRadius < (GetLayoutMinTrackRadius()-EPSILON);
+ return fabs(xx->cornuData.minCurveRadius) < (GetLayoutMinTrackRadius()-EPSILON);
break;
case Q_IS_CORNU:
return TRUE;
@@ -1122,13 +1229,12 @@ static BOOL_T QueryCornu( track_p trk, int query )
// case Q_MODIFY_CANT_SPLIT: Remove Split Restriction
// case Q_CANNOT_BE_ON_END: Remove Restriction - Can have Cornu with no ends
case Q_CANNOT_PLACE_TURNOUT:
- return TRUE;
+ return FALSE;
break;
case Q_IGNORE_EASEMENT_ON_EXTEND:
return TRUE;
break;
case Q_MODIFY_CAN_SPLIT:
- case Q_CAN_EXTEND:
return TRUE;
default:
return FALSE;
@@ -1178,8 +1284,9 @@ static ANGLE_T GetAngleCornu(
BOOL_T back, neg;
int indx;
angle = GetAngleSegs( xx->cornuData.arcSegs.cnt, (trkSeg_p)xx->cornuData.arcSegs.ptr, &pos, &indx, NULL, &back, NULL, &neg );
- if ( ep0 ) *ep0 = -1;
- if ( ep1 ) *ep1 = -1;
+ if (!back) angle = NormalizeAngle(angle+180);
+ if ( ep0 ) *ep0 = neg?1:0;
+ if ( ep1 ) *ep1 = neg?0:1;
return angle;
}
@@ -1188,14 +1295,17 @@ BOOL_T GetCornuSegmentFromTrack(track_p trk, trkSeg_p seg_p) {
return TRUE;
}
+static dynArr_t cornuSegs_da;
static BOOL_T MakeParallelCornu(
track_p trk,
coOrd pos,
DIST_T sep,
+ DIST_T factor,
track_p * newTrkR,
coOrd * p0R,
- coOrd * p1R )
+ coOrd * p1R,
+ BOOL_T track )
{
struct extraData * xx = GetTrkExtraData(trk);
coOrd np[4], p, nc[2];
@@ -1216,40 +1326,41 @@ static BOOL_T MakeParallelCornu(
BOOL_T above = FALSE;
if ( diff_a < 180 ) above = TRUE; //Above track
if (xx->cornuData.a[0] <180) above = !above;
- Translate(&np[0],xx->cornuData.pos[0],xx->cornuData.a[0]+(above?90:-90),sep);
- Translate(&np[1],xx->cornuData.pos[1],xx->cornuData.a[1]+(above?-90:90),sep);
+ DIST_T sep0 = sep+((xx->cornuData.r[0]!=0.0)?fabs(factor/xx->cornuData.r[0]):0);
+ DIST_T sep1 = sep+((xx->cornuData.r[1]!=0.0)?fabs(factor/xx->cornuData.r[1]):0);
+ Translate(&np[0],xx->cornuData.pos[0],xx->cornuData.a[0]+(above?90:-90),sep0);
+ Translate(&np[1],xx->cornuData.pos[1],xx->cornuData.a[1]+(above?-90:90),sep1);
na[0]=xx->cornuData.a[0];
na[1]=xx->cornuData.a[1];
- if (xx->cornuData.r[0]) {
+ if (xx->cornuData.r[0] != 0.0) {
//Find angle between center and end angle of track
ANGLE_T ea0 =
NormalizeAngle(FindAngle(xx->cornuData.c[0],xx->cornuData.pos[0])-xx->cornuData.a[0]);
- DIST_T sep0 = sep;
- if (ea0>180) sep0 = -sep;
+ if (ea0>180) sep0 = -sep0;
nr[0]=xx->cornuData.r[0]+(above?sep0:-sep0); //Needs adjustment
nc[0]=xx->cornuData.c[0];
} else {
- nr[0] = 0;
+ nr[0] = 0.0;
nc[0] = zero;
}
- if (xx->cornuData.r[1]) {
+ if (xx->cornuData.r[1] != 0.0) {
ANGLE_T ea1 =
NormalizeAngle(FindAngle(xx->cornuData.c[1],xx->cornuData.pos[1])-xx->cornuData.a[1]);
- DIST_T sep1 = sep;
- if (ea1<180) sep1 = -sep;
+ if (ea1<180) sep1 = -sep1;
nr[1]=xx->cornuData.r[1]+(above?sep1:-sep1); //Needs adjustment
nc[1]=xx->cornuData.c[1];
} else {
- nr[1] = 0;
+ nr[1] = 0.0;
nc[1] = zero;
}
if ( newTrkR ) {
- *newTrkR = NewCornuTrack( np, nc, na, nr, NULL, 0);
- if (*newTrkR==NULL) {
- wBeep();
- InfoMessage(_("Cornu Create Failed for p1[%0.3f,%0.3f] p2[%0.3f,%0.3f], c1[%0.3f,%0.3f] c2[%0.3f,%0.3f], a1=%0.3f a2=%0.3f, r1=%s r2=%s"),
+ if (track) {
+ *newTrkR = NewCornuTrack( np, nc, na, nr, NULL, 0);
+ if (*newTrkR==NULL) {
+ wBeep();
+ InfoMessage(_("Cornu Create Failed for p1[%0.3f,%0.3f] p2[%0.3f,%0.3f], c1[%0.3f,%0.3f] c2[%0.3f,%0.3f], a1=%0.3f a2=%0.3f, r1=%s r2=%s"),
np[0].x,np[0].y,
np[1].x,np[1].y,
nc[0].x,nc[0].y,
@@ -1258,16 +1369,75 @@ static BOOL_T MakeParallelCornu(
FormatDistance(nr[0]),FormatDistance(nr[1]));
return FALSE;
}
+ } else {
+ tempSegs_da.cnt = 0;
+ CallCornu0(np,nc,na,nr,&tempSegs_da,FALSE);
+ *newTrkR = MakePolyLineFromSegs( zero, 0.0, &tempSegs_da );
+ }
} else {
tempSegs_da.cnt = 0;
CallCornu0(np,nc,na,nr,&tempSegs_da,FALSE);
+ if (!track) {
+ for (int i=0;i<tempSegs_da.cnt;i++) {
+ trkSeg_p seg = &tempSegs(i);
+ if (seg->type == SEG_STRTRK) {
+ seg->type = SEG_STRLIN;
+ seg->color = wDrawColorBlack;
+ seg->width = 0;
+ }
+ if (seg->type == SEG_CRVTRK) {
+ seg->type = SEG_CRVLIN;
+ seg->color = wDrawColorBlack;
+ seg->width = 0;
+ }
+ if (seg->type == SEG_BEZTRK) {
+ for (int j=0;j<seg->bezSegs.cnt;j++) {
+ trkSeg_p bseg = &(((trkSeg_t *)seg->bezSegs.ptr)[j]);
+ if (bseg->type == SEG_STRTRK) {
+ bseg->type = SEG_STRLIN;
+ bseg->color = wDrawColorBlack;
+ bseg->width = 0;
+ }
+ if (bseg->type == SEG_CRVTRK) {
+ bseg->type = SEG_CRVLIN;
+ bseg->color = wDrawColorBlack;
+ bseg->width = 0;
+ }
+ }
+ seg->type = SEG_BEZLIN;
+ seg->color = wDrawColorBlack;
+ seg->width = 0;
+ }
+ }
+ }
}
if ( p0R ) *p0R = np[0];
if ( p1R ) *p1R = np[1];
return TRUE;
}
+static BOOL_T TrimCornu( track_p trk, EPINX_T ep, DIST_T dist, coOrd endpos, ANGLE_T angle, DIST_T radius, coOrd center ) {
+ UndoModify(trk);
+ if (dist>0.0 && dist<minLength) {
+ UndrawNewTrack( trk );
+ DeleteTrack(trk, TRUE);
+ return FALSE;
+ } else {
+ struct extraData *xx;
+ UndrawNewTrack( trk );
+ xx = GetTrkExtraData(trk);
+ xx->cornuData.a[ep] = angle;
+ xx->cornuData.c[ep] = center;
+ xx->cornuData.r[ep] = radius;
+ xx->cornuData.pos[ep] = endpos;
+ RebuildCornu(trk);
+ SetTrkEndPoint(trk, ep, xx->cornuData.pos[ep], xx->cornuData.a[ep]);
+ DrawNewTrack( trk );
+ }
+ return TRUE;
+}
+
/*
* When an undo is run, the array of segs is missing - they are not saved to the Undo log. So Undo calls this routine to
* ensure
@@ -1288,6 +1458,29 @@ EXPORT BOOL_T RebuildCornu (track_p trk)
}
+static wBool_t CompareCornu( track_cp trk1, track_cp trk2 )
+{
+ struct extraData *xx1 = GetTrkExtraData( trk1 );
+ struct extraData *xx2 = GetTrkExtraData( trk2 );
+ char * cp = message + strlen(message);
+ REGRESS_CHECK_POS( "Pos[0]", xx1, xx2, cornuData.pos[0] )
+ REGRESS_CHECK_POS( "Pos[1]", xx1, xx2, cornuData.pos[1] )
+ REGRESS_CHECK_POS( "C[0]", xx1, xx2, cornuData.c[0] )
+ REGRESS_CHECK_POS( "C[1]", xx1, xx2, cornuData.c[1] )
+ REGRESS_CHECK_ANGLE( "A[0]", xx1, xx2, cornuData.a[0] )
+ REGRESS_CHECK_ANGLE( "A[1]", xx1, xx2, cornuData.a[1] )
+ REGRESS_CHECK_DIST( "R[0]", xx1, xx2, cornuData.r[0] )
+ REGRESS_CHECK_DIST( "R[1]", xx1, xx2, cornuData.r[1] )
+ REGRESS_CHECK_DIST( "MinCurveRadius", xx1, xx2, cornuData.minCurveRadius )
+ REGRESS_CHECK_DIST( "MaxRateofChange", xx1, xx2, cornuData.maxRateofChange )
+ REGRESS_CHECK_DIST( "Length", xx1, xx2, cornuData.length )
+ REGRESS_CHECK_ANGLE( "WindingAngle", xx1, xx2, cornuData.windingAngle )
+ // CHECK arcSegs
+ REGRESS_CHECK_POS( "DescOff", xx1, xx2, cornuData.descriptionOff )
+ // CHECK cornuPath
+ return TRUE;
+}
+
static trackCmd_t cornuCmds = {
"CORNU",
DrawCornu,
@@ -1305,7 +1498,7 @@ static trackCmd_t cornuCmds = {
TraverseCornu,
EnumerateCornu,
NULL, /* redraw */
- NULL, /* trim */
+ TrimCornu, /* trim */
MergeCornu,
NULL, /* modify */
GetLengthCornu,
@@ -1319,7 +1512,11 @@ static trackCmd_t cornuCmds = {
NULL,
MakeParallelCornu,
NULL,
- RebuildCornu
+ RebuildCornu,
+ NULL,
+ NULL,
+ NULL,
+ CompareCornu
};