mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-05 19:29:11 +01:00
Sieć trakcyjna: kotwienia, kotwienie środkowe, parasole i wysięgniki rozstawione, konsole 4890/4690
Sam kod exe z gałęzi siec-trakcyjna od poprzedniego commita (bez testów, notatek i danych z tests/catenary). Dane (data/traction_*.txt) leżą poza repozytorium. - kotwienia ciężarowe i stałe (0404/0405, przewody zakotwione osobno, sieci bez własnych danych: network <symbol> as <kod>) - kotwienie środkowe 0406/0408/0418/0416: lina, V i zaciski na linie nośnej liczonej jak przęsło, obejma 4160 na teownikach - parasole i wysięgniki rozstawione na konsolach 4890, wysięgi pomocnicze 0167 na belkach 4690, trzeci wysięgnik w osi słupa, lina nośna z innego wysięgnika (messenger_from) - przęsła w nietypowych sytuacjach nie przechodzą na stary wygląd (bez Y, bez wieszaków, lina nad przewodem) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GfTogWDsfCE8RGFGvm2eyp
This commit is contained in:
@@ -140,6 +140,9 @@ TTraction::Load( cParser *parser, glm::dvec3 const &pOrigin ) {
|
||||
|
||||
std::string token { parser->getToken<std::string>() };
|
||||
std::string catenarytype;
|
||||
double catenarytension[ 2 ] { 0.0, 0.0 };
|
||||
glm::dvec3 catenaryrope2[ 2 ];
|
||||
bool catenaryrope2set[ 2 ] { false, false };
|
||||
while( false == token.empty()
|
||||
&& token != "endtraction" ) {
|
||||
|
||||
@@ -152,11 +155,24 @@ TTraction::Load( cParser *parser, glm::dvec3 const &pOrigin ) {
|
||||
// symbol typu sieci, np. YwsC120-2C; starsze wersje symulatora pomijają ten dopisek
|
||||
catenarytype = parser->getToken<std::string>( false );
|
||||
}
|
||||
else if( token == "rope2" ) {
|
||||
// koniec drugiej liny nośnej przy kotwieniu: "rope2 start|end x y z"
|
||||
auto const which { parser->getToken<std::string>() };
|
||||
auto const point { LoadPoint( *parser ) + pOrigin };
|
||||
auto const end { which == "end" ? 1 : 0 };
|
||||
catenaryrope2[ end ] = point;
|
||||
catenaryrope2set[ end ] = true;
|
||||
}
|
||||
else if( token == "tension" ) {
|
||||
// naciąg liny nośnej i przewodów jezdnych w daN inny niż w typie sieci (brakujące ciężary w kotwieniu)
|
||||
parser->getTokens( 2 );
|
||||
*parser >> catenarytension[ 0 ] >> catenarytension[ 1 ];
|
||||
}
|
||||
token = parser->getToken<std::string>();
|
||||
}
|
||||
|
||||
Init(); // przeliczenie parametrów
|
||||
catenary_span_assign( *this, catenarytype );
|
||||
catenary_span_assign( *this, catenarytype, catenarytension[ 0 ], catenarytension[ 1 ], catenaryrope2, catenaryrope2set );
|
||||
|
||||
// calculate traction location
|
||||
location( glm::mix( pPoint2, pPoint1, 0.5 ) );
|
||||
|
||||
@@ -280,6 +280,7 @@ void cantilever_catalog::parse( std::vector<std::string> const &Tokens, std::str
|
||||
else if( key == "top" ) { number( pole.top, good ); }
|
||||
else if( key == "length" ) { number( pole.length, good ); }
|
||||
else if( key == "depth" ) { number( pole.depth_top, good ); number( pole.depth_base, good ); }
|
||||
else if( key == "width" ) { number( pole.width, good ); }
|
||||
else if( key == "mount_max" ) { number( pole.mount_max, good ); }
|
||||
else if( key == "mount_min" ) { number( pole.mount_min, good ); pole.has_mount_min = true; }
|
||||
else if( key == "turn" ) { number( pole.turn, good ); }
|
||||
@@ -287,10 +288,13 @@ void cantilever_catalog::parse( std::vector<std::string> const &Tokens, std::str
|
||||
else if( key == "strut" ) { text( pole.strut ); }
|
||||
else if( key == "stay" ) { text( pole.stay ); }
|
||||
else if( key == "steady" ) { text( pole.steady ); }
|
||||
else if( key == "console" ) { text( pole.console ); }
|
||||
else if( key == "steady_console" ) { text( pole.steady_console ); }
|
||||
else { report( entry, "unknown keyword \"" + key + "\"" ); good = false; --index; }
|
||||
}
|
||||
else {
|
||||
if( key == "back" ) { text( mount.back ); }
|
||||
else if( key == "console" ) { mount.console = true; number( mount.console_x[ 0 ], good ); number( mount.console_x[ 1 ], good ); number( mount.console_face, good ); }
|
||||
else if( key == "hinge" ) { text( mount.hinge ); number( mount.hinge_eye[ 0 ], good ); number( mount.hinge_eye[ 1 ], good ); }
|
||||
else if( key == "rod" ) { text( mount.rod ); }
|
||||
else if( key == "twin" ) { text( mount.twin ); }
|
||||
@@ -2071,6 +2075,20 @@ bool solve_cantilever_on_pole( cantilever_catalog const &Catalog, cantilever_sch
|
||||
return solve_cantilever_on_pole( Catalog, Scheme, Pole, Distance, RailHead, Messenger, Overrides, cantilever_umbrella(), Result );
|
||||
}
|
||||
|
||||
void spread_mounts( cantilever_pole const &Pole, cantilever_result const &First, cantilever_result const &Second,
|
||||
cantilever_umbrella &FirstSide, cantilever_umbrella &SecondSide ) {
|
||||
|
||||
FirstSide.shared.clear();
|
||||
SecondSide.shared.clear();
|
||||
for( auto const *role : { "stay", "strut", "steady" } ) {
|
||||
auto const a { First.values.find( std::string( "mount." ) + role ) }, b { Second.values.find( std::string( "mount." ) + role ) };
|
||||
if( a == First.values.end() || b == Second.values.end() ) { continue; }
|
||||
auto shared { 0.5 * ( a->second + b->second ) };
|
||||
if( Pole.mount_max != 0.0 ) { shared = std::min( shared, std::max( Pole.mount_max, std::min( a->second, b->second ) ) ); }
|
||||
FirstSide.shared[ role ] = SecondSide.shared[ role ] = shared;
|
||||
}
|
||||
}
|
||||
|
||||
void umbrella_mounts( cantilever_catalog const &Catalog, cantilever_pole const &Pole, cantilever_result const &First, cantilever_result const &Second,
|
||||
cantilever_umbrella &FirstSide, cantilever_umbrella &SecondSide ) {
|
||||
|
||||
@@ -2142,17 +2160,40 @@ bool solve_on_pole_once( cantilever_catalog const &Catalog, cantilever_scheme co
|
||||
if( mount == nullptr ) { fail( std::string( Use ) + " mount \"" + Name + "\" isn't in the catalogue" ); }
|
||||
return mount;
|
||||
};
|
||||
auto const *strut { mountpart( Pole.strut, "strut" ) };
|
||||
auto const *stay { mountpart( Pole.stay, "stay" ) };
|
||||
auto const *steady { Scheme.steady_mounted ? mountpart( Pole.steady, "steady arm" ) : nullptr };
|
||||
// wysięgniki rozstawione: mocowania -06 tej samej karty (4610-06, 4620-06, 4630-06) na konsoli słupa (4890); rozstawione
|
||||
// wysięgi pomocnicze (0167, bez ukośnika i odciągu) na belce 4690 (steady_console, karta 33-0519), gdy słup ją ma
|
||||
auto const onconsole = [ & ]( std::string const &Name ) {
|
||||
if( false == Umbrella.spread || Name.empty() ) { return Name; }
|
||||
return Name.substr( 0, Name.find( '-' ) ) + "-06";
|
||||
};
|
||||
auto const steadyonly { Scheme.roles.count( "strut" ) == 0 && Scheme.roles.count( "stay" ) == 0 };
|
||||
std::map<std::string, cantilever_mount const *> consoles;
|
||||
if( Umbrella.spread ) {
|
||||
for( auto const *role : { "stay", "strut", "steady" } ) {
|
||||
if( ( std::string( role ) != "steady" && steadyonly ) || ( std::string( role ) == "steady" && false == Scheme.steady_mounted ) ) { continue; }
|
||||
// sam wysięg pomocniczy (0167) na belce 4690; wysięg wysięgnika trzyzaczepowego na tej samej konsoli 4890, co reszta
|
||||
auto const &name { steadyonly && false == Pole.steady_console.empty() ? Pole.steady_console : Pole.console };
|
||||
auto const *found { name.empty() ? nullptr : Catalog.mount( name ) };
|
||||
if( found == nullptr || false == found->console ) {
|
||||
return fail( name.empty() ? "the pole has no console for spread cantilevers (\"console\" / \"steady_console\" in its entry)" : "console \"" + name + "\" isn't in the catalogue as a console" );
|
||||
}
|
||||
consoles[ role ] = found;
|
||||
}
|
||||
}
|
||||
auto const *strut { mountpart( onconsole( Pole.strut ), "strut" ) };
|
||||
auto const *stay { mountpart( onconsole( Pole.stay ), "stay" ) };
|
||||
auto const *steady { Scheme.steady_mounted ? mountpart( onconsole( Pole.steady ), "steady arm" ) : nullptr };
|
||||
if( strut == nullptr || stay == nullptr || ( Scheme.steady_mounted && steady == nullptr ) ) { return false; }
|
||||
// oś słupa wzdłuż toru: przy wysięgnikach rozstawionych przesunięta od płaszczyzny wysięgnika
|
||||
auto const polex { Umbrella.spread ? Umbrella.console_x : 0.0 };
|
||||
|
||||
std::vector<cantilever_placement> poleparts;
|
||||
auto const add = [ & ]( std::string const &Role, std::string const &Part, std::string const &Model, double const Y, double const Z ) {
|
||||
auto const add = [ & ]( std::string const &Role, std::string const &Part, std::string const &Model, double const Y, double const Z, double const X = 0.0 ) {
|
||||
cantilever_placement placement;
|
||||
placement.role = Role;
|
||||
placement.part = Part;
|
||||
placement.model = Model;
|
||||
placement.position[ 0 ] = X;
|
||||
placement.position[ 1 ] = Y;
|
||||
placement.position[ 2 ] = Z;
|
||||
poleparts.push_back( placement );
|
||||
@@ -2163,15 +2204,25 @@ bool solve_on_pole_once( cantilever_catalog const &Catalog, cantilever_scheme co
|
||||
auto const fix = [ & ]( std::string const &Role, cantilever_mount const &Mount, double Bolts ) {
|
||||
// parasol: mocowanie dwustronne na wspólnej wysokości, bez tyłu; po stronie z nakrętkami jego połówka "twin"
|
||||
auto const shared { Umbrella.shared.find( Role ) };
|
||||
auto const twin { shared != Umbrella.shared.end() && false == Mount.twin.empty() };
|
||||
if( twin ) { Bolts = RailHead + shared->second; }
|
||||
auto const twin { false == Umbrella.spread && shared != Umbrella.shared.end() && false == Mount.twin.empty() };
|
||||
if( twin || ( Umbrella.spread && shared != Umbrella.shared.end() ) ) { Bolts = RailHead + shared->second; }
|
||||
auto const height { Bolts - RailHead };
|
||||
heights[ Role ] = height;
|
||||
if( height > Pole.top ) { notes.push_back( Role + " mount " + to_text( height - Pole.top ) + " m above the top of the pole" ); }
|
||||
auto const depth { Pole.depth( height ) };
|
||||
auto const face { Distance - 0.5 * depth };
|
||||
auto face { Distance - 0.5 * depth };
|
||||
auto const found { consoles.find( Role ) };
|
||||
auto const *console { found != consoles.end() ? found->second : nullptr };
|
||||
if( console != nullptr ) {
|
||||
// konsola na słupie (jedna na rolę, stawia ją jedna strona), mocowanie na jej punkcie, bliżej toru o jej grubość
|
||||
if( Umbrella.console_parts ) {
|
||||
add( Role + "_console", console->name, "", face, Bolts, polex );
|
||||
if( false == console->back.empty() ) { add( Role + "_console_back", console->back, "", face + depth, Bolts, polex ); }
|
||||
}
|
||||
face += console->console_face;
|
||||
}
|
||||
add( Role + "_mount", ( twin && Umbrella.nuts.count( Role ) ) ? Mount.twin : Mount.name, "", face, Bolts );
|
||||
if( false == twin && false == Mount.back.empty() ) { add( Role + "_back", Mount.back, "", face + depth, Bolts ); }
|
||||
if( false == twin && console == nullptr && false == Mount.back.empty() ) { add( Role + "_back", Mount.back, "", face + depth, Bolts ); }
|
||||
if( false == Mount.hinge.empty() ) { add( Role + "_hinge", Mount.hinge, "", face + Mount.point[ 0 ], Bolts + Mount.point[ 1 ] ); }
|
||||
if( false == Mount.rod.empty() ) { add( Role + "_rod", Mount.rod, "", face + Mount.point[ 0 ], Bolts + Mount.point[ 1 ] ); }
|
||||
return cantilever_point { face + Mount.attach_y(), Bolts + Mount.attach_z() };
|
||||
@@ -2179,7 +2230,7 @@ bool solve_on_pole_once( cantilever_catalog const &Catalog, cantilever_scheme co
|
||||
|
||||
// słup bramki stawia bramka
|
||||
if( Umbrella.pole && false == Pole.gantry ) {
|
||||
add( "pole", Pole.name, Pole.model, Distance, RailHead );
|
||||
add( "pole", Pole.name, Pole.model, Distance, RailHead, polex );
|
||||
if( Pole.turn != 0.0 ) {
|
||||
// model obrócony wokół pionu (zwis na bramce: profil szerszym bokiem wzdłuż toru)
|
||||
auto const angle { Pole.turn * 3.14159265358979323846 / 180.0 };
|
||||
@@ -2188,7 +2239,7 @@ bool solve_on_pole_once( cantilever_catalog const &Catalog, cantilever_scheme co
|
||||
std::copy( std::begin( turned ), std::end( turned ), poleparts.back().rotation );
|
||||
}
|
||||
// fundament ma to samo zero co słup (oś słupa na wysokości główki szyny)
|
||||
if( false == Pole.foundation.empty() ) { add( "foundation", Pole.name + "_foundation", Pole.foundation, Distance, RailHead ); }
|
||||
if( false == Pole.foundation.empty() ) { add( "foundation", Pole.name + "_foundation", Pole.foundation, Distance, RailHead, polex ); }
|
||||
}
|
||||
auto const raise { Messenger.z - Scheme.height };
|
||||
auto staybolts { Scheme.mount_stay + raise - stay->attach_z() };
|
||||
|
||||
@@ -114,6 +114,7 @@ struct cantilever_pole {
|
||||
double length { 0.0 }; // długość, na której biegnie zbieżność, liczona od góry
|
||||
double depth_top { 0.0 }; // wymiar od toru w głąb (prostopadle do toru) u góry
|
||||
double depth_base { 0.0 }; // to samo na końcu długości zbieżności
|
||||
double width { 0.0 }; // wzdłuż toru (słup kratowy 161x: wysokość ceownika, karta 33-1611-E wymiar a); 0 = nieznana
|
||||
double mount_max { 0.0 }; // najwyżej położona oś śrub mocowania; 0 = bez ograniczenia (zwis na bramce: ujemna, pod dźwigarem)
|
||||
double mount_min { 0.0 }; // najniżej położona oś śrub mocowania (zwis: nad jego końcem); tylko gdy has_mount_min
|
||||
bool has_mount_min { false };
|
||||
@@ -122,6 +123,8 @@ struct cantilever_pole {
|
||||
std::string strut; // mocowanie ukośnika (część z punktem axis i zawiasem)
|
||||
std::string stay; // mocowanie izolatora odciągu
|
||||
std::string steady; // mocowanie izolatora wysięgu pomocniczego (schematy z trzema zaczepami)
|
||||
std::string console; // konsola wysięgników rozstawionych (wpis "mount ... console"); pusta = słup ich nie nosi
|
||||
std::string steady_console; // belka 4690 rozstawionych wysięgów pomocniczych (karta 33-0519, wysięgi 0167); mocowanie wysięgu na niej
|
||||
// słup bramki z wysięgnikiem (zrobiony z wpisu "mast" z mocowaniami): model stawia bramka, nie wysięgnik; mount_max pod
|
||||
// dźwigarem bramki liczy sceneria wg jej poziomu (mast_low/mast_high minus below_beam), tu - pod dolnym mocowaniem
|
||||
bool gantry { false };
|
||||
@@ -140,6 +143,11 @@ struct cantilever_mount {
|
||||
std::string hinge; // zawias obrotowy stawiany w punkcie axis (wspornik ukośnika)
|
||||
std::string rod; // pręt z uchem stawiany w punkcie eye (uchwyt odciągu)
|
||||
std::string twin; // połówka z nakrętkami mocowania dwustronnego (parasol); pusta = mocowanie bez regulacji, parasol z dwóch niezależnych
|
||||
// konsola wysięgników rozstawionych (4890, karty 0517/0518): dwa punkty mocowań w X (wzdłuż toru) i ich odsunięcie od
|
||||
// płaszczyzny słupa (Y, ujemne - w stronę toru); na konsoli mocowania -06 (4610-06, 4620-06, 4630-06)
|
||||
bool console { false };
|
||||
double console_x[ 2 ] { 0.0, 0.0 };
|
||||
double console_face { 0.0 };
|
||||
double point[ 2 ] { 0.0, 0.0 }; // Y, Z punktu axis (gdy jest zawias) albo eye
|
||||
double hinge_eye[ 2 ] { 0.0, 0.0 }; // Y, Z ucha zawiasu względem jego zera
|
||||
// punkt zaczepu izolatora względem zera mocowania
|
||||
@@ -293,6 +301,11 @@ struct cantilever_umbrella {
|
||||
std::map<std::string, double> shared; // rola mocowania -> wspólna wysokość osi śrub nad główką szyny
|
||||
std::set<std::string> nuts; // role mocowań, które po tej stronie są połówką z nakrętkami
|
||||
bool pole { true }; // czy stawiać słup (stawia go tylko jedna strona)
|
||||
// wysięgniki rozstawione: oba po tej samej stronie słupa, na konsolach (konsola słupa), mocowania -06 na wspólnych
|
||||
// wysokościach z shared; płaszczyzna wysięgnika przechodzi przez punkt mocowania na konsoli, oś słupa leży w X = ConsoleX
|
||||
bool spread { false };
|
||||
double console_x { 0.0 };
|
||||
bool console_parts { true }; // czy stawiać konsole (stawia je jedna strona)
|
||||
};
|
||||
bool solve_cantilever_on_pole( cantilever_catalog const &Catalog, cantilever_scheme const &Scheme, cantilever_pole const &Pole,
|
||||
double Distance, double RailHead, cantilever_point const &Messenger, std::map<std::string, std::string> const &Overrides,
|
||||
@@ -306,6 +319,11 @@ bool solve_cantilever_on_pole( cantilever_catalog const &Catalog, cantilever_sch
|
||||
void umbrella_mounts( cantilever_catalog const &Catalog, cantilever_pole const &Pole, cantilever_result const &First, cantilever_result const &Second,
|
||||
cantilever_umbrella &FirstSide, cantilever_umbrella &SecondSide );
|
||||
|
||||
// wspólne wysokości mocowań wysięgników rozstawionych: każda rola obu wysięgników na jednej konsoli, na średniej wysokości
|
||||
// (nie ponad mount_max słupa). Wypełnia shared obu stron
|
||||
void spread_mounts( cantilever_pole const &Pole, cantilever_result const &First, cantilever_result const &Second,
|
||||
cantilever_umbrella &FirstSide, cantilever_umbrella &SecondSide );
|
||||
|
||||
// część ustawiona w układzie scenerii symulatora (X, Y w górę, Z), względem punktu osi przewodów jezdnych
|
||||
struct cantilever_scene_part {
|
||||
double offset[ 3 ] { 0.0, 0.0, 0.0 }; // przesunięcie od punktu osi przewodów jezdnych
|
||||
|
||||
@@ -99,7 +99,10 @@ void type_registry::load_tables() {
|
||||
double mass { 0.0 }, diameter { 0.0 };
|
||||
stream >> mass >> diameter;
|
||||
if( stream.fail() || mass <= 0.0 ) { report( "Catenary: bad wire entry in \"" + filename + "\" (line " + std::to_string( linenumber ) + ")" ); continue; }
|
||||
m_wires[ key ] = { mass, diameter * 0.001 };
|
||||
// dalej opcjonalnie: przekrój mm² i moduł sprężystości GPa
|
||||
double area { 0.0 }, modulus { 0.0 };
|
||||
if( stream >> area ) { stream >> modulus; }
|
||||
m_wires[ key ] = { mass, diameter * 0.001, std::max( 0.0, area ) * 1e-6, std::max( 0.0, modulus ) * 1e9 };
|
||||
}
|
||||
else if( kind == "spacing" ) {
|
||||
int span { 0 };
|
||||
@@ -267,25 +270,34 @@ bool solve_span_points( network_definition const &Definition, std::vector<double
|
||||
input.y_at_start = Ystart;
|
||||
input.y_at_end = Yend;
|
||||
span_result result;
|
||||
try {
|
||||
// bez rozstawu wieszaków: odcinek do kotwienia, same liny
|
||||
result = ( Hangergaps.empty() ?
|
||||
solve_free_span( type, length, input.height_start, input.height_end ) :
|
||||
solve_span( type, input, 4.0 ) );
|
||||
}
|
||||
catch( std::exception const &exception ) {
|
||||
Error = exception.what();
|
||||
return false;
|
||||
}
|
||||
// lina poniżej przewodu jezdnego: przęsło za długie albo za mała wysokość konstrukcyjna dla tego typu sieci
|
||||
for( auto const *line : { &result.messenger, &result.y_start, &result.y_end } ) {
|
||||
for( auto const &point : *line ) {
|
||||
if( point.y - ( type.messenger_count > 1 ? type.messenger_stack : 0.0 ) < -0.01 ) {
|
||||
Error = "messenger wire would hang below the contact wire (span too long or suspension too low for this network type)";
|
||||
return false;
|
||||
auto solved { false };
|
||||
// nietypowe przęsła (niska wysokość konstrukcyjna jednego końca, naciąg liny obniżony brakującymi ciężarami poniżej naciągu
|
||||
// linki Y): zamiast rysowania po staremu najpierw bez linek Y, potem jako odcinek bez wieszaków
|
||||
for( int attempt = 0; attempt < 3 && false == solved; ++attempt ) {
|
||||
try {
|
||||
if( attempt == 2 || Hangergaps.empty() ) { result = solve_free_span( type, length, input.height_start, input.height_end ); }
|
||||
else {
|
||||
if( attempt == 1 ) { input.y_at_start = input.y_at_end = false; }
|
||||
result = solve_span( type, input, 4.0 );
|
||||
}
|
||||
solved = true;
|
||||
}
|
||||
catch( std::exception const &exception ) {
|
||||
Error = exception.what();
|
||||
}
|
||||
}
|
||||
if( false == solved ) { return false; }
|
||||
// lina poniżej przewodu jezdnego (przęsło za długie albo za mała wysokość konstrukcyjna dla tego typu sieci): podciągnięta
|
||||
// nad przewód, wieszaki skrócone - przęsło wygląda dziwnie, ale się rysuje
|
||||
// (końce zostają tam, gdzie są punkty przęsła: najniżej na prostej między nimi)
|
||||
auto const lowest { ( type.messenger_count > 1 ? type.messenger_stack : 0.0 ) + 0.02 };
|
||||
for( auto *line : { &result.messenger, &result.y_start, &result.y_end } ) {
|
||||
for( auto &point : *line ) {
|
||||
auto const chord { input.height_start + ( input.height_end - input.height_start ) * std::clamp( point.x / length, 0.0, 1.0 ) };
|
||||
point.y = std::max( point.y, std::min( lowest, chord ) );
|
||||
}
|
||||
}
|
||||
for( auto &hanger : result.hangers ) { hanger.length = std::max( hanger.length, 0.0 ); }
|
||||
Solution.length = length;
|
||||
Solution.result = std::move( result );
|
||||
return true;
|
||||
@@ -435,10 +447,27 @@ void build_geometry( network_definition const &Definition, span_solution const &
|
||||
if( type.messenger_count > 1 ) {
|
||||
std::vector<vec3> middle;
|
||||
if( false == start.empty() ) { middle.push_back( start.back() ); }
|
||||
// końce dolnej liny podane osobno (kotwienie): przesunięcie rozłożone liniowo wzdłuż przęsła
|
||||
vec3 shiftstart { 0.0, 0.0, 0.0 }, shiftend { 0.0, 0.0, 0.0 };
|
||||
if( Points.messenger2_start_set && false == result.messenger.empty() ) {
|
||||
auto const from { rope( result.messenger.front().x, result.messenger.front().y - type.messenger_stack ) };
|
||||
shiftstart = vec3 { Points.messenger2_start.x - from.x, Points.messenger2_start.y - from.y, Points.messenger2_start.z - from.z };
|
||||
}
|
||||
if( Points.messenger2_end_set && false == result.messenger.empty() ) {
|
||||
auto const to { rope( result.messenger.back().x, result.messenger.back().y - type.messenger_stack ) };
|
||||
shiftend = vec3 { Points.messenger2_end.x - to.x, Points.messenger2_end.y - to.y, Points.messenger2_end.z - to.z };
|
||||
}
|
||||
for( auto const &point : result.messenger ) {
|
||||
auto const instart { reachstart > 0.0 && point.x < reachstart + 1e-6 };
|
||||
auto const inend { reachend > 0.0 && point.x > length - reachend - 1e-6 };
|
||||
if( false == instart && false == inend ) { middle.push_back( rope( point.x, point.y - type.messenger_stack ) ); }
|
||||
if( false == instart && false == inend ) {
|
||||
auto at { rope( point.x, point.y - type.messenger_stack ) };
|
||||
auto const t { length > 1e-9 ? point.x / length : 0.0 };
|
||||
at.x += shiftstart.x * ( 1.0 - t ) + shiftend.x * t;
|
||||
at.y += shiftstart.y * ( 1.0 - t ) + shiftend.y * t;
|
||||
at.z += shiftstart.z * ( 1.0 - t ) + shiftend.z * t;
|
||||
middle.push_back( at );
|
||||
}
|
||||
}
|
||||
if( false == end.empty() ) { middle.push_back( end.front() ); }
|
||||
polyline( middle, element_kind::messenger );
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace catenary {
|
||||
struct wire_data {
|
||||
double mass { 0.0 }; // kg/m
|
||||
double diameter { 0.0 }; // m
|
||||
double area { 0.0 }; // m², przekrój czynny (do wydłużeń sprężystych); 0 = nieznany
|
||||
double modulus { 0.0 }; // Pa, moduł sprężystości przewodu (liny skręcane: niższy niż drutu); 0 = nieznany
|
||||
};
|
||||
|
||||
// pełny opis typu sieci: dane dla solvera i dane potrzebne tylko do rysowania
|
||||
@@ -67,6 +69,9 @@ struct vec3 { double x, y, z; };
|
||||
struct span_points {
|
||||
vec3 contact_start, contact_end;
|
||||
vec3 messenger_start, messenger_end;
|
||||
// druga (dolna) lina nośna kończy się gdzie indziej niż o odstęp lin pod pierwszą (uchwyt krańcowy w kotwieniu z dwiema liniami)
|
||||
bool messenger2_start_set { false }, messenger2_end_set { false };
|
||||
vec3 messenger2_start, messenger2_end;
|
||||
};
|
||||
|
||||
// policzone przęsło
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,6 +30,7 @@ void catenary_scene_data( std::string const &Directory );
|
||||
// Zmiany trafiają do plików sieci dopiero przy catenary_scene_save().
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include "world/catenary_suspension.h"
|
||||
#include "world/catenary_cantilever.h"
|
||||
#include "world/catenary_layout.h"
|
||||
@@ -87,6 +88,9 @@ std::size_t catenary_chain_add( std::string const &File, catenary::chain const &
|
||||
// zmienia łańcuch i robi jego przęsła od nowa (mniej niż dwa podwieszenia = łańcuch usunięty)
|
||||
bool catenary_chain_update( std::size_t Index, catenary::chain const &Data );
|
||||
void catenary_chain_remove( std::size_t Index );
|
||||
// kotwienie środkowe łańcucha: liczba wstawionych części (na słupach sąsiednich podwieszeń) i trójkątów brył (lina, V, zaciski);
|
||||
// false, gdy łańcuch go nie ma albo się nie złożyło
|
||||
bool catenary_chain_middle( std::size_t Index, std::size_t &Parts, std::size_t &Triangles );
|
||||
// łańcuch, do którego należy podwieszenie, i jego miejsce w łańcuchu; -1 gdy żaden
|
||||
int catenary_chain_of( std::size_t Suspension, std::size_t &Position );
|
||||
|
||||
@@ -97,6 +101,23 @@ std::string catenary_anchor_file( std::size_t Index );
|
||||
std::size_t catenary_anchor_parts( std::size_t Index );
|
||||
// wynik solvera ostatniego złożenia (b, s, ciężary, naciągi, uwagi); nullptr gdy usunięte
|
||||
catenary::tensioner_result const *catenary_anchor_result( std::size_t Index );
|
||||
// obrys złożonego urządzenia dla edytora (współrzędne scenerii): czoło słupa i oś rolki ruchomej na wysokości rolek, góra i spód
|
||||
// kolumny ciężarów; false gdy usunięte albo niezłożone
|
||||
bool catenary_anchor_shape( std::size_t Index, double ( &Shape )[ 4 ][ 3 ] );
|
||||
// karty urządzeń kotwienia do wyboru (bez odmian dla typów sieci, np. 0461-2x2): nazwa, kotwienie stałe, rolki szeregowe
|
||||
struct catenary_anchor_card {
|
||||
std::string card;
|
||||
bool fixed { false };
|
||||
bool series { false };
|
||||
bool split { false }; // dwa stosy (lina i przewody osobno)
|
||||
std::string title; // opis z danych (odmiany pokazane osobno, np. 0461-2x2)
|
||||
};
|
||||
// Only: puste - kotwienia całości; "messenger" / "contact" - samej liny / samych przewodów (przewody zakotwione osobno)
|
||||
std::vector<catenary_anchor_card> catenary_anchor_devices( std::string const &Only = {} );
|
||||
// katalog urządzeń naprężających (traction_tensioners.txt); nullptr, gdy go nie ma
|
||||
catenary::tensioner_catalog const *catenary_scene_tensioners();
|
||||
// łańcuch, który kończy się tym kotwieniem (Start: na początku), -1 gdy żaden
|
||||
int catenary_anchor_chain( std::size_t Index, bool &Start );
|
||||
// dodaje kotwienie, składa je i przebudowuje łańcuchy, które go używają. zwraca numer
|
||||
std::size_t catenary_anchor_add( std::string const &File, catenary::anchor const &Data );
|
||||
// zmienia kotwienie (także przywraca usunięte) i przebudowuje łańcuchy, które go używają
|
||||
|
||||
@@ -10,6 +10,8 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "stdafx.h"
|
||||
#include "world/catenary_span.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "world/Traction.h"
|
||||
#include "world/catenary_network.h"
|
||||
#include "utilities/Globals.h"
|
||||
@@ -31,6 +33,10 @@ struct catenary_span {
|
||||
gfx::geometrybank_handle solidbank; // osobny bank na bryły tego przęsła
|
||||
catenary_solid solid; // bryły do oglądania z bliska
|
||||
bool solidloaded { false };
|
||||
std::vector<catenary::solid_vertex> attached; // bryła dołączona (lina kotwienia), układ scenerii
|
||||
std::shared_ptr<catenary::network_definition> own; // kopia typu z naciągiem z dopisku "tension"
|
||||
bool rope2set[ 2 ] { false, false }; // końce drugiej liny nośnej z dopisku "rope2"
|
||||
catenary::vec3 rope2[ 2 ];
|
||||
};
|
||||
|
||||
namespace {
|
||||
@@ -43,11 +49,19 @@ definition( TTraction const &Traction ) {
|
||||
|
||||
catenary::span_points
|
||||
points( TTraction const &Traction ) {
|
||||
return {
|
||||
catenary::span_points result {
|
||||
{ Traction.pPoint1.x, Traction.pPoint1.y, Traction.pPoint1.z },
|
||||
{ Traction.pPoint2.x, Traction.pPoint2.y, Traction.pPoint2.z },
|
||||
{ Traction.pPoint3.x, Traction.pPoint3.y, Traction.pPoint3.z },
|
||||
{ Traction.pPoint4.x, Traction.pPoint4.y, Traction.pPoint4.z } };
|
||||
if( Traction.m_catenaryspan ) {
|
||||
auto const &span { *Traction.m_catenaryspan };
|
||||
result.messenger2_start_set = span.rope2set[ 0 ];
|
||||
result.messenger2_end_set = span.rope2set[ 1 ];
|
||||
result.messenger2_start = span.rope2[ 0 ];
|
||||
result.messenger2_end = span.rope2[ 1 ];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// długość podwieszenia Y, jaką typ sieci przewiduje dla tego przęsła; 0 gdy brak
|
||||
@@ -249,13 +263,17 @@ catenary_span_metal( TTraction const &Traction, bool const Fitting ) {
|
||||
|
||||
// przypisuje przęsłu typ sieci z dopisku "type" i dobiera rozstaw wieszaków
|
||||
void
|
||||
catenary_span_assign( TTraction &Traction, std::string const &Symbol ) {
|
||||
catenary_span_assign( TTraction &Traction, std::string const &Symbol, double const Messenger, double const Contact, glm::dvec3 const *Rope2, bool const *Rope2set ) {
|
||||
|
||||
Traction.m_catenaryspan.reset();
|
||||
if( Symbol.empty() ) { return; }
|
||||
|
||||
auto span { std::make_shared<catenary_span>() };
|
||||
span->symbol = Symbol;
|
||||
for( int end = 0; end < 2 && Rope2 != nullptr && Rope2set != nullptr; ++end ) {
|
||||
span->rope2set[ end ] = Rope2set[ end ];
|
||||
span->rope2[ end ] = catenary::vec3 { Rope2[ end ].x, Rope2[ end ].y, Rope2[ end ].z };
|
||||
}
|
||||
Traction.m_catenaryspan = span;
|
||||
if( false == Global.CatenaryProcedural ) { return; }
|
||||
|
||||
@@ -265,6 +283,13 @@ catenary_span_assign( TTraction &Traction, std::string const &Symbol ) {
|
||||
}
|
||||
span->definition = registry.find( Symbol );
|
||||
if( span->definition == nullptr ) { return; } // brak typu został już zgłoszony, przęsło rysuje się po staremu
|
||||
// naciąg z dopisku "tension" (daN): przęsło liczone z kopią typu
|
||||
if( Messenger > 0.0 || Contact > 0.0 ) {
|
||||
span->own = std::make_shared<catenary::network_definition>( *span->definition );
|
||||
if( Messenger > 0.0 ) { span->own->type.messenger_tension = 10.0 * Messenger; }
|
||||
if( Contact > 0.0 && span->own->type.contact_tension > 0.0 ) { span->own->type.contact_tension = 10.0 * Contact; }
|
||||
span->definition = span->own.get();
|
||||
}
|
||||
// odstęp wieszaków 0 w scenerii oznacza odcinek bez wieszaków (do kotwienia albo urządzenia naprężającego):
|
||||
// rysowane są same liny i przewody w liczbie wg typu, a rozstaw wieszaków zostaje pusty
|
||||
if( Traction.iNumSections == 0 ) { return; }
|
||||
@@ -274,6 +299,13 @@ catenary_span_assign( TTraction &Traction, std::string const &Symbol ) {
|
||||
std::hypot( Traction.pPoint2.x - Traction.pPoint1.x, Traction.pPoint2.z - Traction.pPoint1.z ) );
|
||||
}
|
||||
|
||||
// wygląd liny stalowej (ocynk, lekko zmatowiały)
|
||||
catenary_metal const &
|
||||
catenary_rope_metal() {
|
||||
static catenary_metal const steel { { 0.56f, 0.57f, 0.58f }, 0.8f, 0.30f, 0.20f };
|
||||
return steel;
|
||||
}
|
||||
|
||||
// symbol typu sieci przypisany przęsłu; pusty gdy brak
|
||||
std::string
|
||||
catenary_span_symbol( TTraction const &Traction ) {
|
||||
@@ -318,6 +350,7 @@ catenary_span_solid( TTraction &Traction, glm::dvec3 const &Camera ) {
|
||||
// kamera daleko: zwolnienie pamięci, linie wystarczą
|
||||
release( span.solid.wires );
|
||||
release( span.solid.fittings );
|
||||
release( span.solid.rope );
|
||||
span.solid = {};
|
||||
span.solidloaded = false;
|
||||
return {};
|
||||
@@ -344,6 +377,10 @@ catenary_span_solid( TTraction &Traction, glm::dvec3 const &Camera ) {
|
||||
auto data { vertices( Traction, fittings ) };
|
||||
span.solid.fittings = GfxRenderer->Insert( data, userdata, span.solidbank, GL_TRIANGLES );
|
||||
}
|
||||
if( false == span.attached.empty() ) {
|
||||
auto data { vertices( Traction, span.attached ) };
|
||||
span.solid.rope = GfxRenderer->Insert( data, userdata, span.solidbank, GL_TRIANGLES );
|
||||
}
|
||||
span.solidloaded = ( span.solid.wires != null_handle );
|
||||
return ( span.solidloaded ? span.solid : catenary_solid() );
|
||||
}
|
||||
@@ -358,6 +395,7 @@ drop_solid( TTraction &Traction ) {
|
||||
if( false == span.solidloaded ) { return; }
|
||||
release( span.solid.wires );
|
||||
release( span.solid.fittings );
|
||||
release( span.solid.rope );
|
||||
span.solid = {};
|
||||
span.solidloaded = false;
|
||||
}
|
||||
@@ -383,3 +421,12 @@ catenary_span_release( TTraction &Traction ) {
|
||||
drop_solid( Traction );
|
||||
release( Traction.m_geometry );
|
||||
}
|
||||
|
||||
// bryła spoza przęsła rysowana razem z nim (lina kotwienia); zrobi się przy następnym podejściu kamery
|
||||
bool
|
||||
catenary_span_attach( TTraction &Traction, std::vector<catenary::solid_vertex> const &Triangles ) {
|
||||
if( false == static_cast<bool>( Traction.m_catenaryspan ) ) { return false; }
|
||||
drop_solid( Traction );
|
||||
Traction.m_catenaryspan->attached = Triangles;
|
||||
return ( Traction.m_catenaryspan->definition != nullptr );
|
||||
}
|
||||
|
||||
@@ -14,10 +14,12 @@ http://mozilla.org/MPL/2.0/.
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rendering/geometrybank.h"
|
||||
|
||||
class TTraction;
|
||||
namespace catenary { struct solid_vertex; }
|
||||
|
||||
// ustawienia rysowania sieci, zmieniane z eu07.ini i z panelu ustawień
|
||||
struct catenary_settings {
|
||||
@@ -27,7 +29,11 @@ extern catenary_settings CatenarySettings;
|
||||
|
||||
// przypisuje przęsłu typ sieci z dopisku "type" i dobiera rozstaw wieszaków; wołane po wczytaniu punktów przęsła.
|
||||
// pusty symbol albo wyłączone rysowanie wg typu zostawia przęsło rysowane po staremu
|
||||
void catenary_span_assign( TTraction &Traction, std::string const &Symbol );
|
||||
// Messenger, Contact: naciąg liny nośnej i przewodów jezdnych w daN zamiast naciągu typu (dopisek "tension"); 0 = jak w typie
|
||||
// Rope2: końce drugiej liny nośnej podane w wpisie ("rope2 start|end x y z", kotwienie z dwiema liniami): [0] start, [1] koniec,
|
||||
// Rope2set - które podane
|
||||
void catenary_span_assign( TTraction &Traction, std::string const &Symbol, double Messenger = 0.0, double Contact = 0.0,
|
||||
glm::dvec3 const *Rope2 = nullptr, bool const *Rope2set = nullptr );
|
||||
// symbol typu sieci przypisany przęsłu; pusty gdy brak
|
||||
std::string catenary_span_symbol( TTraction const &Traction );
|
||||
// odcinki przęsła policzone wg typu sieci, dopisywane do Vertices; false gdy przęsło ma być narysowane po staremu
|
||||
@@ -37,6 +43,7 @@ bool catenary_span_lines( TTraction &Traction, gfx::vertex_array &Vertices );
|
||||
struct catenary_solid {
|
||||
gfx::geometry_handle wires;
|
||||
gfx::geometry_handle fittings;
|
||||
gfx::geometry_handle rope; // bryła dołączona z zewnątrz (lina urządzenia naprężającego na końcu przęsła), stal
|
||||
};
|
||||
// bryły tworzone są, gdy kamera jest blisko przęsła, i zwalniane, gdy się oddali
|
||||
catenary_solid catenary_span_solid( TTraction &Traction, glm::dvec3 const &Camera );
|
||||
@@ -44,6 +51,9 @@ catenary_solid catenary_span_solid( TTraction &Traction, glm::dvec3 const &Camer
|
||||
void catenary_span_refresh( TTraction &Traction );
|
||||
// zwalnia linie i bryły przęsła przed jego usunięciem
|
||||
void catenary_span_release( TTraction &Traction );
|
||||
// dołącza do brył przęsła bryłę spoza przęsła (lina kotwienia przy jego końcu; trójkąty w układzie scenerii), rysowaną
|
||||
// razem z nim z bliska, ze stali. Pusta lista odłącza. false, gdy przęsło nie jest rysowane wg typu sieci
|
||||
bool catenary_span_attach( TTraction &Traction, std::vector<catenary::solid_vertex> const &Triangles );
|
||||
|
||||
// wygląd metalu brył: kolor własny (sRGB), metaliczność, połysk i siła odbicia otoczenia, każde w zakresie 0–1
|
||||
struct catenary_metal {
|
||||
@@ -55,3 +65,5 @@ struct catenary_metal {
|
||||
// wygląd przewodów (Fitting = false) albo osprzętu przęsła o podanym materiale i stanie z wpisu scenerii.
|
||||
// wartości domyślne można zmienić bez kompilacji plikiem data/traction_materials.txt, czytanym przy pierwszym użyciu
|
||||
catenary_metal const &catenary_span_metal( TTraction const &Traction, bool Fitting );
|
||||
// wygląd liny stalowej (cięgło 4490 urządzenia naprężającego)
|
||||
catenary_metal const &catenary_rope_metal();
|
||||
|
||||
@@ -33,7 +33,7 @@ std::string normalize_path( std::string Path ) {
|
||||
|
||||
// słowa kluczowe wewnątrz wpisu podwieszenia
|
||||
bool is_keyword( std::string const &Token ) {
|
||||
static std::set<std::string> const keywords { "support", "scheme", "messenger", "contact", "insulators", "override", "skin", "at", "attach", "rope", "pole", "umbrella", "endsuspension" };
|
||||
static std::set<std::string> const keywords { "support", "scheme", "messenger", "contact", "insulators", "override", "skin", "at", "attach", "rope", "pole", "umbrella", "spread", "shared_pole", "endsuspension" };
|
||||
return keywords.find( Token ) != keywords.end();
|
||||
}
|
||||
|
||||
@@ -101,6 +101,15 @@ void parse_suspensions( std::vector<std::string> const &Tokens, std::string cons
|
||||
else if( key == "parallel" ) { one( line.parallel ); }
|
||||
else if( key == "anchor_start" ) { one( line.anchor_start ); }
|
||||
else if( key == "anchor_end" ) { one( line.anchor_end ); }
|
||||
else if( key == "anchor_start_contact" ) { one( line.anchor_start_contact ); }
|
||||
else if( key == "anchor_end_contact" ) { one( line.anchor_end_contact ); }
|
||||
else if( key == "middle" ) { one( line.middle ); }
|
||||
else if( key == "middle_device" ) { one( line.middle_device ); }
|
||||
else if( key == "middle_height" ) { number( line.middle_heights[ 0 ] ); number( line.middle_heights[ 1 ] ); }
|
||||
else if( key == "messenger_from" ) {
|
||||
std::string listed, holder;
|
||||
if( one( listed ) && one( holder ) ) { line.messenger_from.emplace_back( listed, holder ); }
|
||||
}
|
||||
else if( key == "hangers" ) { for( auto &value : line.hangers ) { number( value ); } }
|
||||
else if( key == "suspensions" ) {
|
||||
while( index < count && Tokens[ index ] != "endchain" && Tokens[ index ] != "node" ) { line.suspensions.push_back( Tokens[ index++ ] ); }
|
||||
@@ -177,12 +186,21 @@ void parse_suspensions( std::vector<std::string> const &Tokens, std::string cons
|
||||
else if( key == "network" ) { line.network = one(); }
|
||||
else if( key == "pole" ) { line.pole_type = one(); point( line.pole ); haspole = true; }
|
||||
else if( key == "toward" ) { point( line.toward ); hastoward = true; }
|
||||
else if( key == "on" ) { line.on = one(); }
|
||||
else if( key == "distance" ) { number( line.distance ); }
|
||||
else if( key == "color" ) { line.color = one(); }
|
||||
else if( key == "top_color" ) { line.top_color = one(); }
|
||||
else if( key == "elongation" ) { number( line.elongation ); }
|
||||
else if( key == "missing" ) { double value { 0.0 }; number( value ); line.missing = static_cast<int>( value ); }
|
||||
else if( key == "ground" ) { number( line.ground ); }
|
||||
else if( key == "height" ) { number( line.height ); }
|
||||
else if( key == "rope_height" ) { number( line.rope_height ); }
|
||||
else if( key == "insulators" ) {
|
||||
line.insulators = one();
|
||||
if( line.insulators != "new" && line.insulators != "old" && line.insulators != "messenger" && line.insulators != "contact" ) {
|
||||
report( line.name, "\"insulators\" takes new, old, messenger or contact" ); good = false;
|
||||
}
|
||||
}
|
||||
else if( key == "skin" ) { line.skin = one(); }
|
||||
else { report( line.name, "unexpected token \"" + key + "\" in an anchor" ); good = false; }
|
||||
}
|
||||
@@ -250,6 +268,14 @@ void parse_suspensions( std::vector<std::string> const &Tokens, std::string cons
|
||||
}
|
||||
else { report( entry.name, "\"" + key + "\" needs three numbers: a point in scenery coordinates" ); good = false; }
|
||||
}
|
||||
else if( key == "shared_pole" ) {
|
||||
if( list.empty() ) { entry.shared_pole = true; }
|
||||
else { report( entry.name, "\"shared_pole\" takes no values" ); good = false; }
|
||||
}
|
||||
else if( key == "spread" ) {
|
||||
if( list.size() == 3 && to_number( list[ 0 ], entry.spread[ 0 ] ) && to_number( list[ 1 ], entry.spread[ 1 ] ) && to_number( list[ 2 ], entry.spread[ 2 ] ) ) { entry.has_spread = true; }
|
||||
else { report( entry.name, "\"spread\" needs three numbers: the point on the console in the plane of the cantilever" ); good = false; }
|
||||
}
|
||||
else if( key == "umbrella" ) {
|
||||
if( list.size() == 1 ) { entry.umbrella = list.front(); }
|
||||
else { report( entry.name, "\"umbrella\" needs exactly one name" ); good = false; }
|
||||
@@ -270,6 +296,8 @@ void parse_suspensions( std::vector<std::string> const &Tokens, std::string cons
|
||||
if( entry.has_attach && entry.has_pole ) { report( entry.name, "\"attach\" and \"pole\" can't be used together" ); good = false; }
|
||||
if( entry.card == 0 ) { report( entry.name, "explicit points need a \"scheme\"" ); good = false; }
|
||||
if( false == entry.umbrella.empty() && false == entry.has_pole ) { report( entry.name, "\"umbrella\" needs a \"pole\"" ); good = false; }
|
||||
if( entry.shared_pole && false == entry.has_pole ) { report( entry.name, "\"shared_pole\" needs a \"pole\"" ); good = false; }
|
||||
if( entry.has_spread && false == entry.has_pole ) { report( entry.name, "\"spread\" needs a \"pole\"" ); good = false; }
|
||||
}
|
||||
else {
|
||||
if( entry.support.empty() ) { report( entry.name, "missing \"support\"" ); good = false; }
|
||||
@@ -318,9 +346,18 @@ std::string write_suspension( suspension const &Entry ) {
|
||||
if( Entry.has_attach ) { text += " attach " + point( Entry.attach ); }
|
||||
if( Entry.has_pole ) { text += " pole " + Entry.pole_type + " " + point( Entry.pole ); }
|
||||
if( false == Entry.umbrella.empty() ) { text += " umbrella " + Entry.umbrella; }
|
||||
if( Entry.has_spread ) { text += " spread " + point( Entry.spread ); }
|
||||
if( Entry.shared_pole ) { text += " shared_pole"; }
|
||||
return text + " endsuspension";
|
||||
}
|
||||
|
||||
std::string const &messenger_holder( chain const &Chain, std::string const &Listed ) {
|
||||
for( auto const &pair : Chain.messenger_from ) {
|
||||
if( pair.first == Listed && false == pair.second.empty() ) { return pair.second; }
|
||||
}
|
||||
return Listed;
|
||||
}
|
||||
|
||||
std::string write_chain( chain const &Entry ) {
|
||||
|
||||
auto const number = []( double const Value ) {
|
||||
@@ -337,6 +374,13 @@ std::string write_chain( chain const &Entry ) {
|
||||
if( false == Entry.parallel.empty() ) { text += " parallel " + Entry.parallel; }
|
||||
if( false == Entry.anchor_start.empty() ) { text += " anchor_start " + Entry.anchor_start; }
|
||||
if( false == Entry.anchor_end.empty() ) { text += " anchor_end " + Entry.anchor_end; }
|
||||
if( false == Entry.anchor_start_contact.empty() ) { text += " anchor_start_contact " + Entry.anchor_start_contact; }
|
||||
if( false == Entry.anchor_end_contact.empty() ) { text += " anchor_end_contact " + Entry.anchor_end_contact; }
|
||||
if( false == Entry.middle.empty() ) {
|
||||
text += " middle " + Entry.middle + ( Entry.middle_device != "0406" ? " middle_device " + Entry.middle_device : std::string() );
|
||||
if( Entry.middle_heights[ 0 ] > 0.0 || Entry.middle_heights[ 1 ] > 0.0 ) { text += " middle_height " + number( Entry.middle_heights[ 0 ] ) + " " + number( Entry.middle_heights[ 1 ] ); }
|
||||
}
|
||||
for( auto const &pair : Entry.messenger_from ) { text += " messenger_from " + pair.first + " " + pair.second; }
|
||||
text += " suspensions";
|
||||
for( auto const &name : Entry.suspensions ) { text += " " + name; }
|
||||
return text + " endchain";
|
||||
@@ -378,12 +422,17 @@ std::string write_anchor( anchor const &Entry ) {
|
||||
std::string text { "node " + number( Entry.range_max, 0 ) + " " + number( Entry.range_min, 0 ) + " " + ( Entry.name.empty() ? std::string( "none" ) : Entry.name ) + " anchor" };
|
||||
text += " device " + Entry.device;
|
||||
if( false == Entry.network.empty() ) { text += " network " + Entry.network; }
|
||||
text += " pole " + Entry.pole_type + " " + point( Entry.pole ) + " toward " + point( Entry.toward ) + " distance " + number( Entry.distance, 1 );
|
||||
text += " pole " + Entry.pole_type + " " + point( Entry.pole );
|
||||
if( false == Entry.on.empty() ) { text += " on " + Entry.on; }
|
||||
text += " toward " + point( Entry.toward ) + " distance " + number( Entry.distance, 1 );
|
||||
if( false == Entry.color.empty() ) { text += " color " + Entry.color; }
|
||||
if( false == Entry.top_color.empty() ) { text += " top_color " + Entry.top_color; }
|
||||
if( Entry.elongation != 0.0 ) { text += " elongation " + number( Entry.elongation, 3 ); }
|
||||
if( Entry.missing != 0 ) { text += " missing " + std::to_string( Entry.missing ); }
|
||||
if( Entry.ground != -0.50 ) { text += " ground " + number( Entry.ground, 2 ); }
|
||||
if( Entry.height > 0.0 ) { text += " height " + number( Entry.height, 3 ); }
|
||||
if( Entry.rope_height > 0.0 ) { text += " rope_height " + number( Entry.rope_height, 3 ); }
|
||||
if( false == Entry.insulators.empty() ) { text += " insulators " + Entry.insulators; }
|
||||
if( false == Entry.skin.empty() ) { text += " skin " + Entry.skin; }
|
||||
return text + " endanchor";
|
||||
}
|
||||
|
||||
@@ -38,6 +38,12 @@ struct suspension {
|
||||
// parasol: dwa wpisy ze słupem i tą samą nazwą parasola to dwa wysięgniki na jednym słupie, po przeciwnych stronach.
|
||||
// słup stawia pierwszy z nich; mocowania regulowane (z połówką z nakrętkami) idą na wspólną wysokość
|
||||
std::string umbrella;
|
||||
// wysięgnik rozstawiony (konsola 4890; para wpisów z tą samą nazwą "umbrella" po tej samej stronie słupa albo jeden): punkt na osi
|
||||
// płaszczyzny wysięgnika przy słupie (oś słupa przesunięta wzdłuż toru do punktu mocowania na konsoli), "spread x y z"
|
||||
// słup stawia inny wpis w tym samym miejscu (trzeci wysięgnik przy rozstawionych, w osi słupa): ten tylko z niego korzysta
|
||||
bool shared_pole { false };
|
||||
bool has_spread { false };
|
||||
double spread[ 3 ] { 0.0, 0.0, 0.0 };
|
||||
};
|
||||
|
||||
// łańcuch sieci: kolejne przęsła między podwieszeniami z listy (od kotwy do kotwy), wpis
|
||||
@@ -58,12 +64,28 @@ struct chain {
|
||||
double hangers[ 4 ] { 0.4, 4.0, 3.0, 0.04 }; // jak w node traction: najniższy wieszak, odstęp, liczba drutów, odstęp drutów
|
||||
std::string parallel; // przęsło bieżni wspólnej (jak "parallel" w node traction); puste = brak
|
||||
std::string anchor_start, anchor_end; // kotwienia (wpisy "anchor") przed pierwszym i za ostatnim podwieszeniem; puste = brak
|
||||
// przewody jezdne zakotwione osobno (inne kotwienie, zwykle na innym słupie; 0404 albo przewody rozdzielonego): wtedy
|
||||
// anchor_start/anchor_end trzyma samą linę nośną (0405, lina rozdzielonego). Puste = całość na anchor_start/anchor_end
|
||||
std::string anchor_start_contact, anchor_end_contact;
|
||||
// kotwienie środkowe (karty 63-0406 / 0408): podwieszenie, przy którym lina kotwienia środkowego jest zaciśnięta na linie nośnej,
|
||||
// i karta (0406 z izolacją, 0408 bez); lina idzie do słupów sąsiednich podwieszeń. Puste = brak
|
||||
std::string middle;
|
||||
std::string middle_device { "0406" };
|
||||
double middle_heights[ 2 ] { 0.0, 0.0 }; // uchwyty liny kotwienia na słupach przed i za (nad główką); 0 = lina nośna sąsiada
|
||||
// lina nośna z innego podwieszenia niż przewody jezdne (wysięgniki rozstawione na konsoli 4890, wysięgnik samej liny przy
|
||||
// odciągu przewodów): w punkcie łańcucha <podwieszenie z listy> przewody idą przez jego "at", lina przez "rope" podwieszenia
|
||||
// <trzymające linę>. Wpis "messenger_from <z listy> <trzymające linę>", przed "suspensions"
|
||||
std::vector<std::pair<std::string, std::string>> messenger_from;
|
||||
std::vector<std::string> suspensions; // nazwy podwieszeń z tego samego pliku, po kolei
|
||||
};
|
||||
|
||||
// podwieszenie, które trzyma linę nośną łańcucha w punkcie Listed (samo Listed, gdy nie ma wpisu messenger_from)
|
||||
std::string const &messenger_holder( chain const &Chain, std::string const &Listed );
|
||||
|
||||
// kotwienie ciężarowe (urządzenie naprężające z pliku traction_tensioners.txt) na słupie kotwowym, wpis
|
||||
// "node <max> <min> <nazwa> anchor device <karta> network <symbol typu> pole <słup> x y z toward x y z distance <m>
|
||||
// [color <kolor>] [top_color <kolor>] [elongation <m>] [missing <n>] [ground <m>] [skin <tekstura>] endanchor".
|
||||
// "node <max> <min> <nazwa> anchor device <karta> network <symbol typu> pole <słup> x y z [on <podwieszenie>] toward x y z distance <m>
|
||||
// [color <kolor>] [top_color <kolor>] [elongation <m>] [missing <n>] [ground <m>] [height <m>] [rope_height <m>] [insulators <rodzaj>] [skin <tekstura>]
|
||||
// endanchor".
|
||||
// pole: oś słupa na wysokości główki szyny; toward: punkt, z którego przychodzą druty (urządzenie leży w tym kierunku od
|
||||
// słupa); distance: odległość od kotwienia środkowego albo stałego. Łańcuch przypina się do niego "anchor_start/anchor_end",
|
||||
// a ostatnie przęsło (bez wieszaków) kończy się na uchwytach krańcowych urządzenia
|
||||
@@ -75,12 +97,19 @@ struct anchor {
|
||||
std::string network; // symbol typu sieci (traction_<symbol>.txt): numer typu i liczba przewodów jezdnych
|
||||
std::string pole_type;
|
||||
double pole[ 3 ] { 0.0, 0.0, 0.0 };
|
||||
std::string on; // kotwienie na istniejącym słupie: nazwa podwieszenia (z tego pliku), którego słup to
|
||||
// jest; słupa nie stawia, typ i punkt bierze z tamtego wpisu (pole tylko zapasowo)
|
||||
double toward[ 3 ] { 0.0, 0.0, 0.0 };
|
||||
double distance { 700.0 };
|
||||
std::string color, top_color;
|
||||
double elongation { 0.0 };
|
||||
int missing { 0 };
|
||||
double ground { -0.50 };
|
||||
double height { 0.0 }; // oś rolek nad główką szyny; 0 = z tablicy montażowej (6,70). Kotwienie stałe: przewody
|
||||
double rope_height { 0.0 }; // kotwienie stałe: uchwyt liny nośnej nad główką szyny; 0 = jak przy ostatnim słupie
|
||||
// izolatory w łańcuchach do drutów: puste = auto (rolkowe ESN-2025 na obu przy drutach zaśniedziałych, inaczej żywiczne 7150),
|
||||
// "new" żywiczne, "old" rolkowe na obu, "messenger" rolkowy tylko na linie nośnej, "contact" rolkowe tylko na przewodach
|
||||
std::string insulators;
|
||||
std::string skin;
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,13 +26,18 @@ http://mozilla.org/MPL/2.0/.
|
||||
// Ułożenie modeli (w układzie części):
|
||||
// rolka 4460 zero w osi, koło w płaszczyźnie X-Z, oś wzdłuż Y
|
||||
// części liniowe (uchwyty 4440/4450, łączniki, izolatory, śruby, wyrównywacz, uchwyty krańcowe, łączniki na linie)
|
||||
// zero w sworzniu od strony konstrukcji/dźwigni, biegną w +X do drugiego sworznia (długość z danych)
|
||||
// dźwignia 6406 zero w otworze I, otwory w +Z (I na dole), otwór III odsunięty w +X; przy otworze liny poniżej
|
||||
// otworu przewodów dźwignia odwrócona (obrót o 180 stopni wokół Y)
|
||||
// zero w sworzniu od strony konstrukcji/dźwigni, biegną w -X do drugiego sworznia (pusty węzeł,
|
||||
// np. hole_1 uchwytu 4440; długość z danych); "~część" w łańcuchu - postawiona odwrotnie (4440: zero
|
||||
// w wąskim końcu, widełki z osią rolki na -X; przy rolce ruchomej widełki są od strony słupa)
|
||||
// dźwignia 6406 zero w otworze osi II (mount_2 = III), otwory w +Z (I na dole), otwory na druty odsunięte w -X
|
||||
// modelu (w stronę drutów); przy otworze liny poniżej otworu przewodów dźwignia odwrócona (180 wokół Y)
|
||||
// pręt 6401/6402 zero na dole (pod stosem), w +Z do zaczepu na górze (długość z danych)
|
||||
// ciężar 63xx zero w środku spodu, w +Z; kolejne obracane o "turn" wokół Z; kolor numerem wykonania modelu
|
||||
// prowadnica 5070 zero w osi przesuwu pierścienia na dole, w +Z; mocowania do wsporników w -X (w stronę konstrukcji)
|
||||
// pierścień 5080 zero w osi stosu, poziomo, punkt przesuwu po prowadnicy w -X (w stronę konstrukcji); ring_at nad spodem stosu
|
||||
// lina linka rozciągana (część typu cord, zero w zaczepie, w +Z, skalowana wzdłuż Z)
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -77,6 +82,9 @@ struct tensioner_pulley {
|
||||
double diameter { 0.220 }; // po dnie rowka
|
||||
double width { 0.080 };
|
||||
int grooves { 2 };
|
||||
// krążek drugiego rowka jako osobny model (4460-11), stawiany w osi rolki; model rolki niesie wtedy oś i krążek
|
||||
// pierwszego rowka. Oba obracają się osobno o przewiniętą linę; pusty = cała rolka jednym modelem, obracana z rowkiem A
|
||||
std::string sheave;
|
||||
};
|
||||
|
||||
struct tensioner_lever {
|
||||
@@ -88,6 +96,7 @@ struct tensioner_lever {
|
||||
struct tensioner_link {
|
||||
std::string name;
|
||||
double length { 0.0 };
|
||||
double roll { 0.0 }; // stopnie wokół osi łańcucha (w danych "<część>@<stopnie>"), np. 90 - sworzeń obrócony do następnej części
|
||||
};
|
||||
|
||||
// stos ciężarów i otwory dźwigni dla typu sieci (numer typu z karty 0002 = traction_code)
|
||||
@@ -95,6 +104,9 @@ struct tensioner_type {
|
||||
int code { -1 };
|
||||
std::vector<std::pair<std::string, int>> stack; // od dołu: ciężar, liczba
|
||||
std::string messenger_hole, contact_hole, axis_hole;
|
||||
// dźwignie szeregowo (2 liny + 2 przewody na jednym stosie): otwór przewodów pierwszej dźwigni ciągnie łańcuchem "cascade"
|
||||
// drugą dźwignię za jej otwór osi; druga dzieli dalej na drugą linę nośną i przewody. Puste = jedna dźwignia
|
||||
std::string second_messenger_hole, second_contact_hole, second_axis_hole;
|
||||
std::string rod; // pręt, gdy inny niż urządzenia
|
||||
std::string messenger_clamp; // uchwyt krańcowy liny nośnej, gdy inny niż urządzenia
|
||||
};
|
||||
@@ -102,15 +114,88 @@ struct tensioner_type {
|
||||
struct tensioner_device {
|
||||
std::string name; // karta, np. 0461
|
||||
std::string table, pulley, lever, rod, rope;
|
||||
std::string lever2; // druga dźwignia (szeregowo), gdy inna niż pierwsza
|
||||
double rope_diameter { 0.010 };
|
||||
std::string rope_eye; // ucho (kausza) na obu końcach liny, nieskalowane; pusty = lina bez uch
|
||||
double rope_eye_length { 0.0 }; // od zera ucha (styk z liną) do punktu "eye" (zaczep), wzdłuż +Z modelu
|
||||
std::string rope_spacer; // przekładka na sworzniu ucha przy pręcie (6411, oś w +Z modelu); pusta = bez
|
||||
double rope_spacer_length { 0.0 };
|
||||
std::vector<tensioner_link> mount; // od czoła konstrukcji do osi rolki stałej
|
||||
std::vector<tensioner_link> holder; // od osi rolki ruchomej do osi dźwigni
|
||||
std::vector<tensioner_link> hanger; // od rolki stałej w dół do pręta (bez liny)
|
||||
std::vector<tensioner_link> messenger; // od otworu dźwigni do uchwytu krańcowego liny nośnej (bez uchwytu)
|
||||
std::vector<tensioner_link> contact; // od otworu dźwigni do wyrównywacza albo uchwytu krańcowego przewodu
|
||||
// dźwignie szeregowo: od otworu przewodów pierwszej do osi drugiej (z izolatorem) i od otworu liny drugiej do uchwytu drugiej
|
||||
// liny nośnej; przewody ("contact") wtedy z drugiej dźwigni
|
||||
std::vector<tensioner_link> cascade, messenger2;
|
||||
// kotwienie stałe (kind fixed): bez rolek i ciężarów; na konstrukcji dwa przegubowe uchwyty kotwienia (pierwsza część "mount",
|
||||
// 4430) - liny na wysokości liny nośnej, przewodów na wysokości przewodów, każdy w parze uchwytów poz. 1 (karta 43-0453).
|
||||
// Za wyrównywaczem łańcuch każdego drutu osobno (…_each), dwie liny nośne przez messenger_equalizer (sieć 32, 35)
|
||||
bool fixed { false };
|
||||
// rolki szeregowe (karty 0421, 0471, 0480): przy konstrukcji duża rolka (pulley) i za nią mała (small_pulley) o small_spacing
|
||||
// dalej na uchwycie fixed_holder (4440-6), na wózku mała i duża (uchwyt 4440-5 = holder); lina od zaczepu na uchwycie stałym
|
||||
// (dead_end od osi dużej) przez małą ruchomą, małą stałą, dużą ruchomą i dużą stałą w dół. b z tablicy = oś dużej ruchomej.
|
||||
// Puste small_pulley = rolki równoległe (podwójne)
|
||||
std::string small_pulley, fixed_holder;
|
||||
// kotwienie rozdzielone: urządzenie tylko liny albo tylko przewodów (only), bez dźwigni - łańcuch wprost z uchwytu rolki
|
||||
// ruchomej; dwa takie składa urządzenie "kind split" (split <liny> <przewodów>). Prowadnica na ramach 5090 (frame <rama>
|
||||
// <od czoła do osi prowadnic> <prowadnica w Y> <strona stosu: -1 przy konstrukcji, +1 dalej> [owner]): stos pod liną (Y 0),
|
||||
// pierścień obrócony tak, żeby szekla trafiała w prowadnicę; owner stawia ramy i ich uchwyty
|
||||
std::string only;
|
||||
bool split { false };
|
||||
std::string split_messenger, split_contact;
|
||||
std::string frame;
|
||||
double frame_length { 0.0 }, frame_y { 0.0 };
|
||||
int frame_side { -1 };
|
||||
bool frame_owner { false };
|
||||
double messenger_spread { 0.08 }; // rozstaw dwóch lin za messenger_equalizer
|
||||
bool messenger_equalizer_z { false }; // otwory messenger_equalizer w Z modelu (dźwignia 6403), a nie w Y (wyrównywacz 4410)
|
||||
double small_spacing { 0.336 }, dead_end { 0.703 };
|
||||
std::vector<tensioner_link> messenger_each, contact_each;
|
||||
tensioner_link messenger_equalizer;
|
||||
// stare złożenia: izolator rolkowy ESN-2025 zamiast 7150 (Jan 2026-10-24: ESN-2025 - 4420 - [wyrównywacz] - uchwyt);
|
||||
// puste = jak nowe
|
||||
std::vector<tensioner_link> messenger_old, contact_old;
|
||||
tensioner_link messenger_clamp, contact_clamp;
|
||||
tensioner_link contact_clamp_old; // uchwyt krańcowy przewodów w starych złożeniach (5110, stara karta 33-0401); pusty = jak nowe
|
||||
tensioner_link equalizer; // wyrównywacz przewodów jezdnych (tylko przy dwóch przewodach)
|
||||
double equalizer_spread { 0.08 }; // rozstaw przewodów za wyrównywaczem
|
||||
// zabezpieczenie 4600 wyk. 1: dwa ramiona z osi rolek (stałej i ruchomej) zbiegające się na dolnej śrubie, para po obu stronach rolek
|
||||
std::string safety_fixed, safety_moving;
|
||||
double safety_arm { 1.0 }; // rozstaw otworów ramienia
|
||||
double safety_offset { 0.06 }; // odsunięcie każdej pary od środka rolki w bok
|
||||
// zabezpieczenie 4600 wyk. 2 (rolki szeregowe, karta 13-0421 poz. 10): ramiona z osi małych rolek (stałej i ruchomej) w dół,
|
||||
// na końcach drążek; puste = bez niego. safety_series <ramię przy stałej> <ramię przy ruchomej> <drążek> <ramię> <drążek> <w bok>
|
||||
std::string series_arm_fixed, series_arm_moving, series_bar;
|
||||
double series_arm { 0.46268 }, series_bar_length { 1.30 };
|
||||
// tytuł do wyboru w edytorze (karta z odmianą widoczna na liście mimo "-" w nazwie); puste = bez
|
||||
std::string title;
|
||||
// prowadnica ciężarów (5070, karta 33-0455) i pierścień prowadzący na wierzchu stosu (5080). Model prowadnicy: zero w osi
|
||||
// przesuwu pierścienia na dole, w +Z (długość), punkty "mount"/"end" mocowań do wsporników o guide_mount w -X (w stronę
|
||||
// konstrukcji). Pierścień: zero w osi stosu, poziomo, "mount" o ring_arm w -X (w osi przesuwu po prowadnicy); pusty = bez nich
|
||||
std::string guide, ring;
|
||||
double guide_length { 4.50 };
|
||||
double guide_mount { 0.07 };
|
||||
double guide_bottom { 0.80 }; // spód prowadnicy nad główką szyny (karta 23-0018-2: 0,80, prowadnica 4,50 do 5,30)
|
||||
double ring_arm { 0.200 }; // od osi stosu do osi szekli, która chodzi po prowadnicy (karta 23-5080 wyk. 1: 200)
|
||||
double ring_turn { 0.0 }; // stopnie wokół osi stosu: 0 = prowadnica w stronę konstrukcji, 90 = w bok (+Y)
|
||||
double ring_at { 1.00 }; // wysokość pierścienia nad spodem stosu (karta 23-0018-2: 1,00 m); ujemna = na wierzchu stosu
|
||||
// uchwyty do konstrukcji (karta 33-0455): para przód + tył ściśnięta śrubami przez słup, na ścianach wzdłuż drutów (obrócone
|
||||
// o 90 stopni względem wysięgnika; rozstaw śrub obejmuje słup w poprzek). Przód: zero na czole konstrukcji, śruby w +X modelu
|
||||
// (w głąb), hole_1 o hole_out przed czołem i hole_drop pod zerem. Tył: ten sam układ, po drugiej stronie.
|
||||
// Uchwyt przegubowy 4450 (pierwsza część "mount") trzymają dwa: górny wprost za mount_top, dolny odwrócony o 180 stopni za
|
||||
// mount_bottom (pivot_top / pivot_bottom nad / pod zerem 4450)
|
||||
struct bracket_set {
|
||||
std::vector<std::string> poles; // przedrostki nazw słupów, np. 1611-11 (najdłuższy pasujący wygrywa)
|
||||
double hole_out { 0.04 }, hole_drop { 0.04 }, bolt { 0.217 };
|
||||
std::string top_front, top_back, bottom_front, bottom_back;
|
||||
};
|
||||
std::vector<bracket_set> brackets;
|
||||
double pivot_top { 0.0 }, pivot_bottom { 0.0 };
|
||||
// otwór na końcu uchwytu (oś stałej rolki) nad jego zerem: uchwyt schodzi o tyle, żeby rolka została na swojej wysokości
|
||||
// (5040: hole_1 0,03 nad mount_bottom; wpis "pivot <góra> <dół> [rise <m>]")
|
||||
double mount_rise { 0.0 };
|
||||
bracket_set const *brackets_for( std::string const &Pole ) const;
|
||||
std::vector<tensioner_type> types;
|
||||
tensioner_type const *type( int Code ) const;
|
||||
};
|
||||
@@ -126,6 +211,8 @@ public:
|
||||
tensioner_device const *device( std::string const &Name ) const;
|
||||
std::vector<tensioner_device> const &devices() const { return m_devices; }
|
||||
std::map<std::string, double> const &part_lengths() const { return m_lengths; } // długości części liniowych (pręt)
|
||||
// numer typu sieci dla urządzeń: sieć bez własnych danych bierze dane innej (wpis "network <symbol> as <kod>"), inaczej jej kod
|
||||
int code_for( std::string const &Symbol, int Code ) const;
|
||||
|
||||
private:
|
||||
std::vector<tensioner_table> m_tables;
|
||||
@@ -134,19 +221,45 @@ private:
|
||||
std::vector<tensioner_lever> m_levers;
|
||||
std::vector<tensioner_device> m_devices;
|
||||
std::map<std::string, double> m_lengths;
|
||||
std::map<std::string, int> m_networks;
|
||||
};
|
||||
|
||||
struct tensioner_input {
|
||||
int type { 3 }; // numer typu sieci (traction_code)
|
||||
int contacts { 2 }; // liczba przewodów jezdnych
|
||||
int messengers { 1 }; // liczba lin nośnych (kotwienie stałe sieci 32, 35: dwie)
|
||||
double messenger_stack { 0.04 }; // odstęp pionowy dwóch lin nośnych w przęśle (druga celuje o tyle niżej)
|
||||
double temperature { 10.0 }; // °C
|
||||
double distance { 700.0 }; // m, od kotwienia stałego albo środkowego
|
||||
double elongation { 0.0 }; // m, trwałe wydłużenie sieci od ostatniej regulacji (rolka bliżej konstrukcji)
|
||||
int missing { 0 }; // brakujące ciężary (z góry stosu)
|
||||
// sieć do skrócenia przy naciągu mniejszym niż od pełnego stosu (brakujące ciężary): sztywności EA wszystkich lin
|
||||
// nośnych i wszystkich przewodów jezdnych (daN), ciężar sieci na metr wiszący na linie (daN/m) i średnia rozpiętość
|
||||
// przęseł (m). Lina i przewody skracają się sprężyście, a lina dodatkowo zwisa bardziej, więc urządzenie ściąga je ku
|
||||
// przęsłom: rolka dalej od konstrukcji, ciężary wyżej. Sztywność 0 = bez tego (tablica jak przy pełnym stosie)
|
||||
double messenger_stiffness { 0.0 }, contact_stiffness { 0.0 };
|
||||
double load { 0.0 };
|
||||
double span { 0.0 };
|
||||
std::string color; // kolor ciężarów (tensioner_color); pusty = szary
|
||||
std::string top_color; // kolor najwyższego ciężaru; pusty = jak reszta
|
||||
bool old_fittings { false }; // uchwyty krańcowe przewodów 5110 (druty zaśniedziałe)
|
||||
bool old_messenger { false }, old_contact { false }; // izolatory rolkowe (łańcuchy messenger_old / contact_old) na linie / przewodach
|
||||
// punkty, w które celują łańcuchy do liny nośnej i do przewodów jezdnych (ostatnie podwieszenie, układ urządzenia);
|
||||
// bez nich łańcuchy poziomo wzdłuż +X
|
||||
bool aimed { false };
|
||||
double messenger_target[ 3 ] { 0.0, 0.0, 0.0 };
|
||||
double contact_target[ 3 ] { 0.0, 0.0, 0.0 }; // stare złożenie (druty zaśniedziałe): uchwyty krańcowe przewodów 5110 zamiast 5120
|
||||
double height { 0.0 }; // oś rolek nad główką szyny; 0 = z tablicy. Wyżej/niżej: ciężary o tyle samo (lina ta sama)
|
||||
double rope_height { 0.0 }; // kotwienie stałe: uchwyt liny nośnej nad główką; 0 = jak drut przy ostatnim podwieszeniu
|
||||
double ground { -0.50 }; // najniższe położenie spodu ciężarów względem główki szyny (grunt, fundament); ZAŁOŻENIE
|
||||
double gravity { 0.981 }; // daN/kg
|
||||
// konstrukcja: nazwa słupa (dobór uchwytów) i jej grubość od czoła do tyłu (wzdłuż drutów; słup 161x - szerokość wzdłuż toru,
|
||||
// przez nią idą śruby uchwytów) na wysokości nad główką; puste = bez uchwytów
|
||||
std::string pole;
|
||||
std::function<double( double )> depth;
|
||||
// kąt osi konstrukcji (od czoła w stronę kotwionego przęsła) w układzie urządzenia, radiany wokół +Z: urządzenie od przegubu
|
||||
// 4450 ciągnie do drutów, a uchwyty, prowadnica, pierścień i stos zostają przy konstrukcji (0 = konstrukcja w linii drutów)
|
||||
double structure_angle { 0.0 };
|
||||
};
|
||||
|
||||
struct tensioner_placement {
|
||||
@@ -162,19 +275,46 @@ struct tensioner_result {
|
||||
std::vector<std::vector<double>> rope; // punkty liny (x, y, z) po kolei, od zaczepu przy rolce stałej do pręta
|
||||
double b { 0.0 }, s { 0.0 }; // położenie rolki ruchomej i spodu ciężarów
|
||||
double stack_height { 0.0 };
|
||||
double height { 0.0 }; // oś rolek nad główką szyny
|
||||
double lever_tilt { 0.0 }; // radiany: odchylenie uchwytu dźwigni od poziomu w dół (dźwignia od pionu w stronę konstrukcji u góry)
|
||||
// obrót krążków (radiany wokół +Y urządzenia) od położenia przy +10 °C: lina przewinięta przez rowek / promień
|
||||
double turn_fixed_a { 0.0 }, turn_fixed_b { 0.0 }, turn_moving_a { 0.0 }, turn_moving_b { 0.0 };
|
||||
int weights { 0 }; // zawieszone ciężary
|
||||
double tension { 0.0 }; // daN, całkowity naciąg sieci od ciężarów (zero, gdy ciężary stoją na gruncie)
|
||||
double nominal_tension { 0.0 }; // daN, naciąg od pełnego stosu (jak w tablicy)
|
||||
double shortening { 0.0 }; // m, o ile rolka odjechała od tablicy przez mniejszy naciąg (sprężystość i zwis)
|
||||
double messenger_tension { 0.0 }, contact_tension { 0.0 };
|
||||
double messenger_end[ 3 ] { 0.0, 0.0, 0.0 }; // gdzie kończy się lina nośna (uchwyt krańcowy)
|
||||
std::vector<std::vector<double>> rope2; // kotwienie rozdzielone: lina urządzenia przewodów (rope - urządzenia liny)
|
||||
// dźwignie szeregowo: druga lina nośna (z drugiej dźwigni) i naciągi obu lin osobno (messenger_tension to ich suma)
|
||||
bool cascade { false };
|
||||
bool fixed { false }; // kotwienie stałe (bez ciężarów; b, s, naciąg zero)
|
||||
double rope_height { 0.0 }; // kotwienie stałe: wysokość uchwytu liny nośnej (height - przewodów)
|
||||
double messenger2_end[ 3 ] { 0.0, 0.0, 0.0 }; // druga lina nośna: z drugiej dźwigni albo za wyrównywaczem kotwienia stałego
|
||||
double messenger_tensions[ 2 ] { 0.0, 0.0 };
|
||||
std::vector<std::vector<double>> contact_ends; // gdzie kończą się przewody jezdne
|
||||
bool grounded { false }; // ciężary oparte o grunt: sieć bez naciągu od urządzenia
|
||||
// mocowania prowadnicy do wsporników na konstrukcji (dolne i górne, układ urządzenia); has_guide = false bez prowadnicy
|
||||
bool has_guide { false };
|
||||
double guide_mount[ 3 ] { 0.0, 0.0, 0.0 }, guide_end[ 3 ] { 0.0, 0.0, 0.0 };
|
||||
std::vector<std::string> warnings;
|
||||
};
|
||||
|
||||
// składa urządzenie. false, gdy brakuje danych (urządzenia, typu, tablicy, rolki, dźwigni, otworów)
|
||||
bool solve_tensioner( tensioner_catalog const &Catalog, tensioner_device const &Device, tensioner_input const &Input, tensioner_result &Result );
|
||||
|
||||
// lina jako odcinki linki rozciąganej (część Cord o długości spoczynkowej Length, skala w poprzek Girth)
|
||||
void tensioner_rope_parts( tensioner_result &Result, std::string const &Cord, double Length, double Girth );
|
||||
// wierzchołek bryły proceduralnej w układzie urządzenia; kolejne trójki to trójkąty, obchodzone przeciwnie do ruchu
|
||||
// wskazówek zegara patrząc z zewnątrz (w prawoskrętnym układzie urządzenia)
|
||||
struct tensioner_vertex {
|
||||
double position[ 3 ];
|
||||
double normal[ 3 ];
|
||||
};
|
||||
|
||||
// lina jako jedna bryła proceduralna: rura o promieniu Radius i Sides ścianach po całej ścieżce Result.rope (łuki na
|
||||
// rolkach co 5°), bez łączeń. Eye (gdy niepusty): ucho o długości EyeLength (zero w styku z liną, punkt "eye" w +Z w
|
||||
// zaczepie) na obu końcach, dopisywane do Result.parts; rura skrócona o ucha
|
||||
// Spacer: przekładka ślizgowa (6411) na sworzniu ucha przy pręcie ciężarów (koniec liny), oś wzdłuż sworznia; pusta = bez
|
||||
void tensioner_rope_solid( tensioner_result &Result, double Radius, int Sides, std::string const &Eye, double EyeLength, std::vector<tensioner_vertex> &Triangles,
|
||||
std::string const &Spacer = {}, double SpacerLength = 0.0 );
|
||||
|
||||
} // namespace catenary
|
||||
|
||||
Reference in New Issue
Block a user