Add Track.getPointAtDist method and refactor StandardTrack._calcPoints()
This commit is contained in:
parent
ff3baa3c26
commit
94bfa7c060
@ -40,7 +40,7 @@ function InfoPopupSwitchItems(props) {
|
||||
|
||||
function InfoPopupShapeItems(props) {
|
||||
const { track } = props;
|
||||
if (track.type !== 'StandardTrack' || track.r === 0) return null;
|
||||
if (track.r === 0) return null;
|
||||
|
||||
return <InfoPopupItem value={Math.abs(track.r)} label="Radius" options={{suffix: ' m', precision: 0}} />
|
||||
}
|
||||
|
||||
@ -13,8 +13,15 @@ export default class BezierTrack extends Track
|
||||
middle: Vector3.zero(),
|
||||
};
|
||||
|
||||
constructor(id, start, control1, end, control2, rot, len, r, connections, id_station, start_slope, end_slope, id_isolation, prefab_name, maxspeed, derailspeed) {
|
||||
super(id, start, rot, len, r, connections, id_station, start_slope, end_slope, id_isolation, prefab_name, maxspeed, derailspeed, TrackSource.BEZIER);
|
||||
constructor(id, start, control1, end, control2, connections, id_station, start_slope, end_slope, id_isolation, prefab_name, maxspeed, derailspeed) {
|
||||
const length = start.distance(end); // TODO: calculate more precise length
|
||||
super(
|
||||
id, start,
|
||||
Vector3.zero(), // rotation
|
||||
length,
|
||||
0, // radius
|
||||
connections, id_station, start_slope, end_slope, id_isolation, prefab_name, maxspeed, derailspeed, TrackSource.BEZIER,
|
||||
);
|
||||
|
||||
Object.assign(this.points, {
|
||||
start,
|
||||
@ -22,11 +29,10 @@ export default class BezierTrack extends Track
|
||||
end,
|
||||
control2: end.add(control2),
|
||||
});
|
||||
// This is not the the actual middle point, but it's close enough
|
||||
this.points.middle = this._pointAtT(0.5);
|
||||
this.points.middle = this.getPointAtDist(length / 2);
|
||||
}
|
||||
|
||||
_pointAtT(t) {
|
||||
_getPointAtT(t) {
|
||||
const a1 = this.points.start.lerp(this.points.control1, t);
|
||||
const a2 = this.points.control1.lerp(this.points.control2, t);
|
||||
const a3 = this.points.control2.lerp(this.points.end, t);
|
||||
@ -37,6 +43,12 @@ export default class BezierTrack extends Track
|
||||
return b1.lerp(b2, t);
|
||||
}
|
||||
|
||||
getPointAtDist(dist, fromEnd = TrackConnectionEnd.START) {
|
||||
if (fromEnd === TrackConnectionEnd.END) return this.getPointAtDist(this.len - dist, TrackConnectionEnd.START);
|
||||
// TODO: This is just an approximation for a Bezier curve
|
||||
return this._getPointAtT(dist / this.len);
|
||||
}
|
||||
|
||||
getStartAngleXZ() {
|
||||
return this.points.start.atanY(this.points.control1);
|
||||
}
|
||||
@ -58,10 +70,6 @@ export default class BezierTrack extends Track
|
||||
Vector3.fromValuesArray(values, 6), // control1
|
||||
Vector3.fromValuesArray(values, 9), // end
|
||||
Vector3.fromValuesArray(values, 12), // control2
|
||||
// TODO: values below
|
||||
Vector3.zero(),
|
||||
0, // len ??
|
||||
0, // r ??
|
||||
connections,
|
||||
values[17], // id_station
|
||||
...Track.slopesFromText(values[18]), // start_slope, end_slope
|
||||
|
||||
@ -3,13 +3,13 @@ import Track, {TrackSource} from "./track";
|
||||
import Vector3 from "../vector3";
|
||||
import TrackConnection, {TrackConnectionEnd} from "../track-connection";
|
||||
import {ElectrificationStatus} from "../electrification-status";
|
||||
import CurveHelper from "../../helpers/curveHelper";
|
||||
|
||||
export default class StandardTrack extends Track {
|
||||
type = "StandardTrack";
|
||||
points = {
|
||||
start: Vector3.zero(),
|
||||
end: Vector3.zero(),
|
||||
circleCenter: Vector3.zero(),
|
||||
middle: Vector3.zero(),
|
||||
};
|
||||
|
||||
@ -18,6 +18,19 @@ export default class StandardTrack extends Track {
|
||||
this._calcPoints();
|
||||
}
|
||||
|
||||
_transformPoint(point) {
|
||||
const rotRad = AngleHelper.rotationDegToRad(this.rot);
|
||||
return point.rotate(rotRad).add(this.points.start);
|
||||
}
|
||||
|
||||
getPointAtDist(dist, fromEnd = TrackConnectionEnd.START) {
|
||||
if (fromEnd === TrackConnectionEnd.END) return this.getPointAtDist(this.len - dist, TrackConnectionEnd.START)
|
||||
const curveEnd = CurveHelper.calculateCurveEndStandard(this.r, dist).endPos;
|
||||
// TODO: Verify slope logic
|
||||
curveEnd.y += (this.start_slope + this.end_slope) / 2000 * dist;
|
||||
return this._transformPoint(curveEnd);
|
||||
}
|
||||
|
||||
getStartAngleXZ() {
|
||||
return AngleHelper.degToRad(this.rot.y);
|
||||
}
|
||||
@ -25,10 +38,9 @@ export default class StandardTrack extends Track {
|
||||
getEndAngleXZ() {
|
||||
const startAngle = AngleHelper.degToRad(this.rot.y);
|
||||
|
||||
if(this.r === 0) {
|
||||
return startAngle
|
||||
}
|
||||
if (this.r === 0) return startAngle
|
||||
|
||||
// This is only correct for a flat arc on the XZ plane
|
||||
return startAngle - this.len / this.r;
|
||||
}
|
||||
|
||||
@ -59,32 +71,9 @@ export default class StandardTrack extends Track {
|
||||
}
|
||||
|
||||
_calcPoints() {
|
||||
const rotRad = AngleHelper.degToRad(this.rot.y);
|
||||
|
||||
this.points.start = this.pos.clone();
|
||||
|
||||
if (this.r === 0) {
|
||||
this.points.end = this.pos.add(Vector3.fromAngleY(rotRad, this.len));
|
||||
this.points.middle = this.points.start.lerp(this.points.end, 0.5);
|
||||
this.points.circleCenter = this.pos.clone(); // default circle center
|
||||
} else {
|
||||
const centerAngle = rotRad + Math.PI / 2;
|
||||
this.points.circleCenter = this.pos.sub(Vector3.fromAngleY(centerAngle, this.r));
|
||||
|
||||
const middleAngle = centerAngle - (this.len / this.r) / 2;
|
||||
this.points.middle = this.points.circleCenter.add(Vector3.fromAngleY(middleAngle, this.r));
|
||||
|
||||
const endAngle = centerAngle - this.len / this.r;
|
||||
this.points.end = this.points.circleCenter.add(Vector3.fromAngleY(endAngle, this.r));
|
||||
}
|
||||
|
||||
// adjust end point by the slope
|
||||
if (this.end_slope !== 0) {
|
||||
const startHeightDiff = this.start_slope * this.len / 1000;
|
||||
const endHeightDiff = this.end_slope * this.len / 1000;
|
||||
|
||||
this.points.end.y += startHeightDiff + (endHeightDiff - startHeightDiff) / 2;
|
||||
}
|
||||
this.points.middle = this.getPointAtDist(this.len / 2, TrackConnectionEnd.START);
|
||||
this.points.end = this.getPointAtDist(this.len, TrackConnectionEnd.START);
|
||||
}
|
||||
|
||||
applyObject(scenery) {
|
||||
|
||||
@ -55,6 +55,10 @@ export default class Track extends SceneryObject {
|
||||
else return this.getEndAngleXZ();
|
||||
}
|
||||
|
||||
getPointAtDist(_dist, _fromEnd) {
|
||||
throw new Error("getPointAtDist() must be implemented in subclass");
|
||||
}
|
||||
|
||||
static slopesFromText(text) {
|
||||
return text.split(",", 2).map((slope) => parseFloat(slope));
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user