17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 20:19:20 +02:00

feat(editor): switch drive placed with a switch leans with the grade and the cant of the track at the points, raised as the simulation raises a canted track

This commit is contained in:
maj00r
2026-10-08 01:53:34 +02:00
parent 095dae91b6
commit 898b4fcaf7
6 changed files with 52 additions and 3 deletions

View File

@@ -1042,6 +1042,7 @@ class editor_mode : public application_mode, private editor_track::observer
std::vector<std::string> rest; // parameters after the rotation
bool described{false};
std::string track;
glm::dvec2 tilt{0.0}; // rot.x and rot.z of a described template, degrees
};
struct standing_template
{

View File

@@ -288,7 +288,7 @@ std::size_t editor_mode::place_templates(std::vector<template_item> const &Items
include_info info;
if (false == editor_includes::load(item.file, info, Error))
continue;
directive = editor_includes::directive(item.file, info, editor_includes::parameter_count(item.file), local, static_cast<float>(item.yaw), item.track);
directive = editor_includes::directive(item.file, info, editor_includes::parameter_count(item.file), local, static_cast<float>(item.yaw), item.track, item.tilt);
}
else
{

View File

@@ -350,6 +350,38 @@ void editor_mode::selftest_step()
WriteLog(format("SELFTEST frame %s %.2f: %.3f %.3f %.3f widening %.4f cant %.4f setback %.4f", name.c_str(), station, at.position.x, at.position.y, at.position.z, at.widening[side], at.cant[side], sweep->setback(at)));
}
}
else if (command == "switchdrive")
{
int index{-1}, side{0};
words >> index >> side;
scan_switch_drives();
m_switch.drive = index;
m_switch.drive_side = side;
WriteLog("SELFTEST switchdrive: " + (index >= 0 && index < static_cast<int>(m_switch.drives.size()) ? m_switch.drives[index].name : std::string{"none"}));
}
else if (command == "drivetilt")
{
std::string name;
words >> name;
auto *model{simulation::Instances.find(name)};
auto *track{simulation::Paths.find(name.substr(0, name.find('_')))};
if (model == nullptr || track == nullptr)
{
WriteLog("SELFTEST drivetilt: no " + name);
continue;
}
auto const &path{track->m_paths[0]};
auto const transform{glm::dmat3(model->rotation_scale())};
auto const across{transform * glm::dvec3{1.0, 0.0, 0.0}};
auto const forward{transform * glm::dvec3{0.0, 0.0, 1.0}};
auto const direction{glm::normalize(glm::dvec2{forward.x, forward.z})};
auto const lateral{across.x * -direction.y + across.z * direction.x};
auto const cone{-lateral * std::tan(glm::radians(static_cast<double>(path.rolls[0])))};
auto const control{path.points[segment_data::point::control1]};
auto const grade{control.y / std::hypot(control.x, control.z)};
WriteLog(format("SELFTEST drivetilt %s: angles %.3f %.3f %.3f, +x rises %.4f (cone %.4f), +z rises %.4f (grade %.4f), origin %.3f %.3f %.3f, points %.3f", name.c_str(), model->Angles().x, model->Angles().y, model->Angles().z, across.y, cone, forward.y, grade,
model->location().x, model->location().y, model->location().z, path.points[segment_data::point::start].y));
}
else if (command == "fouling")
{
std::map<std::string, std::string> values;

View File

@@ -4747,6 +4747,14 @@ bool editor_mode::place_switch_drive(TTrack &Switch)
item.yaw = yaw < 0.0 ? yaw + 360.0 : yaw;
item.described = true;
item.track = Switch.name();
{
auto const along{control != glm::dvec3{} ? control : main.points[segment_data::point::end] - start};
auto const run{glm::length(plan_of(along))};
auto const roll{static_cast<double>(main.rolls[0])};
item.tilt = {run > 1e-9 ? -glm::degrees(std::atan(along.y / run)) : 0.0, roll};
if (Global.bRollFix)
item.location.y += 0.75 * std::abs(std::sin(glm::radians(roll)));
}
std::string error;
if (place_templates({item}, error) == 0)
{

View File

@@ -644,7 +644,7 @@ std::string compose_directive(std::string const &File, std::vector<std::string>
return text + " end";
}
std::string directive(std::string const &File, include_info const &Info, int const Parameters, glm::dvec3 const &Location, std::optional<float> Yaw, std::string const &Track)
std::string directive(std::string const &File, include_info const &Info, int const Parameters, glm::dvec3 const &Location, std::optional<float> Yaw, std::string const &Track, glm::dvec2 const &Tilt)
{
std::vector<std::string> values;
for (auto id = 1; id <= Parameters; ++id)
@@ -668,6 +668,14 @@ std::string directive(std::string const &File, include_info const &Info, int con
{
value = number(*Yaw);
}
else if (role == "rot.x" && Tilt.x != 0.0)
{
value = number(Tilt.x);
}
else if (role == "rot.z" && Tilt.y != 0.0)
{
value = number(Tilt.y);
}
else if (role.starts_with("rot.") && value.empty())
{
value = "0";

View File

@@ -71,7 +71,7 @@ bool complete(include_info const &Info, int Parameters, std::string *Issue = nul
// builds include directive which places specified template. Location and Yaw are the placement to pass through
// the parameters with matching roles, in the coordinates of the place the directive goes to; without Yaw the
// rotation parameters receive their default values
std::string directive(std::string const &File, include_info const &Info, int Parameters, glm::dvec3 const &Location, std::optional<float> Yaw, std::string const &Track = {});
std::string directive(std::string const &File, include_info const &Info, int Parameters, glm::dvec3 const &Location, std::optional<float> Yaw, std::string const &Track = {}, glm::dvec2 const &Tilt = glm::dvec2{0.0});
// splits include directive into the name of the included file and the values of the parameters, both as they're
// written. returns: false if the text isn't a complete include directive