mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-26 06:49:29 +01:00
feat(editor,track): a cant ramp of its own, off the transition curve: each end of a curve may have its ramp moved and of a length of its own (ST-T1-A6 9.6 pkt 5 and 11), on the straight before the curve or on the arc, the transition keeping the full cant all along, as a switch laid on it wants it; set in the plan under "Cant ramps", stored with the vertex as "ramps", reversed with the curve, marked across the track in the view. The cant of a line is a profile along it now, the paths cut where a ramp of its own starts and ends, their rolls following it, warnings where a ramp is shorter than its cant asks for or reaches into the curve before, past the line or over the other ramp. A switch on a cant ramp is drawn following it: its rails, blades, frogs and bed made at the mean of its rolls, as before, are turned along each path to the roll of the path there, so it no longer steps at its ends against the tracks either side. The checks of a switch laid into a curve warn of the values of table 11.9 in brackets as of the others, with no word of a consent. Unit test of a ramp moved onto the straight
This commit is contained in:
@@ -1227,6 +1227,22 @@ void editor_mode::draw_route_overlay() const
|
||||
previous = next;
|
||||
}
|
||||
}
|
||||
// the cant ramps: their ends across the track, the ones moved off the transitions brighter, with how the cant goes along them
|
||||
for (auto const &ramp : result.ramps)
|
||||
{
|
||||
if (ramp.cant < 0.5)
|
||||
continue;
|
||||
auto const colour{ramp.own ? IM_COL32(255, 170, 40, 255) : IM_COL32(255, 170, 40, 120)};
|
||||
for (auto const end : {ramp.from, ramp.to})
|
||||
{
|
||||
auto const station{alignment::evaluate(result, end)};
|
||||
glm::dvec3 const across{-station.direction.z * 2.0, 0.0, station.direction.x * 2.0};
|
||||
projection.line(drawlist, station.position - across, station.position + across, colour, 3.0f);
|
||||
}
|
||||
ImVec2 screen;
|
||||
if (ramp.own && projection.project(alignment::evaluate(result, (ramp.from + ramp.to) * 0.5).position, screen))
|
||||
drawlist->AddText({screen.x + 8.0f, screen.y + 6.0f}, colour, format(STR_C("ramp %.0f m, %.0f mm"), ramp.to - ramp.from, ramp.cant).c_str());
|
||||
}
|
||||
// the part of the curve whose fields are pointed at or edited in the panel, lit up and named
|
||||
if (auto const focused{route_focused()}; false == focused.empty())
|
||||
{
|
||||
@@ -2161,6 +2177,47 @@ bool editor_mode::render_route_vertex(int const Index)
|
||||
mark(part::whole, 0);
|
||||
}
|
||||
}
|
||||
// the cant ramps at the ends of the curve: along its transitions, or where they're put, off a switch laid on a transition say
|
||||
if (false == vertex.spirals && ImGui::TreeNode(STR_C("Cant ramps")))
|
||||
{
|
||||
std::vector<alignment::result::cant_ramp> ramps;
|
||||
for (auto const &ramp : route.result.ramps)
|
||||
if (ramp.vertex == Index)
|
||||
ramps.push_back(ramp);
|
||||
auto const ramp = [&](char const *Id, char const *Label, double &Offset, double &Length, std::size_t const Which, part const What) {
|
||||
ImGui::PushID(Id);
|
||||
auto along{Length < 0.0};
|
||||
if (ImGui::Checkbox(Label, &along))
|
||||
{
|
||||
// let go of the transition where it lay along it, to be moved from there
|
||||
Length = along ? -1.0 : Which < ramps.size() ? ramps[Which].to - ramps[Which].from : 0.0;
|
||||
Offset = 0.0;
|
||||
changed = true;
|
||||
}
|
||||
mark(What, 0);
|
||||
item_tooltip("The norms recommend the cant ramp along the transition curve; off it, it may lie on the straight before the curve or on the arc, a switch on the transition keeping the same cant all along");
|
||||
if (false == along)
|
||||
{
|
||||
ImGui::SetNextItemWidth(half);
|
||||
changed |= ImGui::DragScalar("##offset", ImGuiDataType_Double, &Offset, 0.5f, nullptr, nullptr, STR_C("into the curve %.1f m"));
|
||||
mark(What, 0);
|
||||
item_tooltip("How far the outer end of the ramp lies into the curve from its end, below 0 out along the straight before it");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(half);
|
||||
changed |= ImGui::DragScalar("##length", ImGuiDataType_Double, &Length, 0.5f, nullptr, nullptr, STR_C("length %.1f m"));
|
||||
mark(What, 0);
|
||||
item_tooltip("The length of the ramp, the cant rising evenly along it");
|
||||
Length = std::max(0.0, Length);
|
||||
}
|
||||
if (Which < ramps.size() && ramps[Which].to > ramps[Which].from)
|
||||
ImGui::TextDisabled(STR_C("km %s - %s, %.2f mm/m"), profile::format_chainage(route.origin + ramps[Which].from).c_str(), profile::format_chainage(route.origin + ramps[Which].to).c_str(),
|
||||
ramps[Which].cant / (ramps[Which].to - ramps[Which].from));
|
||||
ImGui::PopID();
|
||||
};
|
||||
ramp("in", STR_C("Ramp in along the transition curve"), vertex.ramp_in_offset, vertex.ramp_in_length, 0, part::entry);
|
||||
ramp("out", STR_C("Ramp out along the transition curve"), vertex.ramp_out_offset, vertex.ramp_out_length, 1, part::exit);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNode(STR_C("Details")))
|
||||
{
|
||||
for (auto const &curve : route.result.curves)
|
||||
|
||||
@@ -1480,8 +1480,6 @@ void editor_mode::insert_curved_switch(int const Direction, int const Side)
|
||||
if (made.size() == 1)
|
||||
tool.status = format(STR_C("Switch %s inserted into the curve, Ctrl+Z takes it back"), made.front()->name().c_str());
|
||||
// what the norms say of it stays in the status
|
||||
if (report.transition)
|
||||
tool.status += "\n" + report.notes.front();
|
||||
for (auto const &warning : report.warnings)
|
||||
tool.status += "\n" + warning;
|
||||
auto const placed{created};
|
||||
|
||||
@@ -228,6 +228,25 @@ element const &element_at(result const &Result, double const Chainage)
|
||||
return lookup == Result.elements.begin() ? Result.elements.front() : *std::prev(lookup);
|
||||
}
|
||||
|
||||
// the cant of the line at the chainage, signed with the turn of its curve; where it changes all at once there, the one before the
|
||||
// chainage or the one after it
|
||||
double signed_cant(result const &Result, element const &Element, double const Distance, bool const Before)
|
||||
{
|
||||
auto const &cants{Result.cants};
|
||||
if (cants.empty())
|
||||
return Element.turn * element_cant(Element, Distance);
|
||||
auto const chainage{Element.chainage + Distance};
|
||||
auto const next{Before ? std::lower_bound(cants.begin(), cants.end(), chainage, [](glm::dvec2 const &Point, double const Value) { return Point.x < Value; })
|
||||
: std::upper_bound(cants.begin(), cants.end(), chainage, [](double const Value, glm::dvec2 const &Point) { return Value < Point.x; })};
|
||||
if (next == cants.begin())
|
||||
return cants.front().y;
|
||||
if (next == cants.end())
|
||||
return cants.back().y;
|
||||
auto const previous{std::prev(next)};
|
||||
auto const span{next->x - previous->x};
|
||||
return span < 1e-9 ? next->y : previous->y + (next->y - previous->y) * (chainage - previous->x) / span;
|
||||
}
|
||||
|
||||
glm::dvec2 blossom(std::array<glm::dvec2, 4> const &Points, double const A, double const B, double const C)
|
||||
{
|
||||
glm::dvec2 r[3], s[2];
|
||||
@@ -377,6 +396,126 @@ bool meets_norms(curve_report const &Curve, design const &Design)
|
||||
namespace
|
||||
{
|
||||
|
||||
// the length of a straight cant ramp the norms ask for to raise the cant at the speed: slow enough in time and along the track
|
||||
double ramp_length(double const Speed, double const Cant, limits const &Limits)
|
||||
{
|
||||
if (Cant <= 0.0)
|
||||
return 0.0;
|
||||
return ceil_to(std::max(Speed * Cant / (3.6 * Limits.cant_rate), Cant / 1000.0 * Limits.ramp_factor * Speed), 5.0);
|
||||
}
|
||||
|
||||
// the cant along the line: in each curve as its elements carry it, raised from 0 and lowered back to it on its ramps, which go along
|
||||
// its transition curves unless the vertex gives them a place and a length of their own
|
||||
void make_cants(design const &Design, result &R)
|
||||
{
|
||||
R.cants.clear();
|
||||
R.ramps.clear();
|
||||
auto const push = [&](double const Chainage, double const Cant) {
|
||||
if (false == R.cants.empty() && std::abs(R.cants.back().x - Chainage) < 1e-6 && std::abs(R.cants.back().y - Cant) < 1e-6)
|
||||
return;
|
||||
R.cants.push_back({Chainage, Cant});
|
||||
};
|
||||
double reached{0.0}; // where the cant of the curve before is down to 0 again
|
||||
for (std::size_t k = 0; k < Design.vertices.size(); ++k)
|
||||
{
|
||||
auto const &vertex{Design.vertices[k]};
|
||||
int first{-1};
|
||||
int last{-1};
|
||||
for (std::size_t i = 0; i < R.elements.size(); ++i)
|
||||
if (R.elements[i].vertex == static_cast<int>(k) && R.elements[i].length > 1e-6)
|
||||
{
|
||||
first = first < 0 ? static_cast<int>(i) : first;
|
||||
last = static_cast<int>(i);
|
||||
}
|
||||
if (first < 0)
|
||||
continue;
|
||||
auto const &head{R.elements[first]};
|
||||
auto const &tail{R.elements[last]};
|
||||
auto const start{head.chainage};
|
||||
auto const end{tail.chainage + tail.length};
|
||||
auto const turn{static_cast<double>(head.turn)};
|
||||
// the transitions at the ends: the first and the last element, where the curvature grows from 0 and goes back to it
|
||||
auto const entry{head.kind == element_kind::transition_in || (head.kind == element_kind::spiral && head.curvature_start == 0.0 && head.curvature_end > 0.0) ? head.length : 0.0};
|
||||
auto const exit{tail.kind == element_kind::transition_out || (tail.kind == element_kind::spiral && tail.curvature_end == 0.0 && tail.curvature_start > 0.0) ? tail.length : 0.0};
|
||||
auto const cantin{element_cant(head, entry)};
|
||||
auto const cantout{element_cant(tail, tail.length - exit)};
|
||||
if (std::max(cantin, cantout) < 0.5)
|
||||
{
|
||||
reached = end;
|
||||
continue;
|
||||
}
|
||||
result::cant_ramp in{static_cast<int>(k), start, start + entry, cantin, vertex.ramp_in_length >= 0.0};
|
||||
result::cant_ramp out{static_cast<int>(k), end - exit, end, cantout, vertex.ramp_out_length >= 0.0};
|
||||
if (in.own)
|
||||
{
|
||||
in.from = start + vertex.ramp_in_offset;
|
||||
in.to = in.from + vertex.ramp_in_length;
|
||||
}
|
||||
if (out.own)
|
||||
{
|
||||
out.to = end - vertex.ramp_out_offset;
|
||||
out.from = out.to - vertex.ramp_out_length;
|
||||
}
|
||||
// the ramps kept off the curve before, within the line and off each other
|
||||
if (in.from < reached - 1e-6)
|
||||
{
|
||||
R.warnings.emplace_back(R.ramps.empty() ? format(STR_C("Vertex %zu: the cant ramp in reaches back past the start of the line, cut %.1f m shorter"), k + 1, reached - in.from) :
|
||||
format(STR_C("Vertex %zu: the cant ramp in reaches back into the curve before it, cut %.1f m shorter"), k + 1, reached - in.from));
|
||||
in.from = std::min(reached, in.to);
|
||||
}
|
||||
if (out.to > R.length + 1e-6)
|
||||
{
|
||||
R.warnings.emplace_back(format(STR_C("Vertex %zu: the cant ramp out reaches past the end of the line, cut %.1f m shorter"), k + 1, out.to - R.length));
|
||||
out.to = std::max(R.length, out.from);
|
||||
}
|
||||
if (in.to > out.from + 1e-6)
|
||||
{
|
||||
R.warnings.emplace_back(format(STR_C("Vertex %zu: the cant ramps in and out of the curve overlap by %.1f m"), k + 1, in.to - out.from));
|
||||
auto const middle{(in.to + out.from) * 0.5};
|
||||
in.to = std::max(in.from, middle);
|
||||
out.from = std::min(out.to, middle);
|
||||
}
|
||||
auto const speed{std::max(1.0, Design.speed)};
|
||||
for (auto const *ramp : {&in, &out})
|
||||
if (ramp->own && Design.norms.checked)
|
||||
if (auto const required{ramp_length(speed, ramp->cant, Design.norms)}; ramp->to - ramp->from + 1e-6 < required)
|
||||
R.warnings.emplace_back(format(STR_C("Vertex %zu: the cant ramp of %.1f m is shorter than the %.0f m a cant of %.0f mm asks for"), k + 1, ramp->to - ramp->from, required, ramp->cant));
|
||||
// the curve between its ramps as its elements carry the cant, the transitions at its ends with the full cant of the curve where
|
||||
// the ramps went off them
|
||||
push(in.from, 0.0);
|
||||
push(in.to, turn * cantin);
|
||||
auto const low{std::max(in.to, start + entry)};
|
||||
auto const high{std::min(out.from, end - exit)};
|
||||
if (high > low + 1e-6)
|
||||
{
|
||||
push(low, turn * cantin);
|
||||
for (auto i{first}; i <= last; ++i)
|
||||
{
|
||||
auto const &e{R.elements[i]};
|
||||
for (auto const distance : {0.0, e.length})
|
||||
if (auto const chainage{e.chainage + distance}; chainage > low + 1e-6 && chainage < high - 1e-6)
|
||||
push(chainage, turn * element_cant(e, distance));
|
||||
}
|
||||
push(high, turn * cantout);
|
||||
}
|
||||
push(out.from, turn * cantout);
|
||||
push(out.to, 0.0);
|
||||
R.ramps.push_back(in);
|
||||
R.ramps.push_back(out);
|
||||
reached = out.to;
|
||||
// the time the cant takes to rise along the ramps of their own
|
||||
for (auto &curve : R.curves)
|
||||
if (curve.vertex == static_cast<int>(k))
|
||||
{
|
||||
if (in.own && in.to > in.from)
|
||||
curve.cant_rate_in = cantin * speed / 3.6 / (in.to - in.from);
|
||||
if (out.own && out.to > out.from)
|
||||
curve.cant_rate_out = cantout * speed / 3.6 / (out.to - out.from);
|
||||
}
|
||||
}
|
||||
std::stable_sort(R.cants.begin(), R.cants.end(), [](glm::dvec2 const &A, glm::dvec2 const &B) { return A.x < B.x; });
|
||||
}
|
||||
|
||||
result fit_between(design const &Design)
|
||||
{
|
||||
result r;
|
||||
@@ -953,6 +1092,7 @@ result fit_between(design const &Design)
|
||||
r.warnings.emplace_back(format(STR_C("The adjoining track at the start is curved (R %.0f m), the curvature changes abruptly"), Design.start_radius));
|
||||
if (Design.end_radius > 0.0 && Design.end_radius < 10000.0)
|
||||
r.warnings.emplace_back(format(STR_C("The adjoining track at the end is curved (R %.0f m), the curvature changes abruptly"), Design.end_radius));
|
||||
make_cants(Design, r);
|
||||
|
||||
r.valid = r.errors.empty() && r.length > 1e-3;
|
||||
return r;
|
||||
@@ -1828,8 +1968,10 @@ station evaluate(result const &Result, double const Chainage)
|
||||
element_point(e, Result.shape, distance, position, direction);
|
||||
result.position = {position.x, elevation(Result, s), position.y};
|
||||
result.direction = glm::normalize(glm::dvec3{direction.x, grade(Result, s), direction.y});
|
||||
result.cant = element_cant(e, distance);
|
||||
result.turn = e.turn;
|
||||
// a cant ramp of its own may lie on the straight before the curve, its cant turned the way the curve turns
|
||||
auto const cant{signed_cant(Result, e, distance, false)};
|
||||
result.cant = std::abs(cant);
|
||||
result.turn = e.turn != 0 ? e.turn : (cant > 0.0) - (cant < 0.0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2435,6 +2577,12 @@ std::vector<segment_data> pieces(result const &Result, design const &Design, std
|
||||
spans.insert(std::next(Span), second);
|
||||
};
|
||||
double constexpr margin{0.01};
|
||||
// the ends of the cant ramps of their own, where the cant starts or stops changing along a straight, a transition or an arc
|
||||
for (auto const &ramp : Result.ramps)
|
||||
for (auto const chainage : {ramp.from, ramp.to})
|
||||
if (auto inside{std::find_if(spans.begin(), spans.end(), [&](span const &Span) { return chainage_from(Span) < chainage - margin && chainage_to(Span) > chainage + margin; })};
|
||||
ramp.own && inside != spans.end())
|
||||
split(inside, chainage);
|
||||
for (auto const chainage : Breaks)
|
||||
{
|
||||
auto inside{std::find_if(spans.begin(), spans.end(), [&](span const &Span) { return chainage_from(Span) < chainage - margin && chainage_to(Span) > chainage + margin; })};
|
||||
@@ -2566,15 +2714,16 @@ std::vector<segment_data> pieces(result const &Result, design const &Design, std
|
||||
auto const y1{y0 + grade(Result, s0) * glm::distance(p0, p1)};
|
||||
auto const y2{y3 - grade(Result, s3) * glm::distance(p2, p3)};
|
||||
|
||||
auto const roll = [&](double const Cant) { return static_cast<float>(e.turn * glm::degrees(std::asin(std::clamp(Cant / Design.norms.gauge, -1.0, 1.0)))); };
|
||||
// the cant signed with the turn, a ramp of its own on a straight too; where it changes all at once, the one of the piece itself
|
||||
auto const roll = [&](double const Cant) { return static_cast<float>(glm::degrees(std::asin(std::clamp(Cant / Design.norms.gauge, -1.0, 1.0)))); };
|
||||
|
||||
segment_data path;
|
||||
path.points[segment_data::point::start] = {p0.x, y0, p0.y};
|
||||
path.points[segment_data::point::end] = {p3.x, y3, p3.y};
|
||||
path.points[segment_data::point::control1] = glm::dvec3{p1.x, y1, p1.y} - path.points[segment_data::point::start];
|
||||
path.points[segment_data::point::control2] = glm::dvec3{p2.x, y2, p2.y} - path.points[segment_data::point::end];
|
||||
path.rolls[0] = roll(element_cant(e, piece.from));
|
||||
path.rolls[1] = roll(element_cant(e, piece.to));
|
||||
path.rolls[0] = roll(signed_cant(Result, e, piece.from, false));
|
||||
path.rolls[1] = roll(signed_cant(Result, e, piece.to, true));
|
||||
path.radius = e.kind == element_kind::straight ? 0.f : static_cast<float>(e.radius);
|
||||
if (e.kind == element_kind::spiral)
|
||||
{
|
||||
|
||||
@@ -74,6 +74,14 @@ struct vertex
|
||||
// two transition curves meeting at the curvature of the radius, with no arc between them and no cant: the bend of two straights
|
||||
// eased the way the lines are drawn. Their lengths follow from the radius and the deflection, the ones given are left out
|
||||
bool spirals{false};
|
||||
// the cant ramp at each end of the curve where it doesn't go along the transition curve (ST-T1-A6 9.6 pkt 5 and 11): how far its
|
||||
// outer end lies into the curve from the start of the curve, or from its end, below 0 out along the straight, and its length; a
|
||||
// length below 0 keeps the ramp along the transition, as the norms recommend
|
||||
double ramp_in_offset{0.0};
|
||||
double ramp_in_length{-1.0};
|
||||
double ramp_out_offset{0.0};
|
||||
double ramp_out_length{-1.0};
|
||||
bool own_ramps() const { return ramp_in_length >= 0.0 || ramp_out_length >= 0.0; }
|
||||
};
|
||||
|
||||
struct design
|
||||
@@ -187,6 +195,19 @@ struct result
|
||||
std::vector<element> elements;
|
||||
std::vector<curve_report> curves;
|
||||
std::vector<profile_point> profile;
|
||||
// the cant along the line, mm at the chainages, between them changing evenly; signed with the turn of the curve it belongs to,
|
||||
// as the rolls of the paths are
|
||||
std::vector<glm::dvec2> cants;
|
||||
// the cant ramps at the ends of the curves, where the cant goes from 0 to the one of the curve
|
||||
struct cant_ramp
|
||||
{
|
||||
int vertex{-1};
|
||||
double from{0.0};
|
||||
double to{0.0};
|
||||
double cant{0.0}; // mm, at the end of the ramp in the curve
|
||||
bool own{false}; // not along the transition curve
|
||||
};
|
||||
std::vector<cant_ramp> ramps;
|
||||
double length{0.0};
|
||||
glm::dvec3 start{0.0};
|
||||
glm::dvec3 end{0.0};
|
||||
|
||||
@@ -48,6 +48,8 @@ bool g_loaded{false};
|
||||
// vertex <x> <z> <offset> <R> <L in> <L out> <cant> <reverse 0/1> <compound 0/1> <share> <arcs> [<R> <L> <share>]... [spirals 1]
|
||||
// spirals: two transition curves with no arc between them, their lengths following from R
|
||||
// [cants <first> <arc>...]: the cants of the radii of a compound curve set one by one, below 0 the cant in proportion to the curvature
|
||||
// [ramps <in offset> <in length> <out offset> <out length>]: the cant ramps of the curve where they don't go along its transitions,
|
||||
// their outer ends from the start and from the end of the curve, into it above 0; a length below 0 keeps the ramp along the transition
|
||||
// click <x y z>: a point clicked when the line was laid, its curves fitted to them
|
||||
// element <straight|transition|arc> <vertex> <chainage> <length> <R at the start> <R at the end> <cant> <start x> <start z> <direction x> <direction z>
|
||||
// radii signed with the turn, 0 for no curvature
|
||||
@@ -147,6 +149,8 @@ void mark(scene::layer_handle const Layer)
|
||||
for (auto const &arc : vertex.arcs)
|
||||
text += format(" %.1f", arc.cant);
|
||||
}
|
||||
if (vertex.own_ramps())
|
||||
text += format(" ramps %.3f %.3f %.3f %.3f", vertex.ramp_in_offset, vertex.ramp_in_length, vertex.ramp_out_offset, vertex.ramp_out_length);
|
||||
lines.push_back(text);
|
||||
}
|
||||
for (auto const &click : entry.clicks)
|
||||
@@ -168,6 +172,8 @@ void mark(scene::layer_handle const Layer)
|
||||
alignment::vertex reversed_vertex(alignment::vertex Vertex)
|
||||
{
|
||||
std::swap(Vertex.transition_in, Vertex.transition_out);
|
||||
std::swap(Vertex.ramp_in_offset, Vertex.ramp_out_offset);
|
||||
std::swap(Vertex.ramp_in_length, Vertex.ramp_out_length);
|
||||
if (Vertex.compound && false == Vertex.arcs.empty())
|
||||
{
|
||||
struct part
|
||||
@@ -343,6 +349,8 @@ std::optional<alignment::vertex> read_vertex(std::istringstream &Line, scene::la
|
||||
for (auto &arc : vertex.arcs)
|
||||
Line >> arc.cant;
|
||||
}
|
||||
if (word == "ramps")
|
||||
Line >> vertex.ramp_in_offset >> vertex.ramp_in_length >> vertex.ramp_out_offset >> vertex.ramp_out_length;
|
||||
}
|
||||
position = Context.to_world(position);
|
||||
vertex.position = {position.x, position.z};
|
||||
|
||||
@@ -30,17 +30,15 @@ constexpr double kAtEnd{0.3};
|
||||
constexpr double kRampClear{6.0};
|
||||
|
||||
// the curved switches bent from the basic ones, table 11.9: the radius of the basic switch, the limiting curvature of the
|
||||
// diverging track and the least radius of the main track, the values allowed by way of exception in the brackets, 0 for none
|
||||
// diverging track and the least radius of the main track; the values in its brackets, allowed only by way of exception, are past
|
||||
// them as well
|
||||
struct bent_limit
|
||||
{
|
||||
double radius;
|
||||
double branch;
|
||||
double branch_exception;
|
||||
double main;
|
||||
double main_exception;
|
||||
};
|
||||
constexpr bent_limit kBent[]{
|
||||
{300.0, 4.000e-3, 4.673e-3, 1505.522, 749.722}, {500.0, 4.000e-3, 4.673e-3, 501.730, 375.638}, {760.0, 3.333e-3, 0.0, 497.250, 0.0}, {1200.0, 2.169e-3, 0.0, 750.001, 0.0}, {2500.0, 1.063e-3, 0.0, 1510.0, 0.0}};
|
||||
constexpr bent_limit kBent[]{{300.0, 4.000e-3, 1505.522}, {500.0, 4.000e-3, 501.730}, {760.0, 3.333e-3, 497.250}, {1200.0, 2.169e-3, 750.001}, {2500.0, 1.063e-3, 1510.0}};
|
||||
|
||||
double heading_at(std::vector<track_point> const &Track, double const Station)
|
||||
{
|
||||
@@ -147,8 +145,6 @@ switch_report check(std::vector<track_point> const &Main, std::vector<track_poin
|
||||
report.curved = main.sharpest > kStraight;
|
||||
report.transition = report.curved && std::abs(main.last - main.first) > std::max(2e-6, 0.05 * std::max(std::abs(main.first), std::abs(main.last)));
|
||||
|
||||
if (report.transition)
|
||||
report.notes.emplace_back(STR_C("On a transition curve: only by way of exception, by consent of the Zaklad Linii Kolejowych (9.7 pkt 12); the plan gives the radii of both tracks at the start and at the end of the switch"));
|
||||
// the curvature of each track of one sign all along it, the cases KZW I and KZW III of 9.7 pkt 12, not KZW II
|
||||
if (branch.low < -kStraight && branch.high > kStraight)
|
||||
report.warnings.emplace_back(STR_C("The curvature of the diverging track turns from one side to the other within the switch (KZW II), which isn't allowed (9.7 pkt 12)"));
|
||||
@@ -162,14 +158,9 @@ switch_report check(std::vector<track_point> const &Main, std::vector<track_poin
|
||||
else
|
||||
{
|
||||
if (branch.sharpest > limit->branch + 1e-9)
|
||||
report.warnings.emplace_back(limit->branch_exception > 0.0 && branch.sharpest <= limit->branch_exception + 1e-9 ?
|
||||
format(STR_C("The curvature of the diverging track %.3f 1/km is over the limiting %.3f 1/km of table 11.9, up to %.3f 1/km only by consent of the Zaklad Linii Kolejowych"), branch.sharpest * 1000.0,
|
||||
limit->branch * 1000.0, limit->branch_exception * 1000.0) :
|
||||
format(STR_C("The curvature of the diverging track %.3f 1/km is over the limiting %.3f 1/km for the switch of R %.0f m (table 11.9)"), branch.sharpest * 1000.0, limit->branch * 1000.0, Radius));
|
||||
report.warnings.emplace_back(format(STR_C("The curvature of the diverging track %.3f 1/km is over the limiting %.3f 1/km for the switch of R %.0f m (table 11.9)"), branch.sharpest * 1000.0, limit->branch * 1000.0, Radius));
|
||||
if (main.sharpest > kStraight && 1.0 / main.sharpest < limit->main - 1e-6)
|
||||
report.warnings.emplace_back(limit->main_exception > 0.0 && 1.0 / main.sharpest >= limit->main_exception - 1e-6 ?
|
||||
format(STR_C("The main track bent to R %.0f m, below the least %.0f m of table 11.9, down to %.0f m only by consent of the Zaklad Linii Kolejowych"), 1.0 / main.sharpest, limit->main, limit->main_exception) :
|
||||
format(STR_C("The main track bent to R %.0f m, below the least %.0f m for the switch of R %.0f m (table 11.9)"), 1.0 / main.sharpest, limit->main, Radius));
|
||||
report.warnings.emplace_back(format(STR_C("The main track bent to R %.0f m, below the least %.0f m for the switch of R %.0f m (table 11.9)"), 1.0 / main.sharpest, limit->main, Radius));
|
||||
}
|
||||
if (Ratio > 0.0 && Ratio < 9.41)
|
||||
report.warnings.emplace_back(format(STR_C("A switch of 1:%.3f isn't bent in the running and the main tracks: none of 1:9.403 nor steeper than 1:9 (11.4 pkt 4)"), Ratio));
|
||||
@@ -177,8 +168,7 @@ switch_report check(std::vector<track_point> const &Main, std::vector<track_poin
|
||||
|
||||
// the cant: the same all along the switch, a ramp off it by 6 m at least or ending at its ends (11.4 pkt 7, 9.6 pkt 16-17)
|
||||
if (std::abs(report.cant_end - report.cant_start) > 1.0)
|
||||
report.warnings.emplace_back(format(STR_C("The cant changes within the switch, %.0f to %.0f mm: it's to stay the same over it (11.4 pkt 7); a straight ramp through the switch only by consent of the Zaklad Linii Kolejowych"),
|
||||
report.cant_start, report.cant_end));
|
||||
report.warnings.emplace_back(format(STR_C("The cant changes within the switch, %.0f to %.0f mm: it's to stay the same over it (11.4 pkt 7)"), report.cant_start, report.cant_end));
|
||||
auto const low{std::min(From, To)};
|
||||
auto const high{std::max(From, To)};
|
||||
for (auto const end : ramp_ends(Line))
|
||||
|
||||
@@ -11975,8 +11975,6 @@ msgstr "W%d R%d %.0f m przechyłka %.0f mm"
|
||||
msgid "W%d R %.0f m cant %.0f mm"
|
||||
msgstr "W%d R %.0f m przechyłka %.0f mm"
|
||||
|
||||
msgid "On a transition curve: only by way of exception, by consent of the Zaklad Linii Kolejowych (9.7 pkt 12); the plan gives the radii of both tracks at the start and at the end of the switch"
|
||||
msgstr "Na krzywej przejściowej: tylko wyjątkowo, za zgodą Zakładu Linii Kolejowych (9.7 pkt 12); na planie podaje się promienie obu torów na początku i na końcu rozjazdu"
|
||||
|
||||
msgid "The curvature of the diverging track turns from one side to the other within the switch (KZW II), which isn't allowed (9.7 pkt 12)"
|
||||
msgstr "Krzywizna toru zwrotnego zmienia znak w obrębie rozjazdu (KZW II), co jest niedozwolone (9.7 pkt 12)"
|
||||
@@ -11987,14 +11985,10 @@ msgstr "Krzywizna toru zasadniczego zmienia znak w obrębie rozjazdu, co jest ni
|
||||
msgid "The basic switch of R %.0f m isn't in table 11.9, its limiting curvature isn't checked"
|
||||
msgstr "Rozjazdu podstawowego R %.0f m nie ma w tabeli 11.9, jego krzywizna graniczna nie jest sprawdzana"
|
||||
|
||||
msgid "The curvature of the diverging track %.3f 1/km is over the limiting %.3f 1/km of table 11.9, up to %.3f 1/km only by consent of the Zaklad Linii Kolejowych"
|
||||
msgstr "Krzywizna toru zwrotnego %.3f 1/km ponad graniczną %.3f 1/km z tabeli 11.9; do %.3f 1/km tylko za zgodą Zakładu Linii Kolejowych"
|
||||
|
||||
msgid "The curvature of the diverging track %.3f 1/km is over the limiting %.3f 1/km for the switch of R %.0f m (table 11.9)"
|
||||
msgstr "Krzywizna toru zwrotnego %.3f 1/km ponad graniczną %.3f 1/km dla rozjazdu R %.0f m (tabela 11.9)"
|
||||
|
||||
msgid "The main track bent to R %.0f m, below the least %.0f m of table 11.9, down to %.0f m only by consent of the Zaklad Linii Kolejowych"
|
||||
msgstr "Tor zasadniczy wygięty do R %.0f m, poniżej najmniejszego %.0f m z tabeli 11.9; do %.0f m tylko za zgodą Zakładu Linii Kolejowych"
|
||||
|
||||
msgid "The main track bent to R %.0f m, below the least %.0f m for the switch of R %.0f m (table 11.9)"
|
||||
msgstr "Tor zasadniczy wygięty do R %.0f m, poniżej najmniejszego %.0f m dla rozjazdu R %.0f m (tabela 11.9)"
|
||||
@@ -12002,8 +11996,6 @@ msgstr "Tor zasadniczy wygięty do R %.0f m, poniżej najmniejszego %.0f m dla r
|
||||
msgid "A switch of 1:%.3f isn't bent in the running and the main tracks: none of 1:9.403 nor steeper than 1:9 (11.4 pkt 4)"
|
||||
msgstr "Rozjazdu 1:%.3f nie łukuje się w torach szlakowych i głównych: ani 1:9,403, ani o skosie większym niż 1:9 (11.4 pkt 4)"
|
||||
|
||||
msgid "The cant changes within the switch, %.0f to %.0f mm: it's to stay the same over it (11.4 pkt 7); a straight ramp through the switch only by consent of the Zaklad Linii Kolejowych"
|
||||
msgstr "Przechyłka zmienia się w obrębie rozjazdu, z %.0f na %.0f mm: ma być stała na całej jego długości (11.4 pkt 7); prostoliniowa rampa w rozjeździe tylko za zgodą Zakładu Linii Kolejowych"
|
||||
|
||||
msgid "A cant ramp starts or ends within the switch, %.1f m from its start: at the start or the end of the switch, or 6 m off it at least (9.6 pkt 16-17)"
|
||||
msgstr "Rampa przechyłkowa zaczyna się albo kończy w obrębie rozjazdu, %.1f m od jego początku: ma się zaczynać na początku albo końcu rozjazdu, albo co najmniej 6 m od niego (9.6 pkt 16-17)"
|
||||
@@ -12046,3 +12038,51 @@ msgstr "tor zwrotny R %s na początku, %s na końcu"
|
||||
|
||||
msgid "cant %.0f mm at the start, %.0f mm at the end"
|
||||
msgstr "przechyłka %.0f mm na początku, %.0f mm na końcu"
|
||||
|
||||
msgid "The cant changes within the switch, %.0f to %.0f mm: it's to stay the same over it (11.4 pkt 7)"
|
||||
msgstr "Przechyłka zmienia się w obrębie rozjazdu, z %.0f na %.0f mm: ma być stała na całej jego długości (11.4 pkt 7)"
|
||||
|
||||
msgid "Vertex %zu: the cant ramp in reaches back past the start of the line, cut %.1f m shorter"
|
||||
msgstr "Wierzchołek %zu: rampa wejściowa sięga przed początek linii, skrócona o %.1f m"
|
||||
|
||||
msgid "Vertex %zu: the cant ramp in reaches back into the curve before it, cut %.1f m shorter"
|
||||
msgstr "Wierzchołek %zu: rampa wejściowa sięga w łuk przed nim, skrócona o %.1f m"
|
||||
|
||||
msgid "Vertex %zu: the cant ramp out reaches past the end of the line, cut %.1f m shorter"
|
||||
msgstr "Wierzchołek %zu: rampa wyjściowa sięga za koniec linii, skrócona o %.1f m"
|
||||
|
||||
msgid "Vertex %zu: the cant ramps in and out of the curve overlap by %.1f m"
|
||||
msgstr "Wierzchołek %zu: rampy wejściowa i wyjściowa łuku zachodzą na siebie o %.1f m"
|
||||
|
||||
msgid "Vertex %zu: the cant ramp of %.1f m is shorter than the %.0f m a cant of %.0f mm asks for"
|
||||
msgstr "Wierzchołek %zu: rampa przechyłkowa %.1f m jest krótsza niż %.0f m, których wymaga przechyłka %.0f mm"
|
||||
|
||||
msgid "Cant ramps"
|
||||
msgstr "Rampy przechyłkowe"
|
||||
|
||||
msgid "Ramp in along the transition curve"
|
||||
msgstr "Rampa wejściowa wzdłuż krzywej przejściowej"
|
||||
|
||||
msgid "Ramp out along the transition curve"
|
||||
msgstr "Rampa wyjściowa wzdłuż krzywej przejściowej"
|
||||
|
||||
msgid "The norms recommend the cant ramp along the transition curve; off it, it may lie on the straight before the curve or on the arc, a switch on the transition keeping the same cant all along"
|
||||
msgstr "Normy zalecają rampę przechyłkową wzdłuż krzywej przejściowej; poza nią może leżeć na prostej przed łukiem albo na łuku, a rozjazd na przejściówce ma wtedy na całej długości tę samą przechyłkę"
|
||||
|
||||
msgid "into the curve %.1f m"
|
||||
msgstr "w głąb łuku %.1f m"
|
||||
|
||||
msgid "How far the outer end of the ramp lies into the curve from its end, below 0 out along the straight before it"
|
||||
msgstr "Jak daleko w głąb łuku od jego końca leży zewnętrzny koniec rampy; poniżej 0 na prostej przed łukiem"
|
||||
|
||||
msgid "length %.1f m"
|
||||
msgstr "długość %.1f m"
|
||||
|
||||
msgid "The length of the ramp, the cant rising evenly along it"
|
||||
msgstr "Długość rampy, przechyłka rośnie wzdłuż niej równomiernie"
|
||||
|
||||
msgid "km %s - %s, %.2f mm/m"
|
||||
msgstr "km %s - %s, %.2f mm/m"
|
||||
|
||||
msgid "ramp %.0f m, %.0f mm"
|
||||
msgstr "rampa %.0f m, %.0f mm"
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
#include "doctest.h"
|
||||
#include "editor/editorAlignment.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -391,3 +393,48 @@ TEST_CASE("alignment: bends clicked close along a curve make one compound curve,
|
||||
}
|
||||
CHECK(design.vertices.size() < 12);
|
||||
}
|
||||
|
||||
TEST_CASE("alignment: a cant ramp moved off the transition curve onto the straight before it") {
|
||||
auto design{straights({300.0, 300.0}, {30.0 * pi / 180.0}, 80.0)};
|
||||
auto &vertex{design.vertices.front()};
|
||||
vertex.radius = 800.0;
|
||||
vertex.transition_in = vertex.transition_out = 60.0;
|
||||
vertex.cant = 60.0;
|
||||
auto const along{alignment::compute(design)};
|
||||
REQUIRE(along.valid);
|
||||
REQUIRE(along.ramps.size() == 2);
|
||||
auto const start{along.ramps.front().from};
|
||||
CHECK(along.ramps.front().to - start == doctest::Approx(60.0));
|
||||
CHECK(alignment::evaluate(along, start + 30.0).cant == doctest::Approx(30.0));
|
||||
|
||||
// the whole ramp on the straight, the transition with the full cant all along it, as a switch laid on it wants it
|
||||
vertex.ramp_in_offset = -40.0;
|
||||
vertex.ramp_in_length = 40.0;
|
||||
auto const moved{alignment::compute(design)};
|
||||
REQUIRE(moved.valid);
|
||||
REQUIRE(moved.ramps.size() == 2);
|
||||
CHECK(moved.ramps.front().own);
|
||||
CHECK(moved.ramps.front().from == doctest::Approx(start - 40.0));
|
||||
CHECK(moved.ramps.front().to == doctest::Approx(start));
|
||||
CHECK(alignment::evaluate(moved, start - 50.0).cant == doctest::Approx(0.0));
|
||||
CHECK(alignment::evaluate(moved, start - 20.0).cant == doctest::Approx(30.0));
|
||||
CHECK(alignment::evaluate(moved, start + 10.0).cant == doctest::Approx(60.0));
|
||||
CHECK(alignment::evaluate(moved, start + 50.0).cant == doctest::Approx(60.0));
|
||||
// on the straight the cant leans the way the curve turns
|
||||
CHECK(alignment::evaluate(moved, start - 20.0).turn == alignment::evaluate(moved, start + 100.0).turn);
|
||||
// 40 m are too short to raise 60 mm at 80 km/h
|
||||
CHECK(std::any_of(moved.warnings.begin(), moved.warnings.end(), [](std::string const &Warning) { return Warning.find("cant ramp of") != std::string::npos; }));
|
||||
|
||||
// the paths end where the ramp starts and ends, their rolls going along it
|
||||
auto const paths{alignment::pieces(moved, design, alignment::minimum_pieces(moved, design))};
|
||||
auto const meets = [&](double const Chainage) {
|
||||
auto const point{alignment::evaluate(moved, Chainage).position};
|
||||
return std::any_of(paths.begin(), paths.end(), [&](segment_data const &Path) { return glm::distance(Path.points[segment_data::point::start], point) < 0.05; });
|
||||
};
|
||||
CHECK(meets(start - 40.0));
|
||||
CHECK(meets(start));
|
||||
for (std::size_t i = 1; i < paths.size(); ++i)
|
||||
CHECK(paths[i].rolls[0] == doctest::Approx(paths[i - 1].rolls[1]).epsilon(1e-4));
|
||||
auto const turned{std::max_element(paths.begin(), paths.end(), [](segment_data const &A, segment_data const &B) { return std::abs(A.rolls[1]) < std::abs(B.rolls[1]); })};
|
||||
CHECK(std::abs(turned->rolls[1]) == doctest::Approx(glm::degrees(std::asin(60.0 / design.norms.gauge))).epsilon(1e-3));
|
||||
}
|
||||
|
||||
@@ -55,7 +55,6 @@ TEST_CASE("switch on a curve: the curvatures of its tracks on a transition curve
|
||||
CHECK(report.branch_start < 0.0);
|
||||
CHECK(report.branch_end < 0.0);
|
||||
CHECK(false == says(report.warnings, "KZW II"));
|
||||
CHECK(says(report.notes, "transition curve"));
|
||||
// laid on the ramp, the cant changing under it
|
||||
CHECK(report.cant_start == doctest::Approx(25.0).epsilon(0.02));
|
||||
CHECK(report.cant_end == doctest::Approx(40.0).epsilon(0.02));
|
||||
|
||||
@@ -578,6 +578,7 @@ bool TSegment::RenderLoft( gfx::vertex_array &Output, glm::dvec3 const &Origin,
|
||||
pt,
|
||||
glm::normalize( norm ),
|
||||
glm::vec2 { ( jmm1 * ShapePoints[ j ].texture.x + m1 * ShapePoints[ j + iNumShapePoints ].texture.x ) / texturescale, tv1 } );
|
||||
roll_vertex( Output.back(), pos1, parallel1, s - step );
|
||||
}
|
||||
// jeśli jest wskaźnik do tablicy
|
||||
if (p && *p && !j) // to dla pierwszego punktu
|
||||
@@ -596,6 +597,7 @@ bool TSegment::RenderLoft( gfx::vertex_array &Output, glm::dvec3 const &Origin,
|
||||
pt,
|
||||
glm::normalize( norm ),
|
||||
glm::vec2 { ( jmm2 * ShapePoints[ j ].texture.x + m2 * ShapePoints[ j + iNumShapePoints ].texture.x ) / texturescale, tv2 } );
|
||||
roll_vertex( Output.back(), pos2, parallel2, s );
|
||||
}
|
||||
// jeśli jest wskaźnik do tablicy
|
||||
// to dla pierwszego punktu
|
||||
@@ -618,6 +620,7 @@ bool TSegment::RenderLoft( gfx::vertex_array &Output, glm::dvec3 const &Origin,
|
||||
pt,
|
||||
glm::normalize( norm ),
|
||||
glm::vec2 { ShapePoints[ j ].texture.x / texturescale, tv1 } );
|
||||
roll_vertex( Output.back(), pos1, parallel1, s - step );
|
||||
|
||||
pt = parallel2 * ( jmm2 * ( ShapePoints[ j ].position.x - fOffsetX.first ) + m2 * ( ShapePoints[ j ].position.x - fOffsetX.second ) ) + pos2;
|
||||
pt.y += ShapePoints[ j ].position.y;
|
||||
@@ -628,6 +631,7 @@ bool TSegment::RenderLoft( gfx::vertex_array &Output, glm::dvec3 const &Origin,
|
||||
pt,
|
||||
glm::normalize( norm ),
|
||||
glm::vec2 { ShapePoints[ j ].texture.x / texturescale, tv2 } );
|
||||
roll_vertex( Output.back(), pos2, parallel2, s );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -638,6 +642,25 @@ bool TSegment::RenderLoft( gfx::vertex_array &Output, glm::dvec3 const &Origin,
|
||||
return true;
|
||||
};
|
||||
|
||||
void TSegment::roll_vertex( gfx::basic_vertex &Vertex, glm::vec3 const &Position, glm::vec3 const &Parallel, double const Distance ) const {
|
||||
if( false == m_baked_roll.has_value() ) {
|
||||
return;
|
||||
}
|
||||
auto const delta { GetRoll( std::clamp( Distance, 0.0, fLength ) ) - *m_baked_roll };
|
||||
if( std::abs( delta ) < 1e-6f ) {
|
||||
return;
|
||||
}
|
||||
auto const c { std::cos( delta ) };
|
||||
auto const s { std::sin( delta ) };
|
||||
// across the path and up turned the way the profiles are turned by the roll, along the path as it was
|
||||
auto const turn = [&]( glm::vec3 const &Vector ) {
|
||||
auto const across { glm::dot( Vector, Parallel ) };
|
||||
auto const along { Vector - Parallel * across - glm::vec3 { 0.f, Vector.y, 0.f } };
|
||||
return along + Parallel * ( across * c + Vector.y * s ) + glm::vec3 { 0.f, -across * s + Vector.y * c, 0.f }; };
|
||||
Vertex.position = Position + turn( Vertex.position - Position );
|
||||
Vertex.normal = turn( Vertex.normal );
|
||||
}
|
||||
|
||||
bool TSegment::RenderLoftSteps( gfx::vertex_array &Output, glm::dvec3 const &Origin, gfx::vertex_array const &ShapePoints, double fTextureLength, int const Steps ) const
|
||||
{
|
||||
if( fTsBuffer.empty() || Steps < 1 || fLength <= 0.0 )
|
||||
@@ -675,7 +698,8 @@ bool TSegment::RenderLoftSteps( gfx::vertex_array &Output, glm::dvec3 const &Ori
|
||||
point.y += rest * from.position.y + Share * to.position.y;
|
||||
auto normal { ( rest * from.normal.x + Share * to.normal.x ) * Parallel };
|
||||
normal.y += rest * from.normal.y + Share * to.normal.y;
|
||||
Output.emplace_back( point, glm::normalize( normal ), glm::vec2 { rest * from.texture.x + Share * to.texture.x, V } ); };
|
||||
Output.emplace_back( point, glm::normalize( normal ), glm::vec2 { rest * from.texture.x + Share * to.texture.x, V } );
|
||||
roll_vertex( Output.back(), Position, Parallel, Share * fLength ); };
|
||||
|
||||
glm::vec3 pos1, pos2, parallel1, parallel2;
|
||||
station( 0, pos1, parallel1 );
|
||||
@@ -917,6 +941,9 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig
|
||||
Ring.emplace_back( pt, glm::normalize( norm ), glm::vec2{ shape.texture.x, 0.f } );
|
||||
Wear.push_back( Span.rampwidth != 0.0 ? static_cast<float>( std::clamp( ( Span.rampwidth > 0.0 ? outside - worn : worn - outside ) / std::abs( Span.rampwidth ) + 1.0, 0.0, 1.0 ) ) : 1.f );
|
||||
}
|
||||
for( auto &vertex : Ring ) {
|
||||
roll_vertex( vertex, position, parallel, Distance );
|
||||
}
|
||||
};
|
||||
|
||||
auto const texturelength { static_cast<float>( Span.texturelength ) };
|
||||
|
||||
@@ -102,6 +102,9 @@ class TSegment
|
||||
std::vector<double> m_starts; // distance from Point1 to the start of each part
|
||||
std::optional<std::pair<glm::dvec3, glm::dvec3>> m_joints[ 2 ];
|
||||
double m_dense { 0.0 };
|
||||
// a switch makes the profiles of its rails and its bed at the mean of the rolls of its paths: lofted along a path, they're turned
|
||||
// from it to the roll of the path there, so a switch on a cant ramp follows it; none for the other paths
|
||||
std::optional<float> m_baked_roll;
|
||||
|
||||
glm::dvec3 GetFirstDerivative(double const fTime) const;
|
||||
double RombergIntegral(double const fA, double const fB) const;
|
||||
@@ -111,6 +114,8 @@ class TSegment
|
||||
glm::dvec3 RaInterpolate(double const t) const;
|
||||
glm::dvec3 RaInterpolate0(double const t) const;
|
||||
std::size_t piece_at(double const s) const;
|
||||
// the vertex of a profile lofted at the point and across the path there, turned from the baked roll to the one of the path at the distance
|
||||
void roll_vertex( gfx::basic_vertex &Vertex, glm::vec3 const &Position, glm::vec3 const &Parallel, double const Distance ) const;
|
||||
|
||||
public:
|
||||
bool bCurve = false;
|
||||
@@ -200,6 +205,9 @@ public:
|
||||
void
|
||||
set_dense( double const Distance ) {
|
||||
m_dense = Distance; }
|
||||
void
|
||||
set_baked_roll( std::optional<float> const Roll ) {
|
||||
m_baked_roll = Roll; }
|
||||
/*
|
||||
void
|
||||
Render();
|
||||
|
||||
@@ -1086,6 +1086,13 @@ void TTrack::init_segments( bool const Initial ) {
|
||||
fTexHeightOffset = texheightoffset;
|
||||
SwitchExtension->Segments[ index ]->InitChain( std::move( chain ) );
|
||||
}
|
||||
// the profiles of the switch are made at the mean of the rolls of its paths; lofted, they're turned from it to the roll of
|
||||
// each path along it, so a switch on a cant ramp follows the ramp to its ends
|
||||
float mean1, mean2;
|
||||
profile_rolls( mean1, mean2 );
|
||||
for( std::size_t index = 0; index < 2; ++index ) {
|
||||
SwitchExtension->Segments[ index ]->set_baked_roll( mean1 );
|
||||
}
|
||||
}
|
||||
|
||||
if( Initial ) {
|
||||
|
||||
Reference in New Issue
Block a user