diff --git a/src/input_output/FGScript.h b/src/input_output/FGScript.h index e051f26de7..7ec84a5481 100644 --- a/src/input_output/FGScript.h +++ b/src/input_output/FGScript.h @@ -194,6 +194,12 @@ class FGScript : public FGJSBBase void ResetEvents(void); + std::string GetScriptName() { return ScriptName; } + + double GetStartTime() { return StartTime; } + + double GetEndTime() { return EndTime; } + private: enum eAction { FG_RAMP = 1, diff --git a/src/math/FGFunction.cpp b/src/math/FGFunction.cpp index acf3884204..19616d2ba3 100644 --- a/src/math/FGFunction.cpp +++ b/src/math/FGFunction.cpp @@ -309,6 +309,19 @@ void FGFunction::Load(Element* el, FGPropertyValue* var, FGFDMExec* fdmex, const string& Prefix) { Name = el->GetAttributeValue("name"); + JSBSim::Element* parent = el->GetParent(); + std::string parent_name = parent->GetAttributeValue("name"); + Parameter_Name = parent->GetName(); + if (parent_name.size() > 0) { + Parameter_Name += "_" + parent_name; + } + Parameter_Name += "_" + el->GetName(); + if (Name.size() > 0) { + Parameter_Name += "_" + Name; + } + + Parameter_Description = el->GetAttributeValue("description"); + Parameter_LineNumber = el->GetLineNumber(); Element* element = el->GetElement(); auto sum = [](const decltype(Parameters)& Parameters)->double { @@ -322,6 +335,7 @@ void FGFunction::Load(Element* el, FGPropertyValue* var, FGFDMExec* fdmex, while (element) { string operation = element->GetName(); + Function_Operation = operation; // data types if (operation == "property" || operation == "p") { diff --git a/src/math/FGFunction.h b/src/math/FGFunction.h index d212dbe63e..4a3fd211bc 100644 --- a/src/math/FGFunction.h +++ b/src/math/FGFunction.h @@ -814,6 +814,10 @@ class FGFunction : public FGParameter, public FGJSBBase enum class OddEven {Either, Odd, Even}; + const std::vector GetParameters(void) const { return Parameters; } + const FGPropertyNode_ptr GetFGPropertyNode(void) const { return pNode; } + const std::string GetFunctionOperation(void) const { return Function_Operation; } + protected: bool cached; double cachedValue; @@ -829,6 +833,9 @@ class FGFunction : public FGParameter, public FGJSBBase void CheckOddOrEvenArguments(Element* el, OddEven odd_even); std::string CreateOutputNode(Element* el, const std::string& Prefix); +protected: + std::string Function_Operation = ""; + private: std::string Name; FGPropertyNode_ptr pCopyTo; // Property node for CopyTo property string diff --git a/src/math/FGParameter.h b/src/math/FGParameter.h index e8b9adc7fa..10f2582773 100644 --- a/src/math/FGParameter.h +++ b/src/math/FGParameter.h @@ -63,10 +63,19 @@ class JSBSIM_API FGParameter : public SGReferenced virtual ~FGParameter(void) {}; virtual double GetValue(void) const = 0; virtual std::string GetName(void) const = 0; + + virtual std::string GetParameterName(void) const { return Parameter_Name; } + virtual std::string GetParameterDescription(void) const { return Parameter_Description; } + virtual int GetParameterLineNumber(void) const { return Parameter_LineNumber; } virtual bool IsConstant(void) const { return false; } // SGPropertyNode impersonation. double getDoubleValue(void) const { return GetValue(); } + +protected: + std::string Parameter_Name = ""; + std::string Parameter_Description = ""; + int Parameter_LineNumber = 0; }; typedef SGSharedPtr FGParameter_ptr; diff --git a/src/math/FGPropertyValue.cpp b/src/math/FGPropertyValue.cpp index cef989f510..4713aadcb7 100644 --- a/src/math/FGPropertyValue.cpp +++ b/src/math/FGPropertyValue.cpp @@ -51,6 +51,7 @@ FGPropertyValue::FGPropertyValue(const std::string& propName, if (PropertyManager->HasNode(PropertyName)) { PropertyNode = PropertyManager->GetNode(PropertyName); + Parameter_Name = PropertyName; assert(PropertyNode); XML_def = nullptr; // Now that the property is bound, we no longer need that. diff --git a/src/math/FGRealValue.h b/src/math/FGRealValue.h index 0d2acd07b9..2010a1d6fc 100644 --- a/src/math/FGRealValue.h +++ b/src/math/FGRealValue.h @@ -58,7 +58,9 @@ class JSBSIM_API FGRealValue : public FGParameter { public: - explicit FGRealValue(double val) : Value(val) {} + explicit FGRealValue(double val) : Value(val) { + Parameter_Name = "constant value :" + std::to_string(val); + } double GetValue(void) const override { return Value; }; std::string GetName(void) const override; diff --git a/src/math/FGTable.cpp b/src/math/FGTable.cpp index 62f2ab59b5..55279e5fea 100644 --- a/src/math/FGTable.cpp +++ b/src/math/FGTable.cpp @@ -119,6 +119,20 @@ FGTable::FGTable(std::shared_ptr pm, Element* el, // Is this an internal lookup table? Name = el->GetAttributeValue("name"); // Allow this table to be named with a property + JSBSim::Element* parent = el->GetParent(); + std::string parent_name = parent->GetAttributeValue("name"); + Parameter_Name = parent->GetName(); + if (parent_name.size() > 0) { + Parameter_Name += "_" + parent_name; + } + Parameter_Name += "_" + el->GetName(); + if (Name.size() > 0) { + Parameter_Name += "_" + Name; + } + + Parameter_Description = el->GetAttributeValue("description"); + Parameter_LineNumber = el->GetLineNumber(); + Function_Operation = "table"; string call_type = el->GetAttributeValue("type"); if (call_type == "internal") { internal = true; @@ -159,6 +173,7 @@ FGTable::FGTable(std::shared_ptr pm, Element* el, FGPropertyValue_ptr node = new FGPropertyValue(property_string, PropertyManager, axisElement); + Parameters.push_back(node); string lookup_axis = axisElement->GetAttributeValue("lookup"); if (lookup_axis == string("row")) { lookupProperty[eRow] = node; diff --git a/src/math/FGTable.h b/src/math/FGTable.h index 1439c69cb7..1c7766830e 100644 --- a/src/math/FGTable.h +++ b/src/math/FGTable.h @@ -38,7 +38,7 @@ SENTRY INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#include "FGParameter.h" +#include "FGFunction.h" #include "math/FGPropertyValue.h" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -230,7 +230,7 @@ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class JSBSIM_API FGTable : public FGParameter, public FGJSBBase +class JSBSIM_API FGTable : public FGFunction { public: /// Destructor @@ -308,13 +308,24 @@ class JSBSIM_API FGTable : public FGParameter, public FGJSBBase { lookupProperty[eColumn] = new FGPropertyValue(node); } unsigned int GetNumRows() const {return nRows;} + const std::vector GetLookupProperty(void) const { + auto v = std::vector(); + for (unsigned int i = 0; i < 3; i++) { + v.push_back(lookupProperty[i]); + } + return v; + } void Print(void); std::string GetName(void) const {return Name;} + enum type {tt1D, tt2D,tt3D}; + + type GetType(void) const { return Type; } + private: - enum type {tt1D, tt2D, tt3D} Type; + type Type; enum axis {eRow=0, eColumn, eTable}; bool internal = false; std::shared_ptr PropertyManager; // Property root used to do late binding. diff --git a/src/models/FGFCS.h b/src/models/FGFCS.h index dcaf6f5a43..6290d337bc 100644 --- a/src/models/FGFCS.h +++ b/src/models/FGFCS.h @@ -369,6 +369,10 @@ class JSBSIM_API FGFCS : public FGModel @return a string containing the descriptive names for all components */ std::string GetComponentStrings(const std::string& delimiter) const; + typedef std::vector Channels; + + const Channels GetSystemChannels(void) const { return SystemChannels; } + /** Retrieves all component outputs for inclusion in output stream @param delimiter either a tab or comma string depending on output type @return a string containing the numeric values for the current set of @@ -589,7 +593,6 @@ class JSBSIM_API FGFCS : public FGModel int ChannelRate; FGFDMExec* fdmex; - typedef std::vector Channels; Channels SystemChannels; void bind(void); void bindThrottle(unsigned int); diff --git a/src/models/FGFCSChannel.h b/src/models/FGFCSChannel.h index 766aa1f28c..801e507671 100644 --- a/src/models/FGFCSChannel.h +++ b/src/models/FGFCSChannel.h @@ -87,7 +87,7 @@ class FGFCSChannel { FCSComponents.clear(); } /// Retrieves the name of the channel - std::string GetName() {return Name;} + std::string GetName() const {return Name;} /// Adds a component to a channel void Add(FGFCSComponent* comp) { @@ -138,6 +138,8 @@ class FGFCSChannel { /// Get the channel rate int GetRate(void) const { return ExecRate; } + const FCSCompVec GetFCSComponents(void) const { return FCSComponents; } + private: FGFCS* fcs; FCSCompVec FCSComponents; diff --git a/src/models/FGLGear.cpp b/src/models/FGLGear.cpp index d9aae6a6d3..0c0d7793e7 100644 --- a/src/models/FGLGear.cpp +++ b/src/models/FGLGear.cpp @@ -565,7 +565,7 @@ void FGLGear::CrashDetect(void) SinkRate > 1.4666*30 ) && !fdmex->IntegrationSuspended()) { if (debug_lvl > 0) { - cout << "*CRASH DETECTED* " << fdmex->GetSimTime() << " seconds: " << name; + cout << "*CRASH DETECTED* " << fdmex->GetSimTime() << " seconds: " << name << endl; } // fdmex->SuspendIntegration(); diff --git a/src/models/flight_control/FGFCSComponent.h b/src/models/flight_control/FGFCSComponent.h index 58f6003a81..7bac852400 100644 --- a/src/models/flight_control/FGFCSComponent.h +++ b/src/models/flight_control/FGFCSComponent.h @@ -97,6 +97,10 @@ class FGFCSComponent : public FGJSBBase virtual double GetOutputPct(void) const { return 0; } virtual void ResetPastStates(void); + const std::vector & GetInitNodes(void) const { return InitNodes;} + const std::vector & GetInputNodes(void) const { return InputNodes; } + const std::vector & GetOutputNodes(void) const { return OutputNodes; } + protected: FGFCS* fcs; std::vector OutputNodes; diff --git a/utils/JSBSim_Static/JSBSim_Static.vcxproj b/utils/JSBSim_Static/JSBSim_Static.vcxproj new file mode 100644 index 0000000000..be7e3ea317 --- /dev/null +++ b/utils/JSBSim_Static/JSBSim_Static.vcxproj @@ -0,0 +1,382 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {67C6FDD4-27D7-4061-98BE-A88C795357ED} + JSBSim + Win32Proj + 10.0 + + + + StaticLibrary + PGOptimize + v143 + + + StaticLibrary + v143 + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(SolutionDir)$(Configuration)\$(PlatformTarget)\$(ProjectName)\ + true + $(SolutionDir)$(Configuration)\ + $(SolutionDir)$(Configuration)\$(PlatformTarget)\$(ProjectName)\ + false + false + false + + + + Disabled + $(ProjectDir)..\..\src;$(ProjectDir)..\..\src\simgear\xml;%(AdditionalIncludeDirectories) + JSBSIM_STATIC_LINK;JSBSIM_VERSION="1.2.1.dev1";WIN32;NOMINMAX;_DEBUG;_CONSOLE;_USE_MATH_DEFINES;XML_STATIC;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebugDLL + NotSet + Precise + true + + + false + true + Level3 + ProgramDatabase + 4996;4267;%(DisableSpecificWarnings) + false + + + LinkVerbose + + + %(AdditionalLibraryDirectories) + true + Console + false + + + ws2_32.lib;%(AdditionalDependencies) + + + + + MaxSpeed + true + Speed + true + $(ProjectDir)..\..\src;$(ProjectDir)..\..\src\simgear\xml;%(AdditionalIncludeDirectories) + JSBSIM_STATIC_LINK;JSBSIM_VERSION="1.2.1.dev1";WIN32;NOMINMAX;NDEBUG;_CONSOLE;_USE_MATH_DEFINES;XML_STATIC;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + StreamingSIMDExtensions2 + Fast + + + false + Level3 + ProgramDatabase + true + false + stdcpp14 + Default + + + LinkVerbose + %(AdditionalLibraryDirectories) + false + Console + true + true + UseLinkTimeCodeGeneration + false + + + MachineX64 + ws2_32.lib;%(AdditionalDependencies) + + + false + true + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + Document + true + + + Document + true + + + Document + true + + + + + + \ No newline at end of file diff --git a/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.cpp b/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.cpp new file mode 100644 index 0000000000..755353c795 --- /dev/null +++ b/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.cpp @@ -0,0 +1,312 @@ +#include "aerodynamics_2_graphviz.h" + +std::set jsbsim_parameters_without_axis; +gvpp::SubGraph<>* jsbsim_subgraphs[7]; + + +const string version = "0.1" __DATE__ " " __TIME__; + +std::string aerodynamics_2_graphviz::GetVersion() +{ + return version; +} + +void aerodynamics_2_graphviz::graph_jsbsim_fdm_aerodynamics(std::shared_ptr fdm + , const std::string output_filename + , bool show_table_png +) +{ + auto model_name = fdm->GetModelName(); + if (model_name.size() == 0) { + cerr << "Model NOT Loaded, exit." << endl; + return; + } + + auto aero_dynamics = fdm->GetAerodynamics(); + auto aero_functions = aero_dynamics->GetAeroFunctions(); + + gvpp::Graph<> all_axis_graph(true, model_name); + all_axis_graph.set(gvpp::AttrType::GRAPH, "nodesep", "0.1"); + all_axis_graph.set(gvpp::AttrType::GRAPH, "rankdir", "LR"); + if (imagepath.size() > 0) { + all_axis_graph.set(gvpp::AttrType::GRAPH, "imagepath", imagepath); + } + + for (unsigned int axis_index = 0; axis_index < 6; axis_index++) { + gvpp::Graph<> axis_graph(true, model_name); + axis_graph.set(gvpp::AttrType::GRAPH, "nodesep", "0.1"); + axis_graph.set(gvpp::AttrType::GRAPH, "rankdir", "LR"); + if (imagepath.size() > 0) { + axis_graph.set(gvpp::AttrType::GRAPH, "imagepath", imagepath); + } + + auto axis_functions = &aero_functions[axis_index]; + auto subgraph_name = std::to_string(axis_index); + auto& all_axis_subgraph = all_axis_graph.addSubGraph(subgraph_name, true, subgraph_name); + auto& axis_subgraph = axis_graph.addSubGraph(subgraph_name, true, subgraph_name); + jsbsim_subgraphs[axis_index] = &all_axis_subgraph; + for (auto function : *axis_functions) { + add_function_edges(axis_index, &all_axis_subgraph, function,show_table_png); + + add_function_edges(axis_index, &axis_subgraph, function,show_table_png); + + } + + std::string axis_file_name = ""; + if (output_filename.size() > 0) { + axis_file_name = output_filename + "_" + std::to_string(axis_index) + ".dot"; + } + else { + axis_file_name = model_name + "_" + std::to_string(axis_index) + ".dot"; + } + write_dot_file(axis_graph, axis_file_name); + //gvpp::renderToFile(axis_graph, "dot","png", axis_file_name); + } + + add_common_nodes_and_edges(&all_axis_graph); + + std::string all_axis_file_name = ""; + if (output_filename.size() > 0) { + all_axis_file_name = output_filename + ".dot"; + } + else { + all_axis_file_name = model_name + ".dot"; + } + write_dot_file(all_axis_graph, all_axis_file_name); + //gvpp::renderToFile(all_axis_graph, "dot","png", all_axis_file_name); + +} + +void aerodynamics_2_graphviz::add_function_edges(int axis_index + , gvpp::SubGraph<>* graph + , const JSBSim::FGFunction* function + , bool show_table_png +) +{ + if (function == NULL) { + return; + } + + auto function_desc = function->GetParameterDescription(); + auto function_name = function->GetParameterName(); + auto function_operation = function->GetFunctionOperation(); + + auto function_node_name = get_node_name_with_axis(axis_index, function_name); + if (!graph->hasNode(function_node_name)) { + auto& add_function_node = graph->addNode(function_node_name, function_desc); + + if (function_operation == "property") { + add_function_node.set("shape", "point"); + add_function_node.set("color", "blue"); + } + + if (function_operation == "product") { + add_function_node.set("shape", "box"); + add_function_node.set("color", "gold"); + } + } + + auto& function_node = graph->getNode(function_node_name); + + auto parameters = function->GetParameters(); + auto parameters_count = parameters.size(); + if (parameters_count == 1) { + + } + + unsigned int parameter_index = 0; + for (auto parameter : parameters) { + parameter_index++; + auto parameter_name = parameter->GetParameterName(); + auto parameter_desc = parameter->GetParameterDescription(); + auto parameter_node_name = get_node_name_with_axis(axis_index, parameter_name); + + if (!graph->hasNode(parameter_node_name)) { + auto& add_parameter_node = graph->addNode(parameter_node_name, parameter_desc); + + config_parameter_node_by_name(&add_parameter_node, parameter_name); + + if (parameter_name._Starts_with("product_table_")) { + auto parameter_2_table = dynamic_cast(parameter.ptr()); + if (parameter_2_table != NULL) { + auto table_type = parameter_2_table->GetType(); + switch (table_type) { + case JSBSim::FGTable::tt1D: + add_parameter_node.set("style", "filled"); + add_parameter_node.set("shape", "polygon"); + add_parameter_node.set("sides", "6"); + add_parameter_node.set("fillcolor", "red"); + break; + case JSBSim::FGTable::tt2D: + add_parameter_node.set("style", "filled"); + add_parameter_node.set("shape", "doubleoctagon"); + add_parameter_node.set("fillcolor", "yellow"); + break; + case JSBSim::FGTable::tt3D: + add_parameter_node.set("style", "filled"); + add_parameter_node.set("shape", "tripleoctagon"); + add_parameter_node.set("fillcolor", "green"); + break; + } + + if (show_table_png) { + auto image_name = "\"" +parameter_2_table->GetName() + ".png\""; + if (image_name.size() > 0) { + add_parameter_node.set("image",image_name); + } + } + } + } + + auto parameter_2_functionvalue = dynamic_cast(parameter.ptr()); + if (parameter_2_functionvalue != NULL) { + add_parameter_node.set("shape", "point"); + add_parameter_node.set("color", "blue"); + } + } + + auto& parameter_node = graph->getNode(parameter_node_name); + auto edge_label = std::to_string(parameter_index) + ":" + parameter_name; + auto& add_edge = graph->addEdge(function_node, parameter_node, edge_label); + + auto parameter_2_function = dynamic_cast(parameter.ptr()); + if (parameter_2_function != NULL) { + add_function_edges(axis_index, graph, parameter_2_function, show_table_png); + } + } +} + +std::string aerodynamics_2_graphviz::get_node_name(const std::string name) +{ + std::string node_name = "\"" + name + "\""; + return node_name; +} + +std::string aerodynamics_2_graphviz::get_node_name_with_axis(int axis_index, const std::string name) +{ + std::string node_name = "\"" + name + "_axis_" + std::to_string(axis_index) + "\""; + + if (auto search = jsbsim_parameters_without_axis.find(name); search != jsbsim_parameters_without_axis.end()) { + } + else { + auto is_common_node = test_if_name_is_common_node(name); + if (is_common_node) { + jsbsim_parameters_without_axis.insert(name); + } + } + + return node_name; +} + +bool aerodynamics_2_graphviz::test_if_name_is_common_node(const std::string name) +{ + if (name._Starts_with("function")) { + return false; + } + + if (name._Starts_with("product_table")) { + return false; + } + + if (name._Starts_with("constant value")) { + return false; + } + + if (name._Starts_with("axis_")) { + return false; + } + + return true; +} + +void aerodynamics_2_graphviz::add_common_nodes_and_edges(gvpp::Graph<>* graph) +{ + auto& common_subgraph = graph->addSubGraph("common", true, "common"); + jsbsim_subgraphs[6] = &common_subgraph; + + for (auto& name : jsbsim_parameters_without_axis) { + auto node_name = get_node_name(name); + auto& add_node = common_subgraph.addNode(node_name); + config_parameter_node_by_name(&add_node, name); + + for (unsigned int axis_index = 0; axis_index < 6; axis_index++) { + auto subgraph_name = std::to_string(axis_index); + auto subgraph = jsbsim_subgraphs[axis_index]; + auto name_with_axis = get_node_name_with_axis(axis_index, name); + if (subgraph->hasNode(name_with_axis)) { + auto& axis_node = subgraph->getNode(name_with_axis); + auto& add_edge = graph->addEdge(axis_node, add_node); + add_edge.set("splines", "curved"); + } + } + } +} + +void aerodynamics_2_graphviz::config_parameter_node_by_name(gvpp::Node<>* node, const std::string name) +{ + if (name._Starts_with("fcs")) { + node->set("style", "filled"); + node->set("fillcolor", "blue"); + node->set("shape", "polygon"); + node->set("sides", "5"); + node->set("skew", "-0.5"); + node->set("distortion", "0"); + node->set("height", "2.0"); + } + + if (name._Starts_with("metrics")) { + node->set("style", "filled"); + node->set("fillcolor", "yellow"); + node->set("shape", "polygon"); + node->set("sides", "6"); + node->set("skew", "-0.5"); + node->set("distortion", "0"); + node->set("height", "2.0"); + } + + if (name._Starts_with("aero")) { + node->set("style", "filled"); + node->set("fillcolor", "green"); + node->set("shape", "polygon"); + node->set("sides", "7"); + node->set("skew", "-0.5"); + node->set("distortion", "0"); + node->set("height", "2.0"); + } + + if (name._Starts_with("constant value")) { + node->set("style", "filled"); + node->set("fillcolor", "red"); + node->set("shape", "egg"); + } + + if (name._Starts_with("velocities")) { + node->set("style", "filled"); + node->set("fillcolor", "olivedrab"); + node->set("shape", "tab"); + } +} + +//#TODO: gen subgraphs for each axis +void aerodynamics_2_graphviz::graph_jsbsim_fdm_subgraphs() +{ +} + +void aerodynamics_2_graphviz::set_imagepath(const std::string imagepath) +{ + this->imagepath = "\"" + imagepath + "\""; +} + +void aerodynamics_2_graphviz::write_dot_file(gvpp::Graph<>& graph, const std::string file_name) +{ + std::fstream file; + file.open(file_name, std::ios::out); // 以输出模式打开文件 + + if (!file) { + std::cerr << "Unable to open file!" << std::endl; + } + + file << graph; + file.flush(); + file.close(); // 关闭文件 +} diff --git a/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.h b/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.h new file mode 100644 index 0000000000..3be58b0e25 --- /dev/null +++ b/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gvpp.hpp" + +class aerodynamics_2_graphviz +{ +public : + static std::string GetVersion(); + + void graph_jsbsim_fdm_aerodynamics( + std::shared_ptr fdm + , const std::string output_filename="" + , bool show_table_png = false + ); + void add_function_edges(int axis_index + , gvpp::SubGraph<>* graph + , const JSBSim::FGFunction* function + , bool show_table_png = false + ); + std::string get_node_name(const std::string name); + std::string get_node_name_with_axis(int axis_index, const std::string name); + bool test_if_name_is_common_node(const std::string name); + void add_common_nodes_and_edges(gvpp::Graph<>* graph); + void config_parameter_node_by_name(gvpp::Node<>* node, const std::string name); + void graph_jsbsim_fdm_subgraphs(); + void set_imagepath(const std::string imagepath); + void write_dot_file(gvpp::Graph<>& graph, const std::string file_name); +private: + std::string imagepath; +}; + diff --git a/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.sln b/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.sln new file mode 100644 index 0000000000..f9b39f85c9 --- /dev/null +++ b/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.34928.147 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "aerodynamics_2_graphviz", "aerodynamics_2_graphviz.vcxproj", "{E7F7BC85-3CDD-4BC9-864F-364C38EEFAB9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSBSim_Static", "..\JSBSim_Static\JSBSim_Static.vcxproj", "{67C6FDD4-27D7-4061-98BE-A88C795357ED}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E7F7BC85-3CDD-4BC9-864F-364C38EEFAB9}.Debug|x64.ActiveCfg = Debug|x64 + {E7F7BC85-3CDD-4BC9-864F-364C38EEFAB9}.Debug|x64.Build.0 = Debug|x64 + {E7F7BC85-3CDD-4BC9-864F-364C38EEFAB9}.Debug|x86.ActiveCfg = Debug|Win32 + {E7F7BC85-3CDD-4BC9-864F-364C38EEFAB9}.Debug|x86.Build.0 = Debug|Win32 + {E7F7BC85-3CDD-4BC9-864F-364C38EEFAB9}.Release|x64.ActiveCfg = Release|x64 + {E7F7BC85-3CDD-4BC9-864F-364C38EEFAB9}.Release|x64.Build.0 = Release|x64 + {E7F7BC85-3CDD-4BC9-864F-364C38EEFAB9}.Release|x86.ActiveCfg = Release|Win32 + {E7F7BC85-3CDD-4BC9-864F-364C38EEFAB9}.Release|x86.Build.0 = Release|Win32 + {67C6FDD4-27D7-4061-98BE-A88C795357ED}.Debug|x64.ActiveCfg = Debug|x64 + {67C6FDD4-27D7-4061-98BE-A88C795357ED}.Debug|x64.Build.0 = Debug|x64 + {67C6FDD4-27D7-4061-98BE-A88C795357ED}.Debug|x86.ActiveCfg = Debug|x64 + {67C6FDD4-27D7-4061-98BE-A88C795357ED}.Debug|x86.Build.0 = Debug|x64 + {67C6FDD4-27D7-4061-98BE-A88C795357ED}.Release|x64.ActiveCfg = Release|x64 + {67C6FDD4-27D7-4061-98BE-A88C795357ED}.Release|x64.Build.0 = Release|x64 + {67C6FDD4-27D7-4061-98BE-A88C795357ED}.Release|x86.ActiveCfg = Release|x64 + {67C6FDD4-27D7-4061-98BE-A88C795357ED}.Release|x86.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FD81A853-AD3B-421C-84DE-347BE3ECBB89} + EndGlobalSection +EndGlobal diff --git a/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.vcxproj b/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.vcxproj new file mode 100644 index 0000000000..75571ad591 --- /dev/null +++ b/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.vcxproj @@ -0,0 +1,153 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {e7f7bc85-3cdd-4bc9-864f-364c38eefab9} + aerodynamics2graphviz + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_CRT_SECURE_NO_WARNINGS;JSBSIM_STATIC_LINK;XML_STATIC;%(PreprocessorDefinitions) + true + stdcpp17 + ..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)$(Configuration)\JSBSim_Static.lib;legacy_stdio_definitions.lib;Ws2_32.lib;%(AdditionalDependencies) + LinkVerbose + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_CRT_SECURE_NO_WARNINGS;JSBSIM_STATIC_LINK;XML_STATIC;%(PreprocessorDefinitions) + true + ../../src;%(AdditionalIncludeDirectories) + stdcpp17 + + + Console + true + true + true + $(SolutionDir)$(Configuration)\JSBSim_Static.lib;legacy_stdio_definitions.lib;Ws2_32.lib;%(AdditionalDependencies) + + + + + + + + + + {67c6fdd4-27d7-4061-98be-a88c795357ed} + + + + + + + + + + \ No newline at end of file diff --git a/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.vcxproj.filters b/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.vcxproj.filters new file mode 100644 index 0000000000..15e32286d6 --- /dev/null +++ b/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + 源文件 + + + 头文件 + + + + + 头文件 + + + 头文件 + + + \ No newline at end of file diff --git a/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.vcxproj.user b/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.vcxproj.user new file mode 100644 index 0000000000..49aa53573b --- /dev/null +++ b/utils/aerodynamics_2_graphviz/aerodynamics_2_graphviz.vcxproj.user @@ -0,0 +1,8 @@ + + + + --script=scripts/f16_test.xml --outputfile=test --show_table_png=on --imagepath=F:\SXHX\jsbsim\f16 + WindowsLocalDebugger + $(SolutionDir)$(Platform)\$(Configuration)\ + + \ No newline at end of file diff --git a/utils/aerodynamics_2_graphviz/dot -ooutput.f16.dot -Tf16.dot -Kdot b/utils/aerodynamics_2_graphviz/dot -ooutput.f16.dot -Tf16.dot -Kdot new file mode 100644 index 0000000000..8fb8f2753a --- /dev/null +++ b/utils/aerodynamics_2_graphviz/dot -ooutput.f16.dot -Tf16.dot -Kdot @@ -0,0 +1,566 @@ +digraph f16 { + graph [nodesep=0.1,rankdir=LR] + subgraph cluster_0 { + graph [label="0"] + "axis_DRAG_function_aero/coefficient/CDDh_axis_0"[color=gold,label="Drag_due_to_horizontal_tail_deflection",shape=box]; + "function_aero/coefficient/CDDh_product_axis_0"; + "axis_DRAG_function_aero/coefficient/CDDh_axis_0"->"function_aero/coefficient/CDDh_product_axis_0" [label="1:function_aero/coefficient/CDDh_product"]; + "aero/qbar-psf_axis_0"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "function_aero/coefficient/CDDh_product_axis_0"->"aero/qbar-psf_axis_0" [label="1:aero/qbar-psf"]; + "metrics/Sw-sqft_axis_0"[distortion=0,fillcolor=yellow,height=2.0,shape=polygon,sides=6,skew=-0.5,style=filled]; + "function_aero/coefficient/CDDh_product_axis_0"->"metrics/Sw-sqft_axis_0" [label="2:metrics/Sw-sqft"]; + "product_table_CDdHT_axis_0"[fillcolor=yellow,shape=doubleoctagon,style=filled]; + "function_aero/coefficient/CDDh_product_axis_0"->"product_table_CDdHT_axis_0" [label="3:product_table_CDdHT"]; + "aero/alpha-rad_axis_0"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "product_table_CDdHT_axis_0"->"aero/alpha-rad_axis_0" [label="1:aero/alpha-rad"]; + "fcs/elevator-pos-rad_axis_0"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "product_table_CDdHT_axis_0"->"fcs/elevator-pos-rad_axis_0" [label="2:fcs/elevator-pos-rad"]; + "axis_DRAG_function_aero/coefficient/CDmach_axis_0"[color=gold,label="Drag_due_to_mach",shape=box]; + "function_aero/coefficient/CDmach_product_axis_0"; + "axis_DRAG_function_aero/coefficient/CDmach_axis_0"->"function_aero/coefficient/CDmach_product_axis_0" [label="1:function_aero/coefficient/CDmach_product"]; + "function_aero/coefficient/CDmach_product_axis_0"->"aero/qbar-psf_axis_0" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CDmach_product_axis_0"->"metrics/Sw-sqft_axis_0" [label="2:metrics/Sw-sqft"]; + "product_table_CDmach_axis_0"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/CDmach_product_axis_0"->"product_table_CDmach_axis_0" [label="3:product_table_CDmach"]; + "velocities/mach_axis_0"[fillcolor=olivedrab,shape=tab,style=filled]; + "product_table_CDmach_axis_0"->"velocities/mach_axis_0" [label="1:velocities/mach"]; + "axis_DRAG_function_aero/coefficient/CDDlef_axis_0"[color=gold,label="Drag_due_to_leading_edge_flap_deflection",shape=box]; + "function_aero/coefficient/CDDlef_product_axis_0"; + "axis_DRAG_function_aero/coefficient/CDDlef_axis_0"->"function_aero/coefficient/CDDlef_product_axis_0" [label="1:function_aero/coefficient/CDDlef_product"]; + "function_aero/coefficient/CDDlef_product_axis_0"->"aero/qbar-psf_axis_0" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CDDlef_product_axis_0"->"metrics/Sw-sqft_axis_0" [label="2:metrics/Sw-sqft"]; + "fcs/lef-pos-rad_axis_0"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "function_aero/coefficient/CDDlef_product_axis_0"->"fcs/lef-pos-rad_axis_0" [label="3:fcs/lef-pos-rad"]; + "product_table_CDDlef_axis_0"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/CDDlef_product_axis_0"->"product_table_CDDlef_axis_0" [label="4:product_table_CDDlef"]; + "product_table_CDDlef_axis_0"->"aero/alpha-rad_axis_0" [label="1:aero/alpha-rad"]; + "axis_DRAG_function_aero/coefficient/CDDflaps_axis_0"[color=gold,label="Drag_due_to_trailing_edge_flaps",shape=box]; + "function_aero/coefficient/CDDflaps_product_axis_0"; + "axis_DRAG_function_aero/coefficient/CDDflaps_axis_0"->"function_aero/coefficient/CDDflaps_product_axis_0" [label="1:function_aero/coefficient/CDDflaps_product"]; + "function_aero/coefficient/CDDflaps_product_axis_0"->"aero/qbar-psf_axis_0" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CDDflaps_product_axis_0"->"metrics/Sw-sqft_axis_0" [label="2:metrics/Sw-sqft"]; + "fcs/flaperon-mix-rad_axis_0"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "function_aero/coefficient/CDDflaps_product_axis_0"->"fcs/flaperon-mix-rad_axis_0" [label="3:fcs/flaperon-mix-rad"]; + "constant value :0.080000_axis_0"[fillcolor=red,shape=egg,style=filled]; + "function_aero/coefficient/CDDflaps_product_axis_0"->"constant value :0.080000_axis_0" [label="4:constant value :0.080000"]; + "axis_DRAG_function_aero/coefficient/CDgear_axis_0"[color=gold,label="Drag_due_to_gear",shape=box]; + "function_aero/coefficient/CDgear_product_axis_0"; + "axis_DRAG_function_aero/coefficient/CDgear_axis_0"->"function_aero/coefficient/CDgear_product_axis_0" [label="1:function_aero/coefficient/CDgear_product"]; + "function_aero/coefficient/CDgear_product_axis_0"->"aero/qbar-psf_axis_0" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CDgear_product_axis_0"->"metrics/Sw-sqft_axis_0" [label="2:metrics/Sw-sqft"]; + "gear/gear-pos-norm_axis_0"; + "function_aero/coefficient/CDgear_product_axis_0"->"gear/gear-pos-norm_axis_0" [label="3:gear/gear-pos-norm"]; + "constant value :0.027000_axis_0"[fillcolor=red,shape=egg,style=filled]; + "function_aero/coefficient/CDgear_product_axis_0"->"constant value :0.027000_axis_0" [label="4:constant value :0.027000"]; + "axis_DRAG_function_aero/coefficient/CDDsb_axis_0"[color=gold,label="Drag_due_to_speedbrake_deflection",shape=box]; + "function_aero/coefficient/CDDsb_product_axis_0"; + "axis_DRAG_function_aero/coefficient/CDDsb_axis_0"->"function_aero/coefficient/CDDsb_product_axis_0" [label="1:function_aero/coefficient/CDDsb_product"]; + "function_aero/coefficient/CDDsb_product_axis_0"->"aero/qbar-psf_axis_0" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CDDsb_product_axis_0"->"metrics/Sw-sqft_axis_0" [label="2:metrics/Sw-sqft"]; + "fcs/speedbrake-pos-rad_axis_0"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "function_aero/coefficient/CDDsb_product_axis_0"->"fcs/speedbrake-pos-rad_axis_0" [label="3:fcs/speedbrake-pos-rad"]; + "product_table_CDDsb_axis_0"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/CDDsb_product_axis_0"->"product_table_CDDsb_axis_0" [label="4:product_table_CDDsb"]; + "product_table_CDDsb_axis_0"->"aero/alpha-rad_axis_0" [label="1:aero/alpha-rad"]; + "axis_DRAG_function_aero/coefficient/CDq_axis_0"[color=gold,label="Drag_due_to_pitch_rate",shape=box]; + "function_aero/coefficient/CDq_product_axis_0"; + "axis_DRAG_function_aero/coefficient/CDq_axis_0"->"function_aero/coefficient/CDq_product_axis_0" [label="1:function_aero/coefficient/CDq_product"]; + "function_aero/coefficient/CDq_product_axis_0"->"aero/qbar-psf_axis_0" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CDq_product_axis_0"->"metrics/Sw-sqft_axis_0" [label="2:metrics/Sw-sqft"]; + "velocities/q-aero-rad_sec_axis_0"[fillcolor=olivedrab,shape=tab,style=filled]; + "function_aero/coefficient/CDq_product_axis_0"->"velocities/q-aero-rad_sec_axis_0" [label="3:velocities/q-aero-rad_sec"]; + "aero/ci2vel_axis_0"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "function_aero/coefficient/CDq_product_axis_0"->"aero/ci2vel_axis_0" [label="4:aero/ci2vel"]; + "product_table_CDq_axis_0"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/CDq_product_axis_0"->"product_table_CDq_axis_0" [label="5:product_table_CDq"]; + "product_table_CDq_axis_0"->"aero/alpha-rad_axis_0" [label="1:aero/alpha-rad"]; + "axis_DRAG_function_aero/coefficient/CDq_Dlef_axis_0"[color=gold,label="Drag_due_to_pitch_rate_and_leading_edge_flap_deflection",shape=box]; + "function_aero/coefficient/CDq_Dlef_product_axis_0"; + "axis_DRAG_function_aero/coefficient/CDq_Dlef_axis_0"->"function_aero/coefficient/CDq_Dlef_product_axis_0" [label="1:function_aero/coefficient/CDq_Dlef_product"]; + "function_aero/coefficient/CDq_Dlef_product_axis_0"->"aero/qbar-psf_axis_0" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CDq_Dlef_product_axis_0"->"metrics/Sw-sqft_axis_0" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/CDq_Dlef_product_axis_0"->"velocities/q-aero-rad_sec_axis_0" [label="3:velocities/q-aero-rad_sec"]; + "function_aero/coefficient/CDq_Dlef_product_axis_0"->"aero/ci2vel_axis_0" [label="4:aero/ci2vel"]; + "function_aero/coefficient/CDq_Dlef_product_axis_0"->"fcs/lef-pos-rad_axis_0" [label="5:fcs/lef-pos-rad"]; + "product_table_CDq_Dlef_axis_0"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/CDq_Dlef_product_axis_0"->"product_table_CDq_Dlef_axis_0" [label="6:product_table_CDq_Dlef"]; + "product_table_CDq_Dlef_axis_0"->"aero/alpha-rad_axis_0" [label="1:aero/alpha-rad"]; + } + subgraph cluster_1 { + graph [label="1"] + "axis_SIDE_function_aero/coefficient/CYb_axis_1"[color=gold,label="Side_force_due_to_beta",shape=box]; + "function_aero/coefficient/CYb_product_axis_1"; + "axis_SIDE_function_aero/coefficient/CYb_axis_1"->"function_aero/coefficient/CYb_product_axis_1" [label="1:function_aero/coefficient/CYb_product"]; + "aero/qbar-psf_axis_1"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "function_aero/coefficient/CYb_product_axis_1"->"aero/qbar-psf_axis_1" [label="1:aero/qbar-psf"]; + "metrics/Sw-sqft_axis_1"[distortion=0,fillcolor=yellow,height=2.0,shape=polygon,sides=6,skew=-0.5,style=filled]; + "function_aero/coefficient/CYb_product_axis_1"->"metrics/Sw-sqft_axis_1" [label="2:metrics/Sw-sqft"]; + "aero/beta-rad_axis_1"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "function_aero/coefficient/CYb_product_axis_1"->"aero/beta-rad_axis_1" [label="3:aero/beta-rad"]; + "constant value :-1.146000_axis_1"[fillcolor=red,shape=egg,style=filled]; + "function_aero/coefficient/CYb_product_axis_1"->"constant value :-1.146000_axis_1" [label="4:constant value :-1.146000"]; + "axis_SIDE_function_aero/coefficient/CYb_M_axis_1"[color=gold,label="Change_in_Side_force_due_to_beta_due_to_mach",shape=box]; + "function_aero/coefficient/CYb_M_product_axis_1"; + "axis_SIDE_function_aero/coefficient/CYb_M_axis_1"->"function_aero/coefficient/CYb_M_product_axis_1" [label="1:function_aero/coefficient/CYb_M_product"]; + "function_aero/coefficient/CYb_M_product_axis_1"->"aero/qbar-psf_axis_1" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CYb_M_product_axis_1"->"metrics/Sw-sqft_axis_1" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/CYb_M_product_axis_1"->"aero/beta-rad_axis_1" [label="3:aero/beta-rad"]; + "product_table_CYb_M_axis_1"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/CYb_M_product_axis_1"->"product_table_CYb_M_axis_1" [label="4:product_table_CYb_M"]; + "velocities/mach_axis_1"[fillcolor=olivedrab,shape=tab,style=filled]; + "product_table_CYb_M_axis_1"->"velocities/mach_axis_1" [label="1:velocities/mach"]; + "axis_SIDE_function_aero/coefficient/CYDa_axis_1"[color=gold,label="Side_force_due_to_aileron",shape=box]; + "function_aero/coefficient/CYDa_product_axis_1"; + "axis_SIDE_function_aero/coefficient/CYDa_axis_1"->"function_aero/coefficient/CYDa_product_axis_1" [label="1:function_aero/coefficient/CYDa_product"]; + "function_aero/coefficient/CYDa_product_axis_1"->"aero/qbar-psf_axis_1" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CYDa_product_axis_1"->"metrics/Sw-sqft_axis_1" [label="2:metrics/Sw-sqft"]; + "fcs/aileron-pos-rad_axis_1"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "function_aero/coefficient/CYDa_product_axis_1"->"fcs/aileron-pos-rad_axis_1" [label="3:fcs/aileron-pos-rad"]; + "constant value :-0.022600_axis_1"[fillcolor=red,shape=egg,style=filled]; + "function_aero/coefficient/CYDa_product_axis_1"->"constant value :-0.022600_axis_1" [label="4:constant value :-0.022600"]; + "axis_SIDE_function_aero/coefficient/CYdr_axis_1"[color=gold,label="Side_force_due_to_rudder",shape=box]; + "function_aero/coefficient/CYdr_product_axis_1"; + "axis_SIDE_function_aero/coefficient/CYdr_axis_1"->"function_aero/coefficient/CYdr_product_axis_1" [label="1:function_aero/coefficient/CYdr_product"]; + "function_aero/coefficient/CYdr_product_axis_1"->"aero/qbar-psf_axis_1" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CYdr_product_axis_1"->"metrics/Sw-sqft_axis_1" [label="2:metrics/Sw-sqft"]; + "fcs/rudder-pos-rad_axis_1"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "function_aero/coefficient/CYdr_product_axis_1"->"fcs/rudder-pos-rad_axis_1" [label="3:fcs/rudder-pos-rad"]; + "constant value :0.086000_axis_1"[fillcolor=red,shape=egg,style=filled]; + "function_aero/coefficient/CYdr_product_axis_1"->"constant value :0.086000_axis_1" [label="4:constant value :0.086000"]; + "axis_SIDE_function_aero/coefficient/CYp_axis_1"[color=gold,label="Side_force_due_to_roll_rate",shape=box]; + "function_aero/coefficient/CYp_product_axis_1"; + "axis_SIDE_function_aero/coefficient/CYp_axis_1"->"function_aero/coefficient/CYp_product_axis_1" [label="1:function_aero/coefficient/CYp_product"]; + "function_aero/coefficient/CYp_product_axis_1"->"aero/qbar-psf_axis_1" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CYp_product_axis_1"->"metrics/Sw-sqft_axis_1" [label="2:metrics/Sw-sqft"]; + "aero/bi2vel_axis_1"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "function_aero/coefficient/CYp_product_axis_1"->"aero/bi2vel_axis_1" [label="3:aero/bi2vel"]; + "velocities/p-aero-rad_sec_axis_1"[fillcolor=olivedrab,shape=tab,style=filled]; + "function_aero/coefficient/CYp_product_axis_1"->"velocities/p-aero-rad_sec_axis_1" [label="4:velocities/p-aero-rad_sec"]; + "product_table_CYp_axis_1"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/CYp_product_axis_1"->"product_table_CYp_axis_1" [label="5:product_table_CYp"]; + "aero/alpha-rad_axis_1"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "product_table_CYp_axis_1"->"aero/alpha-rad_axis_1" [label="1:aero/alpha-rad"]; + "axis_SIDE_function_aero/coefficient/CYr_axis_1"[color=gold,label="Side_force_due_to_yaw_rate",shape=box]; + "function_aero/coefficient/CYr_product_axis_1"; + "axis_SIDE_function_aero/coefficient/CYr_axis_1"->"function_aero/coefficient/CYr_product_axis_1" [label="1:function_aero/coefficient/CYr_product"]; + "function_aero/coefficient/CYr_product_axis_1"->"aero/qbar-psf_axis_1" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CYr_product_axis_1"->"metrics/Sw-sqft_axis_1" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/CYr_product_axis_1"->"aero/bi2vel_axis_1" [label="3:aero/bi2vel"]; + "velocities/r-aero-rad_sec_axis_1"[fillcolor=olivedrab,shape=tab,style=filled]; + "function_aero/coefficient/CYr_product_axis_1"->"velocities/r-aero-rad_sec_axis_1" [label="4:velocities/r-aero-rad_sec"]; + "product_table_CYr_axis_1"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/CYr_product_axis_1"->"product_table_CYr_axis_1" [label="5:product_table_CYr"]; + "product_table_CYr_axis_1"->"aero/alpha-rad_axis_1" [label="1:aero/alpha-rad"]; + } + subgraph cluster_2 { + graph [label="2"] + "axis_LIFT_function_aero/coefficient/CLDh_axis_2"[color=gold,label="Lift_due_to_horizontal_tail_deflection",shape=box]; + "function_aero/coefficient/CLDh_product_axis_2"; + "axis_LIFT_function_aero/coefficient/CLDh_axis_2"->"function_aero/coefficient/CLDh_product_axis_2" [label="1:function_aero/coefficient/CLDh_product"]; + "aero/qbar-psf_axis_2"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "function_aero/coefficient/CLDh_product_axis_2"->"aero/qbar-psf_axis_2" [label="1:aero/qbar-psf"]; + "metrics/Sw-sqft_axis_2"[distortion=0,fillcolor=yellow,height=2.0,shape=polygon,sides=6,skew=-0.5,style=filled]; + "function_aero/coefficient/CLDh_product_axis_2"->"metrics/Sw-sqft_axis_2" [label="2:metrics/Sw-sqft"]; + "aero/function/kCLge_axis_2"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "function_aero/coefficient/CLDh_product_axis_2"->"aero/function/kCLge_axis_2" [label="3:aero/function/kCLge"]; + "product_table_CLDh_axis_2"[fillcolor=yellow,shape=doubleoctagon,style=filled]; + "function_aero/coefficient/CLDh_product_axis_2"->"product_table_CLDh_axis_2" [label="4:product_table_CLDh"]; + "aero/alpha-rad_axis_2"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "product_table_CLDh_axis_2"->"aero/alpha-rad_axis_2" [label="1:aero/alpha-rad"]; + "fcs/elevator-pos-rad_axis_2"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "product_table_CLDh_axis_2"->"fcs/elevator-pos-rad_axis_2" [label="2:fcs/elevator-pos-rad"]; + "axis_LIFT_function_aero/coefficient/CLDlef_axis_2"[color=gold,label="Lift_due_to_leading_edge_flap_deflection",shape=box]; + "function_aero/coefficient/CLDlef_product_axis_2"; + "axis_LIFT_function_aero/coefficient/CLDlef_axis_2"->"function_aero/coefficient/CLDlef_product_axis_2" [label="1:function_aero/coefficient/CLDlef_product"]; + "function_aero/coefficient/CLDlef_product_axis_2"->"aero/qbar-psf_axis_2" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CLDlef_product_axis_2"->"metrics/Sw-sqft_axis_2" [label="2:metrics/Sw-sqft"]; + "fcs/lef-pos-rad_axis_2"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "function_aero/coefficient/CLDlef_product_axis_2"->"fcs/lef-pos-rad_axis_2" [label="3:fcs/lef-pos-rad"]; + "function_aero/coefficient/CLDlef_product_axis_2"->"aero/function/kCLge_axis_2" [label="4:aero/function/kCLge"]; + "product_table_CLDlef_axis_2"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/CLDlef_product_axis_2"->"product_table_CLDlef_axis_2" [label="5:product_table_CLDlef"]; + "product_table_CLDlef_axis_2"->"aero/alpha-rad_axis_2" [label="1:aero/alpha-rad"]; + "axis_LIFT_function_aero/coefficient/CLDflaps_axis_2"[color=gold,label="Delta_Lift_due_to_trailing_edge_flaps",shape=box]; + "function_aero/coefficient/CLDflaps_product_axis_2"; + "axis_LIFT_function_aero/coefficient/CLDflaps_axis_2"->"function_aero/coefficient/CLDflaps_product_axis_2" [label="1:function_aero/coefficient/CLDflaps_product"]; + "function_aero/coefficient/CLDflaps_product_axis_2"->"aero/qbar-psf_axis_2" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CLDflaps_product_axis_2"->"metrics/Sw-sqft_axis_2" [label="2:metrics/Sw-sqft"]; + "fcs/flaperon-mix-rad_axis_2"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "function_aero/coefficient/CLDflaps_product_axis_2"->"fcs/flaperon-mix-rad_axis_2" [label="3:fcs/flaperon-mix-rad"]; + "function_aero/coefficient/CLDflaps_product_axis_2"->"aero/function/kCLge_axis_2" [label="4:aero/function/kCLge"]; + "constant value :0.350000_axis_2"[fillcolor=red,shape=egg,style=filled]; + "function_aero/coefficient/CLDflaps_product_axis_2"->"constant value :0.350000_axis_2" [label="5:constant value :0.350000"]; + "axis_LIFT_function_aero/coefficient/CLDsb_axis_2"[color=gold,label="Lift_due_to_speedbrake_deflection",shape=box]; + "function_aero/coefficient/CLDsb_product_axis_2"; + "axis_LIFT_function_aero/coefficient/CLDsb_axis_2"->"function_aero/coefficient/CLDsb_product_axis_2" [label="1:function_aero/coefficient/CLDsb_product"]; + "function_aero/coefficient/CLDsb_product_axis_2"->"aero/qbar-psf_axis_2" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CLDsb_product_axis_2"->"metrics/Sw-sqft_axis_2" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/CLDsb_product_axis_2"->"aero/function/kCLge_axis_2" [label="3:aero/function/kCLge"]; + "fcs/speedbrake-pos-rad_axis_2"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "function_aero/coefficient/CLDsb_product_axis_2"->"fcs/speedbrake-pos-rad_axis_2" [label="4:fcs/speedbrake-pos-rad"]; + "product_table_CLDsb_axis_2"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/CLDsb_product_axis_2"->"product_table_CLDsb_axis_2" [label="5:product_table_CLDsb"]; + "product_table_CLDsb_axis_2"->"aero/alpha-rad_axis_2" [label="1:aero/alpha-rad"]; + "axis_LIFT_function_aero/coefficient/CLq_axis_2"[color=gold,label="Lift_due_to_pitch_rate",shape=box]; + "function_aero/coefficient/CLq_product_axis_2"; + "axis_LIFT_function_aero/coefficient/CLq_axis_2"->"function_aero/coefficient/CLq_product_axis_2" [label="1:function_aero/coefficient/CLq_product"]; + "function_aero/coefficient/CLq_product_axis_2"->"aero/qbar-psf_axis_2" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CLq_product_axis_2"->"metrics/Sw-sqft_axis_2" [label="2:metrics/Sw-sqft"]; + "velocities/q-aero-rad_sec_axis_2"[fillcolor=olivedrab,shape=tab,style=filled]; + "function_aero/coefficient/CLq_product_axis_2"->"velocities/q-aero-rad_sec_axis_2" [label="3:velocities/q-aero-rad_sec"]; + "function_aero/coefficient/CLq_product_axis_2"->"aero/function/kCLge_axis_2" [label="4:aero/function/kCLge"]; + "aero/ci2vel_axis_2"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "function_aero/coefficient/CLq_product_axis_2"->"aero/ci2vel_axis_2" [label="5:aero/ci2vel"]; + "product_table_CLq_axis_2"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/CLq_product_axis_2"->"product_table_CLq_axis_2" [label="6:product_table_CLq"]; + "product_table_CLq_axis_2"->"aero/alpha-rad_axis_2" [label="1:aero/alpha-rad"]; + "axis_LIFT_function_aero/coefficient/CLq_Dsb_axis_2"[color=gold,label="Lift_due_to_pitch_rate_and_speedbrake_deflection",shape=box]; + "function_aero/coefficient/CLq_Dsb_product_axis_2"; + "axis_LIFT_function_aero/coefficient/CLq_Dsb_axis_2"->"function_aero/coefficient/CLq_Dsb_product_axis_2" [label="1:function_aero/coefficient/CLq_Dsb_product"]; + "function_aero/coefficient/CLq_Dsb_product_axis_2"->"aero/qbar-psf_axis_2" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CLq_Dsb_product_axis_2"->"metrics/Sw-sqft_axis_2" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/CLq_Dsb_product_axis_2"->"velocities/q-aero-rad_sec_axis_2" [label="3:velocities/q-aero-rad_sec"]; + "function_aero/coefficient/CLq_Dsb_product_axis_2"->"aero/ci2vel_axis_2" [label="4:aero/ci2vel"]; + "function_aero/coefficient/CLq_Dsb_product_axis_2"->"fcs/speedbrake-pos-rad_axis_2" [label="5:fcs/speedbrake-pos-rad"]; + "product_table_CLq_Dsb_axis_2"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/CLq_Dsb_product_axis_2"->"product_table_CLq_Dsb_axis_2" [label="6:product_table_CLq_Dsb"]; + "product_table_CLq_Dsb_axis_2"->"aero/alpha-rad_axis_2" [label="1:aero/alpha-rad"]; + } + subgraph cluster_3 { + graph [label="3"] + "axis_ROLL_function_aero/coefficient/Clb_axis_3"[color=gold,label="Roll_moment_due_to_beta",shape=box]; + "function_aero/coefficient/Clb_product_axis_3"; + "axis_ROLL_function_aero/coefficient/Clb_axis_3"->"function_aero/coefficient/Clb_product_axis_3" [label="1:function_aero/coefficient/Clb_product"]; + "aero/qbar-psf_axis_3"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "function_aero/coefficient/Clb_product_axis_3"->"aero/qbar-psf_axis_3" [label="1:aero/qbar-psf"]; + "metrics/Sw-sqft_axis_3"[distortion=0,fillcolor=yellow,height=2.0,shape=polygon,sides=6,skew=-0.5,style=filled]; + "function_aero/coefficient/Clb_product_axis_3"->"metrics/Sw-sqft_axis_3" [label="2:metrics/Sw-sqft"]; + "metrics/bw-ft_axis_3"[distortion=0,fillcolor=yellow,height=2.0,shape=polygon,sides=6,skew=-0.5,style=filled]; + "function_aero/coefficient/Clb_product_axis_3"->"metrics/bw-ft_axis_3" [label="3:metrics/bw-ft"]; + "product_table_Clb_axis_3"[fillcolor=yellow,shape=doubleoctagon,style=filled]; + "function_aero/coefficient/Clb_product_axis_3"->"product_table_Clb_axis_3" [label="4:product_table_Clb"]; + "aero/alpha-rad_axis_3"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "product_table_Clb_axis_3"->"aero/alpha-rad_axis_3" [label="1:aero/alpha-rad"]; + "aero/beta-rad_axis_3"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "product_table_Clb_axis_3"->"aero/beta-rad_axis_3" [label="2:aero/beta-rad"]; + "axis_ROLL_function_aero/coefficient/Clb_M_axis_3"[color=gold,label="Change_in_Roll_moment_due_to_beta_due_to_mach",shape=box]; + "function_aero/coefficient/Clb_M_product_axis_3"; + "axis_ROLL_function_aero/coefficient/Clb_M_axis_3"->"function_aero/coefficient/Clb_M_product_axis_3" [label="1:function_aero/coefficient/Clb_M_product"]; + "function_aero/coefficient/Clb_M_product_axis_3"->"aero/qbar-psf_axis_3" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Clb_M_product_axis_3"->"metrics/Sw-sqft_axis_3" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Clb_M_product_axis_3"->"metrics/bw-ft_axis_3" [label="3:metrics/bw-ft"]; + "function_aero/coefficient/Clb_M_product_axis_3"->"aero/beta-rad_axis_3" [label="4:aero/beta-rad"]; + "product_table_Clb_M_axis_3"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/Clb_M_product_axis_3"->"product_table_Clb_M_axis_3" [label="5:product_table_Clb_M"]; + "velocities/mach_axis_3"[fillcolor=olivedrab,shape=tab,style=filled]; + "product_table_Clb_M_axis_3"->"velocities/mach_axis_3" [label="1:velocities/mach"]; + "axis_ROLL_function_aero/coefficient/Clp_axis_3"[color=gold,label="Roll_moment_due_to_roll_rate_(roll_damping)",shape=box]; + "function_aero/coefficient/Clp_product_axis_3"; + "axis_ROLL_function_aero/coefficient/Clp_axis_3"->"function_aero/coefficient/Clp_product_axis_3" [label="1:function_aero/coefficient/Clp_product"]; + "function_aero/coefficient/Clp_product_axis_3"->"aero/qbar-psf_axis_3" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Clp_product_axis_3"->"metrics/Sw-sqft_axis_3" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Clp_product_axis_3"->"metrics/bw-ft_axis_3" [label="3:metrics/bw-ft"]; + "aero/bi2vel_axis_3"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "function_aero/coefficient/Clp_product_axis_3"->"aero/bi2vel_axis_3" [label="4:aero/bi2vel"]; + "velocities/p-aero-rad_sec_axis_3"[fillcolor=olivedrab,shape=tab,style=filled]; + "function_aero/coefficient/Clp_product_axis_3"->"velocities/p-aero-rad_sec_axis_3" [label="5:velocities/p-aero-rad_sec"]; + "product_table_Clp_axis_3"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/Clp_product_axis_3"->"product_table_Clp_axis_3" [label="6:product_table_Clp"]; + "product_table_Clp_axis_3"->"aero/alpha-rad_axis_3" [label="1:aero/alpha-rad"]; + "axis_ROLL_function_aero/coefficient/Clr_axis_3"[color=gold,label="Roll_moment_due_to_yaw_rate",shape=box]; + "function_aero/coefficient/Clr_product_axis_3"; + "axis_ROLL_function_aero/coefficient/Clr_axis_3"->"function_aero/coefficient/Clr_product_axis_3" [label="1:function_aero/coefficient/Clr_product"]; + "function_aero/coefficient/Clr_product_axis_3"->"aero/qbar-psf_axis_3" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Clr_product_axis_3"->"metrics/Sw-sqft_axis_3" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Clr_product_axis_3"->"metrics/bw-ft_axis_3" [label="3:metrics/bw-ft"]; + "function_aero/coefficient/Clr_product_axis_3"->"aero/bi2vel_axis_3" [label="4:aero/bi2vel"]; + "velocities/r-aero-rad_sec_axis_3"[fillcolor=olivedrab,shape=tab,style=filled]; + "function_aero/coefficient/Clr_product_axis_3"->"velocities/r-aero-rad_sec_axis_3" [label="5:velocities/r-aero-rad_sec"]; + "product_table_Clr_axis_3"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/Clr_product_axis_3"->"product_table_Clr_axis_3" [label="6:product_table_Clr"]; + "product_table_Clr_axis_3"->"aero/alpha-rad_axis_3" [label="1:aero/alpha-rad"]; + "axis_ROLL_function_aero/coefficient/Clda_axis_3"[color=gold,label="Roll_moment_due_to_aileron",shape=box]; + "function_aero/coefficient/Clda_product_axis_3"; + "axis_ROLL_function_aero/coefficient/Clda_axis_3"->"function_aero/coefficient/Clda_product_axis_3" [label="1:function_aero/coefficient/Clda_product"]; + "function_aero/coefficient/Clda_product_axis_3"->"aero/qbar-psf_axis_3" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Clda_product_axis_3"->"metrics/Sw-sqft_axis_3" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Clda_product_axis_3"->"metrics/bw-ft_axis_3" [label="3:metrics/bw-ft"]; + "fcs/aileron-pos-rad_axis_3"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "function_aero/coefficient/Clda_product_axis_3"->"fcs/aileron-pos-rad_axis_3" [label="4:fcs/aileron-pos-rad"]; + "product_table_Clda_axis_3"[fillcolor=yellow,shape=doubleoctagon,style=filled]; + "function_aero/coefficient/Clda_product_axis_3"->"product_table_Clda_axis_3" [label="5:product_table_Clda"]; + "product_table_Clda_axis_3"->"aero/alpha-rad_axis_3" [label="1:aero/alpha-rad"]; + "product_table_Clda_axis_3"->"aero/beta-rad_axis_3" [label="2:aero/beta-rad"]; + "axis_ROLL_function_aero/coefficient/Clda_M_axis_3"[color=gold,label="Change_in_Roll_moment_due_to_aileron_due_to_mach",shape=box]; + "function_aero/coefficient/Clda_M_product_axis_3"; + "axis_ROLL_function_aero/coefficient/Clda_M_axis_3"->"function_aero/coefficient/Clda_M_product_axis_3" [label="1:function_aero/coefficient/Clda_M_product"]; + "function_aero/coefficient/Clda_M_product_axis_3"->"aero/qbar-psf_axis_3" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Clda_M_product_axis_3"->"metrics/Sw-sqft_axis_3" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Clda_M_product_axis_3"->"metrics/bw-ft_axis_3" [label="3:metrics/bw-ft"]; + "function_aero/coefficient/Clda_M_product_axis_3"->"aero/alpha-rad_axis_3" [label="4:aero/alpha-rad"]; + "function_aero/coefficient/Clda_M_product_axis_3"->"fcs/aileron-pos-rad_axis_3" [label="5:fcs/aileron-pos-rad"]; + "product_table_Clda_M_axis_3"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/Clda_M_product_axis_3"->"product_table_Clda_M_axis_3" [label="6:product_table_Clda_M"]; + "product_table_Clda_M_axis_3"->"velocities/mach_axis_3" [label="1:velocities/mach"]; + "axis_ROLL_function_aero/coefficient/Cldr_M_axis_3"[color=gold,label="Change_in_Roll_moment_due_to_rudder_due_to_mach",shape=box]; + "function_aero/coefficient/Cldr_M_product_axis_3"; + "axis_ROLL_function_aero/coefficient/Cldr_M_axis_3"->"function_aero/coefficient/Cldr_M_product_axis_3" [label="1:function_aero/coefficient/Cldr_M_product"]; + "function_aero/coefficient/Cldr_M_product_axis_3"->"aero/qbar-psf_axis_3" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Cldr_M_product_axis_3"->"metrics/Sw-sqft_axis_3" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Cldr_M_product_axis_3"->"metrics/bw-ft_axis_3" [label="3:metrics/bw-ft"]; + "function_aero/coefficient/Cldr_M_product_axis_3"->"aero/alpha-rad_axis_3" [label="4:aero/alpha-rad"]; + "fcs/rudder-pos-rad_axis_3"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "function_aero/coefficient/Cldr_M_product_axis_3"->"fcs/rudder-pos-rad_axis_3" [label="5:fcs/rudder-pos-rad"]; + "product_table_Cldr_M_axis_3"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/Cldr_M_product_axis_3"->"product_table_Cldr_M_axis_3" [label="6:product_table_Cldr_M"]; + "product_table_Cldr_M_axis_3"->"velocities/mach_axis_3" [label="1:velocities/mach"]; + "axis_ROLL_function_aero/coefficient/Cldr_axis_3"[color=gold,label="Roll_moment_due_to_rudder",shape=box]; + "function_aero/coefficient/Cldr_product_axis_3"; + "axis_ROLL_function_aero/coefficient/Cldr_axis_3"->"function_aero/coefficient/Cldr_product_axis_3" [label="1:function_aero/coefficient/Cldr_product"]; + "function_aero/coefficient/Cldr_product_axis_3"->"aero/qbar-psf_axis_3" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Cldr_product_axis_3"->"metrics/Sw-sqft_axis_3" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Cldr_product_axis_3"->"metrics/bw-ft_axis_3" [label="3:metrics/bw-ft"]; + "function_aero/coefficient/Cldr_product_axis_3"->"fcs/rudder-pos-rad_axis_3" [label="4:fcs/rudder-pos-rad"]; + "product_table_Cldr_axis_3"[fillcolor=yellow,shape=doubleoctagon,style=filled]; + "function_aero/coefficient/Cldr_product_axis_3"->"product_table_Cldr_axis_3" [label="5:product_table_Cldr"]; + "product_table_Cldr_axis_3"->"aero/alpha-rad_axis_3" [label="1:aero/alpha-rad"]; + "product_table_Cldr_axis_3"->"aero/beta-rad_axis_3" [label="2:aero/beta-rad"]; + } + subgraph cluster_4 { + graph [label="4"] + "axis_PITCH_function_aero/coefficient/CmDh_axis_4"[color=gold,label="Pitch_moment_due_to_horizontal_tail_deflection",shape=box]; + "function_aero/coefficient/CmDh_product_axis_4"; + "axis_PITCH_function_aero/coefficient/CmDh_axis_4"->"function_aero/coefficient/CmDh_product_axis_4" [label="1:function_aero/coefficient/CmDh_product"]; + "aero/qbar-psf_axis_4"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "function_aero/coefficient/CmDh_product_axis_4"->"aero/qbar-psf_axis_4" [label="1:aero/qbar-psf"]; + "metrics/Sw-sqft_axis_4"[distortion=0,fillcolor=yellow,height=2.0,shape=polygon,sides=6,skew=-0.5,style=filled]; + "function_aero/coefficient/CmDh_product_axis_4"->"metrics/Sw-sqft_axis_4" [label="2:metrics/Sw-sqft"]; + "metrics/cbarw-ft_axis_4"[distortion=0,fillcolor=yellow,height=2.0,shape=polygon,sides=6,skew=-0.5,style=filled]; + "function_aero/coefficient/CmDh_product_axis_4"->"metrics/cbarw-ft_axis_4" [label="3:metrics/cbarw-ft"]; + "product_table_CmDh_axis_4"[fillcolor=yellow,shape=doubleoctagon,style=filled]; + "function_aero/coefficient/CmDh_product_axis_4"->"product_table_CmDh_axis_4" [label="4:product_table_CmDh"]; + "aero/alpha-rad_axis_4"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "product_table_CmDh_axis_4"->"aero/alpha-rad_axis_4" [label="1:aero/alpha-rad"]; + "fcs/elevator-pos-rad_axis_4"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "product_table_CmDh_axis_4"->"fcs/elevator-pos-rad_axis_4" [label="2:fcs/elevator-pos-rad"]; + "axis_PITCH_function_aero/coefficient/Cma_M_axis_4"[color=gold,label="Change_in_Pitch_moment_due_to_alpha_due_to_mach",shape=box]; + "function_aero/coefficient/Cma_M_product_axis_4"; + "axis_PITCH_function_aero/coefficient/Cma_M_axis_4"->"function_aero/coefficient/Cma_M_product_axis_4" [label="1:function_aero/coefficient/Cma_M_product"]; + "function_aero/coefficient/Cma_M_product_axis_4"->"aero/qbar-psf_axis_4" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Cma_M_product_axis_4"->"metrics/Sw-sqft_axis_4" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Cma_M_product_axis_4"->"metrics/cbarw-ft_axis_4" [label="3:metrics/cbarw-ft"]; + "function_aero/coefficient/Cma_M_product_axis_4"->"aero/alpha-rad_axis_4" [label="4:aero/alpha-rad"]; + "product_table_Cma_M_axis_4"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/Cma_M_product_axis_4"->"product_table_Cma_M_axis_4" [label="5:product_table_Cma_M"]; + "velocities/mach_axis_4"[fillcolor=olivedrab,shape=tab,style=filled]; + "product_table_Cma_M_axis_4"->"velocities/mach_axis_4" [label="1:velocities/mach"]; + "axis_PITCH_function_aero/coefficient/CmDsb_axis_4"[color=gold,label="Change_in_Pitch_moment_due_to_speedbrake",shape=box]; + "function_aero/coefficient/CmDsb_product_axis_4"; + "axis_PITCH_function_aero/coefficient/CmDsb_axis_4"->"function_aero/coefficient/CmDsb_product_axis_4" [label="1:function_aero/coefficient/CmDsb_product"]; + "function_aero/coefficient/CmDsb_product_axis_4"->"aero/qbar-psf_axis_4" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/CmDsb_product_axis_4"->"metrics/Sw-sqft_axis_4" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/CmDsb_product_axis_4"->"metrics/cbarw-ft_axis_4" [label="3:metrics/cbarw-ft"]; + "fcs/speedbrake-pos-rad_axis_4"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "function_aero/coefficient/CmDsb_product_axis_4"->"fcs/speedbrake-pos-rad_axis_4" [label="4:fcs/speedbrake-pos-rad"]; + "product_table_CmDsb_axis_4"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/CmDsb_product_axis_4"->"product_table_CmDsb_axis_4" [label="5:product_table_CmDsb"]; + "product_table_CmDsb_axis_4"->"aero/alpha-rad_axis_4" [label="1:aero/alpha-rad"]; + "axis_PITCH_function_aero/coefficient/Cmq_axis_4"[color=gold,label="Pitch_moment_due_to_pitch_rate",shape=box]; + "function_aero/coefficient/Cmq_product_axis_4"; + "axis_PITCH_function_aero/coefficient/Cmq_axis_4"->"function_aero/coefficient/Cmq_product_axis_4" [label="1:function_aero/coefficient/Cmq_product"]; + "function_aero/coefficient/Cmq_product_axis_4"->"aero/qbar-psf_axis_4" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Cmq_product_axis_4"->"metrics/Sw-sqft_axis_4" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Cmq_product_axis_4"->"metrics/cbarw-ft_axis_4" [label="3:metrics/cbarw-ft"]; + "aero/ci2vel_axis_4"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "function_aero/coefficient/Cmq_product_axis_4"->"aero/ci2vel_axis_4" [label="4:aero/ci2vel"]; + "velocities/q-aero-rad_sec_axis_4"[fillcolor=olivedrab,shape=tab,style=filled]; + "function_aero/coefficient/Cmq_product_axis_4"->"velocities/q-aero-rad_sec_axis_4" [label="5:velocities/q-aero-rad_sec"]; + "product_table_Cmq_axis_4"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/Cmq_product_axis_4"->"product_table_Cmq_axis_4" [label="6:product_table_Cmq"]; + "product_table_Cmq_axis_4"->"aero/alpha-rad_axis_4" [label="1:aero/alpha-rad"]; + } + subgraph cluster_5 { + graph [label="5"] + "axis_YAW_function_aero/coefficient/Cnb_axis_5"[color=gold,label="Yaw_moment_due_to_beta",shape=box]; + "function_aero/coefficient/Cnb_product_axis_5"; + "axis_YAW_function_aero/coefficient/Cnb_axis_5"->"function_aero/coefficient/Cnb_product_axis_5" [label="1:function_aero/coefficient/Cnb_product"]; + "aero/qbar-psf_axis_5"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "function_aero/coefficient/Cnb_product_axis_5"->"aero/qbar-psf_axis_5" [label="1:aero/qbar-psf"]; + "metrics/Sw-sqft_axis_5"[distortion=0,fillcolor=yellow,height=2.0,shape=polygon,sides=6,skew=-0.5,style=filled]; + "function_aero/coefficient/Cnb_product_axis_5"->"metrics/Sw-sqft_axis_5" [label="2:metrics/Sw-sqft"]; + "metrics/bw-ft_axis_5"[distortion=0,fillcolor=yellow,height=2.0,shape=polygon,sides=6,skew=-0.5,style=filled]; + "function_aero/coefficient/Cnb_product_axis_5"->"metrics/bw-ft_axis_5" [label="3:metrics/bw-ft"]; + "product_table_Cnb_axis_5"[fillcolor=yellow,shape=doubleoctagon,style=filled]; + "function_aero/coefficient/Cnb_product_axis_5"->"product_table_Cnb_axis_5" [label="4:product_table_Cnb"]; + "aero/alpha-rad_axis_5"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "product_table_Cnb_axis_5"->"aero/alpha-rad_axis_5" [label="1:aero/alpha-rad"]; + "aero/beta-rad_axis_5"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "product_table_Cnb_axis_5"->"aero/beta-rad_axis_5" [label="2:aero/beta-rad"]; + "axis_YAW_function_aero/coefficient/Cnb_M_axis_5"[color=gold,label="Change_in_Yaw_moment_due_to_beta_due_to_mach",shape=box]; + "function_aero/coefficient/Cnb_M_product_axis_5"; + "axis_YAW_function_aero/coefficient/Cnb_M_axis_5"->"function_aero/coefficient/Cnb_M_product_axis_5" [label="1:function_aero/coefficient/Cnb_M_product"]; + "function_aero/coefficient/Cnb_M_product_axis_5"->"aero/qbar-psf_axis_5" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Cnb_M_product_axis_5"->"metrics/Sw-sqft_axis_5" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Cnb_M_product_axis_5"->"metrics/bw-ft_axis_5" [label="3:metrics/bw-ft"]; + "function_aero/coefficient/Cnb_M_product_axis_5"->"aero/beta-rad_axis_5" [label="4:aero/beta-rad"]; + "product_table_Cnb_M_axis_5"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/Cnb_M_product_axis_5"->"product_table_Cnb_M_axis_5" [label="5:product_table_Cnb_M"]; + "velocities/mach_axis_5"[fillcolor=olivedrab,shape=tab,style=filled]; + "product_table_Cnb_M_axis_5"->"velocities/mach_axis_5" [label="1:velocities/mach"]; + "axis_YAW_function_aero/coefficient/Cnp_axis_5"[color=gold,label="Yaw_moment_due_to_roll_rate",shape=box]; + "function_aero/coefficient/Cnp_product_axis_5"; + "axis_YAW_function_aero/coefficient/Cnp_axis_5"->"function_aero/coefficient/Cnp_product_axis_5" [label="1:function_aero/coefficient/Cnp_product"]; + "function_aero/coefficient/Cnp_product_axis_5"->"aero/qbar-psf_axis_5" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Cnp_product_axis_5"->"metrics/Sw-sqft_axis_5" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Cnp_product_axis_5"->"metrics/bw-ft_axis_5" [label="3:metrics/bw-ft"]; + "aero/bi2vel_axis_5"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "function_aero/coefficient/Cnp_product_axis_5"->"aero/bi2vel_axis_5" [label="4:aero/bi2vel"]; + "velocities/p-aero-rad_sec_axis_5"[fillcolor=olivedrab,shape=tab,style=filled]; + "function_aero/coefficient/Cnp_product_axis_5"->"velocities/p-aero-rad_sec_axis_5" [label="5:velocities/p-aero-rad_sec"]; + "product_table_Cnp_axis_5"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/Cnp_product_axis_5"->"product_table_Cnp_axis_5" [label="6:product_table_Cnp"]; + "product_table_Cnp_axis_5"->"aero/alpha-rad_axis_5" [label="1:aero/alpha-rad"]; + "axis_YAW_function_aero/coefficient/Cnr_axis_5"[color=gold,label="Yaw_moment_due_to_yaw_rate",shape=box]; + "function_aero/coefficient/Cnr_product_axis_5"; + "axis_YAW_function_aero/coefficient/Cnr_axis_5"->"function_aero/coefficient/Cnr_product_axis_5" [label="1:function_aero/coefficient/Cnr_product"]; + "function_aero/coefficient/Cnr_product_axis_5"->"aero/qbar-psf_axis_5" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Cnr_product_axis_5"->"metrics/Sw-sqft_axis_5" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Cnr_product_axis_5"->"metrics/bw-ft_axis_5" [label="3:metrics/bw-ft"]; + "function_aero/coefficient/Cnr_product_axis_5"->"aero/bi2vel_axis_5" [label="4:aero/bi2vel"]; + "velocities/r-aero-rad_sec_axis_5"[fillcolor=olivedrab,shape=tab,style=filled]; + "function_aero/coefficient/Cnr_product_axis_5"->"velocities/r-aero-rad_sec_axis_5" [label="5:velocities/r-aero-rad_sec"]; + "product_table_Cnr_axis_5"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/Cnr_product_axis_5"->"product_table_Cnr_axis_5" [label="6:product_table_Cnr"]; + "product_table_Cnr_axis_5"->"aero/alpha-rad_axis_5" [label="1:aero/alpha-rad"]; + "axis_YAW_function_aero/coefficient/Cnda_M_axis_5"[color=gold,label="Change_in_Yaw_moment_due_to_aileron_due_to_mach",shape=box]; + "function_aero/coefficient/Cnda_M_product_axis_5"; + "axis_YAW_function_aero/coefficient/Cnda_M_axis_5"->"function_aero/coefficient/Cnda_M_product_axis_5" [label="1:function_aero/coefficient/Cnda_M_product"]; + "function_aero/coefficient/Cnda_M_product_axis_5"->"aero/qbar-psf_axis_5" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Cnda_M_product_axis_5"->"metrics/Sw-sqft_axis_5" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Cnda_M_product_axis_5"->"metrics/bw-ft_axis_5" [label="3:metrics/bw-ft"]; + "fcs/aileron-pos-rad_axis_5"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "function_aero/coefficient/Cnda_M_product_axis_5"->"fcs/aileron-pos-rad_axis_5" [label="4:fcs/aileron-pos-rad"]; + "product_table_Cnda_M_axis_5"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/Cnda_M_product_axis_5"->"product_table_Cnda_M_axis_5" [label="5:product_table_Cnda_M"]; + "product_table_Cnda_M_axis_5"->"velocities/mach_axis_5" [label="1:velocities/mach"]; + "axis_YAW_function_aero/coefficient/Cnda_axis_5"[color=gold,label="Yaw_moment_due_to_aileron",shape=box]; + "function_aero/coefficient/Cnda_product_axis_5"; + "axis_YAW_function_aero/coefficient/Cnda_axis_5"->"function_aero/coefficient/Cnda_product_axis_5" [label="1:function_aero/coefficient/Cnda_product"]; + "function_aero/coefficient/Cnda_product_axis_5"->"aero/qbar-psf_axis_5" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Cnda_product_axis_5"->"metrics/Sw-sqft_axis_5" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Cnda_product_axis_5"->"metrics/bw-ft_axis_5" [label="3:metrics/bw-ft"]; + "function_aero/coefficient/Cnda_product_axis_5"->"fcs/aileron-pos-rad_axis_5" [label="4:fcs/aileron-pos-rad"]; + "product_table_Cnda_axis_5"[fillcolor=yellow,shape=doubleoctagon,style=filled]; + "function_aero/coefficient/Cnda_product_axis_5"->"product_table_Cnda_axis_5" [label="5:product_table_Cnda"]; + "product_table_Cnda_axis_5"->"aero/alpha-rad_axis_5" [label="1:aero/alpha-rad"]; + "product_table_Cnda_axis_5"->"aero/beta-rad_axis_5" [label="2:aero/beta-rad"]; + "axis_YAW_function_aero/coefficient/Cndr_axis_5"[color=gold,label="Yaw_moment_due_to_rudder",shape=box]; + "function_aero/coefficient/Cndr_product_axis_5"; + "axis_YAW_function_aero/coefficient/Cndr_axis_5"->"function_aero/coefficient/Cndr_product_axis_5" [label="1:function_aero/coefficient/Cndr_product"]; + "function_aero/coefficient/Cndr_product_axis_5"->"aero/qbar-psf_axis_5" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Cndr_product_axis_5"->"metrics/Sw-sqft_axis_5" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Cndr_product_axis_5"->"metrics/bw-ft_axis_5" [label="3:metrics/bw-ft"]; + "fcs/rudder-pos-rad_axis_5"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "function_aero/coefficient/Cndr_product_axis_5"->"fcs/rudder-pos-rad_axis_5" [label="4:fcs/rudder-pos-rad"]; + "product_table_Cndr_axis_5"[fillcolor=yellow,shape=doubleoctagon,style=filled]; + "function_aero/coefficient/Cndr_product_axis_5"->"product_table_Cndr_axis_5" [label="5:product_table_Cndr"]; + "product_table_Cndr_axis_5"->"aero/alpha-rad_axis_5" [label="1:aero/alpha-rad"]; + "product_table_Cndr_axis_5"->"aero/beta-rad_axis_5" [label="2:aero/beta-rad"]; + "axis_YAW_function_aero/coefficient/Cndr_M_axis_5"[color=gold,label="Change_in_Yaw_moment_due_to_rudder_due_to_mach",shape=box]; + "function_aero/coefficient/Cndr_M_product_axis_5"; + "axis_YAW_function_aero/coefficient/Cndr_M_axis_5"->"function_aero/coefficient/Cndr_M_product_axis_5" [label="1:function_aero/coefficient/Cndr_M_product"]; + "function_aero/coefficient/Cndr_M_product_axis_5"->"aero/qbar-psf_axis_5" [label="1:aero/qbar-psf"]; + "function_aero/coefficient/Cndr_M_product_axis_5"->"metrics/Sw-sqft_axis_5" [label="2:metrics/Sw-sqft"]; + "function_aero/coefficient/Cndr_M_product_axis_5"->"metrics/bw-ft_axis_5" [label="3:metrics/bw-ft"]; + "function_aero/coefficient/Cndr_M_product_axis_5"->"aero/alpha-rad_axis_5" [label="4:aero/alpha-rad"]; + "function_aero/coefficient/Cndr_M_product_axis_5"->"fcs/rudder-pos-rad_axis_5" [label="5:fcs/rudder-pos-rad"]; + "product_table_Cndr_M_axis_5"[fillcolor=red,shape=polygon,sides=6,style=filled]; + "function_aero/coefficient/Cndr_M_product_axis_5"->"product_table_Cndr_M_axis_5" [label="6:product_table_Cndr_M"]; + "product_table_Cndr_M_axis_5"->"velocities/mach_axis_5" [label="1:velocities/mach"]; + } + subgraph cluster_common { + graph [label="common"] + "aero/alpha-rad"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "aero/beta-rad"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "aero/bi2vel"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "aero/ci2vel"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "aero/function/kCLge"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "aero/qbar-psf"[distortion=0,fillcolor=green,height=2.0,shape=polygon,sides=7,skew=-0.5,style=filled]; + "fcs/aileron-pos-rad"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "fcs/elevator-pos-rad"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "fcs/flaperon-mix-rad"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "fcs/lef-pos-rad"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "fcs/rudder-pos-rad"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "fcs/speedbrake-pos-rad"[distortion=0,fillcolor=blue,height=2.0,shape=polygon,sides=5,skew=-0.5,style=filled]; + "gear/gear-pos-norm"; + "metrics/Sw-sqft"[distortion=0,fillcolor=yellow,height=2.0,shape=polygon,sides=6,skew=-0.5,style=filled]; + "metrics/bw-ft"[distortion=0,fillcolor=yellow,height=2.0,shape=polygon,sides=6,skew=-0.5,style=filled]; + "metrics/cbarw-ft"[distortion=0,fillcolor=yellow,height=2.0,shape=polygon,sides=6,skew=-0.5,style=filled]; + "velocities/mach"[fillcolor=olivedrab,shape=tab,style=filled]; + "velocities/p-aero-rad_sec"[fillcolor=olivedrab,shape=tab,style=filled]; + "velocities/q-aero-rad_sec"[fillcolor=olivedrab,shape=tab,style=filled]; + "velocities/r-aero-rad_sec"[fillcolor=olivedrab,shape=tab,style=filled]; + } + "aero/alpha-rad_axis_0"->"aero/alpha-rad" [splines=curved]; + "aero/alpha-rad_axis_1"->"aero/alpha-rad" [splines=curved]; + "aero/alpha-rad_axis_2"->"aero/alpha-rad" [splines=curved]; + "aero/alpha-rad_axis_3"->"aero/alpha-rad" [splines=curved]; + "aero/alpha-rad_axis_4"->"aero/alpha-rad" [splines=curved]; + "aero/alpha-rad_axis_5"->"aero/alpha-rad" [splines=curved]; + "aero/beta-rad_axis_1"->"aero/beta-rad" [splines=curved]; + "aero/beta-rad_axis_3"->"aero/beta-rad" [splines=curved]; + "aero/beta-rad_axis_5"->"aero/beta-rad" [splines=curved]; + "aero/bi2vel_axis_1"->"aero/bi2vel" [splines=curved]; + "aero/bi2vel_axis_3"->"aero/bi2vel" [splines=curved]; + "aero/bi2vel_axis_5"->"aero/bi2vel" [splines=curved]; + "aero/ci2vel_axis_0"->"aero/ci2vel" [splines=curved]; + "aero/ci2vel_axis_2"->"aero/ci2vel" [splines=curved]; + "aero/ci2vel_axis_4"->"aero/ci2vel" [splines=curved]; + "aero/function/kCLge_axis_2"->"aero/function/kCLge" [splines=curved]; + "aero/qbar-psf_axis_0"->"aero/qbar-psf" [splines=curved]; + "aero/qbar-psf_axis_1"->"aero/qbar-psf" [splines=curved]; + "aero/qbar-psf_axis_2"->"aero/qbar-psf" [splines=curved]; + "aero/qbar-psf_axis_3"->"aero/qbar-psf" [splines=curved]; + "aero/qbar-psf_axis_4"->"aero/qbar-psf" [splines=curved]; + "aero/qbar-psf_axis_5"->"aero/qbar-psf" [splines=curved]; + "fcs/aileron-pos-rad_axis_1"->"fcs/aileron-pos-rad" [splines=curved]; + "fcs/aileron-pos-rad_axis_3"->"fcs/aileron-pos-rad" [splines=curved]; + "fcs/aileron-pos-rad_axis_5"->"fcs/aileron-pos-rad" [splines=curved]; + "fcs/elevator-pos-rad_axis_0"->"fcs/elevator-pos-rad" [splines=curved]; + "fcs/elevator-pos-rad_axis_2"->"fcs/elevator-pos-rad" [splines=curved]; + "fcs/elevator-pos-rad_axis_4"->"fcs/elevator-pos-rad" [splines=curved]; + "fcs/flaperon-mix-rad_axis_0"->"fcs/flaperon-mix-rad" [splines=curved]; + "fcs/flaperon-mix-rad_axis_2"->"fcs/flaperon-mix-rad" [splines=curved]; + "fcs/lef-pos-rad_axis_0"->"fcs/lef-pos-rad" [splines=curved]; + "fcs/lef-pos-rad_axis_2"->"fcs/lef-pos-rad" [splines=curved]; + "fcs/rudder-pos-rad_axis_1"->"fcs/rudder-pos-rad" [splines=curved]; + "fcs/rudder-pos-rad_axis_3"->"fcs/rudder-pos-rad" [splines=curved]; + "fcs/rudder-pos-rad_axis_5"->"fcs/rudder-pos-rad" [splines=curved]; + "fcs/speedbrake-pos-rad_axis_0"->"fcs/speedbrake-pos-rad" [splines=curved]; + "fcs/speedbrake-pos-rad_axis_2"->"fcs/speedbrake-pos-rad" [splines=curved]; + "fcs/speedbrake-pos-rad_axis_4"->"fcs/speedbrake-pos-rad" [splines=curved]; + "gear/gear-pos-norm_axis_0"->"gear/gear-pos-norm" [splines=curved]; + "metrics/Sw-sqft_axis_0"->"metrics/Sw-sqft" [splines=curved]; + "metrics/Sw-sqft_axis_1"->"metrics/Sw-sqft" [splines=curved]; + "metrics/Sw-sqft_axis_2"->"metrics/Sw-sqft" [splines=curved]; + "metrics/Sw-sqft_axis_3"->"metrics/Sw-sqft" [splines=curved]; + "metrics/Sw-sqft_axis_4"->"metrics/Sw-sqft" [splines=curved]; + "metrics/Sw-sqft_axis_5"->"metrics/Sw-sqft" [splines=curved]; + "metrics/bw-ft_axis_3"->"metrics/bw-ft" [splines=curved]; + "metrics/bw-ft_axis_5"->"metrics/bw-ft" [splines=curved]; + "metrics/cbarw-ft_axis_4"->"metrics/cbarw-ft" [splines=curved]; + "velocities/mach_axis_0"->"velocities/mach" [splines=curved]; + "velocities/mach_axis_1"->"velocities/mach" [splines=curved]; + "velocities/mach_axis_3"->"velocities/mach" [splines=curved]; + "velocities/mach_axis_4"->"velocities/mach" [splines=curved]; + "velocities/mach_axis_5"->"velocities/mach" [splines=curved]; + "velocities/p-aero-rad_sec_axis_1"->"velocities/p-aero-rad_sec" [splines=curved]; + "velocities/p-aero-rad_sec_axis_3"->"velocities/p-aero-rad_sec" [splines=curved]; + "velocities/p-aero-rad_sec_axis_5"->"velocities/p-aero-rad_sec" [splines=curved]; + "velocities/q-aero-rad_sec_axis_0"->"velocities/q-aero-rad_sec" [splines=curved]; + "velocities/q-aero-rad_sec_axis_2"->"velocities/q-aero-rad_sec" [splines=curved]; + "velocities/q-aero-rad_sec_axis_4"->"velocities/q-aero-rad_sec" [splines=curved]; + "velocities/r-aero-rad_sec_axis_1"->"velocities/r-aero-rad_sec" [splines=curved]; + "velocities/r-aero-rad_sec_axis_3"->"velocities/r-aero-rad_sec" [splines=curved]; + "velocities/r-aero-rad_sec_axis_5"->"velocities/r-aero-rad_sec" [splines=curved]; +} diff --git a/utils/aerodynamics_2_graphviz/gvpp.cpp b/utils/aerodynamics_2_graphviz/gvpp.cpp new file mode 100644 index 0000000000..bff8f8906b --- /dev/null +++ b/utils/aerodynamics_2_graphviz/gvpp.cpp @@ -0,0 +1,269 @@ +#include "gvpp.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#define CHECK_CALL(CODE) if (!(CODE)) throw runtime_error("Call to 'CODE' failed") + +#define ostreamtype std::basic_ostream +#define strtype std::basic_string +#define ElementI Element +#define AbstractGraphI AbstractGraph +#define GraphI Graph +#define SubGraphI SubGraph +#define NodeI Node +#define EdgeI Edge +#define GvAttributesI GvAttributes +#define printLineI printLine + +namespace gvpp { + using namespace std; + + #define indentChar (chartype)'\t' + + #define quoteChar (chartype)'"' + + template<> + string strFromLit(const wchar_t *chars) { + static wstring_convert> converter; + return converter.to_bytes(wstring(chars)); + } + + template<> + wstring strFromLit(const char *chars) { + static wstring_convert> converter; + return converter.from_bytes(string(chars)); + } + + template + void NodeI::printTo(printLineI pl) const { + pl.os << pl.indent << id; + this->getAttributes().printTo(pl); + pl.os << ";" << endl; + } + + template + void EdgeI::printTo(printLineI pl) const { + pl.os << pl.indent << getFrom().getId() + << (this->getParent().isDirected() ? "->" : "--") << getTo().getId() + <<" "; + this->getAttributes().printTo(pl); + pl.os <<";" << endl; + } + + template + void GvAttributesI::printTo(printLineI pl) const { + if (!this->empty()) { + pl.os << "["; + int i = 0; + for (auto p : *this) + pl.os << (i++ > 0 ? "," : "") << get<0>(p) <<"="<< get<1>(p); + pl.os << "]"; + } + } + + template + void AbstractGraphI::printGraphTo(printLineI pl) const { + pl.os << pl.indent << getKeyword() <<" "<< getName() << " {\n"; + printLineI npl = {pl.os, pl.indent + (chartype)'\t'}; + if (getAttributes(AttrType::GRAPH).size() > 0) { + npl.os << npl.indent << "graph "; + getAttributes(AttrType::GRAPH).printTo(npl); + npl.os << endl; + } + if (getAttributes(AttrType::EDGE).size() > 0) { + npl.os << npl.indent << "edge "; + getAttributes(AttrType::EDGE).printTo(npl); + npl.os << endl; + } + if (getAttributes(AttrType::NODE).size() > 0) { + npl.os << npl.indent << "node "; + getAttributes(AttrType::NODE).printTo(npl); + npl.os << endl; + } + for (auto e : this->elements) { + e->printTo(npl); + } + pl.os << pl.indent << "}" << endl; + } + + template + AbstractGraphI::~AbstractGraph() { + for (auto e : this->elements) + delete e; + } + + + template + SubGraphI &AbstractGraphI::addSubGraph(strtype name, bool cluster, strtype lab) { + if (cluster && name.find(strFromLit("cluster_")) != 0) + name = strFromLit("cluster_") + name; + if (lab.length() > 0) + lab = quoteChar + lab + quoteChar; + elements.push_back(new SubGraphI(*this, name, lab)); + return static_cast(*elements.back()); + } + + template + NodeI &AbstractGraphI::addNode(strtype id, strtype lab, bool forcenew) { + if (nodes.find(id) != nodes.end()) { + if (forcenew) + throw runtime_error("Node ID conflict : "+ strFromLit(id.c_str())); + else + return static_cast(*nodes.at(id)); + } + if (lab.length() > 0) + lab = quoteChar + lab + quoteChar; + elements.push_back(new NodeI(*this, id, lab)); + nodes[id] = static_cast(elements.back()); + return static_cast(*elements.back()); + } + + template + EdgeI &AbstractGraphI::addEdge(NodeI &n1, NodeI &n2, strtype lab) { + if (lab.length() > 0) + lab = quoteChar + lab + quoteChar; + elements.push_back(new EdgeI(*this, n1, n2, lab)); + return static_cast(*elements.back()); + } + + template + bool AbstractGraphI::hasNode(strtype id) { + return nodes.find(id) != nodes.end(); + } + + template + NodeI &AbstractGraphI::getNode(strtype id) { + return *nodes.at(id); + } + + template + ostreamtype &operator<<(ostreamtype &os, const GraphI &g) { + g.printGraphTo({os, strtype()}); + return os; + } + + template + const GvAttributesI &AbstractGraphI::getAttrsT(AttrType t) const { + switch(t) { + case AttrType::NODE: + return NAttrs; + case AttrType::EDGE: + return EAttrs; + case AttrType::GRAPH: + return GAttrs; + default: +#ifdef __GNUC__ + __builtin_unreachable(); +#else + return GAttrs; +#endif + } + } + + template + GvAttributesI &AbstractGraphI::getAttrsT(AttrType t) { + switch(t) { + case AttrType::NODE: + return NAttrs; + case AttrType::EDGE: + return EAttrs; + case AttrType::GRAPH: + return GAttrs; + default: +#ifdef __GNUC__ + __builtin_unreachable(); +#else + return GAttrs; +#endif + } + } + + template + strtype GraphI::getKeyword() const { + return strFromLit(directed ? "digraph" : "graph"); + } + + template + strtype SubGraphI::getKeyword() const { + return strFromLit("subgraph"); + } + + template + SubGraphI::SubGraph(AbstractGraphI &g, strtype name, strtype lab) : + AbstractGraphI(name), + ElementI(g) { + if (lab.length() > 0) + set(AttrType::GRAPH, strFromLit("label"), lab); + } + + string toCharString(basic_string &&str) { + wstring_convert> converter; + return converter.to_bytes(str); + } + + string toCharString(basic_string &&str) { + return str; + } + + template + int renderToFile(GraphI &g, string layout, string format, string file) { + static const char *GUIFormats[] = {"x11", "xlib", "gtk"}; + static const locale loc; + char *frmt = new char[format.length()+1]; + // Convert to lowercase + for (size_t i = 0; i < format.length(); i ++) + frmt[i] = use_facet>(loc).tolower(format[i]); + frmt[format.length()] = '\0'; + + bool isGUI = false; + for (const char* f : GUIFormats) + if (strcmp(f, frmt) == 0) + isGUI = true; + + if (!isGUI) { + if (file.length() == 0) { + file = string("-ooutput.")+ format; + } else + file = "-o"+ file; + } + delete[] frmt; + + basic_ostringstream stream; + stream << g; + + string buf = toCharString(stream.str()); + + auto cmd = string("dot ")+ file +" -T"+ format+ " -K"+ layout; + FILE *fd = fopen(cmd.c_str(), "w"); + fwrite(buf.c_str(), sizeof(chartype), buf.length(), fd); + fflush(fd); + return fclose(fd); + } + + template class AbstractGraph; + template class Graph; + template class Element; + template class Node; + template class Edge; + template class SubGraph; + template basic_ostream &operator<< + (basic_ostream &os, const Graph &g); + template int renderToFile + (Graph &g, string layout, string format, string file); + + template class AbstractGraph; + template class Graph; + template class Element; + template class Node; + template class Edge; + template class SubGraph; + template basic_ostream &operator<< + (basic_ostream &os, const Graph &g); + template int renderToFile + (Graph &g, string layout, string format, std::string file); +} diff --git a/utils/aerodynamics_2_graphviz/gvpp.hpp b/utils/aerodynamics_2_graphviz/gvpp.hpp new file mode 100644 index 0000000000..058d6477c1 --- /dev/null +++ b/utils/aerodynamics_2_graphviz/gvpp.hpp @@ -0,0 +1,228 @@ +#include +#include +#include +#include +#include +#include + +namespace gvpp { + enum class AttrType { NODE, EDGE, GRAPH }; + + #define ostreamtype std::basic_ostream + #define strtype std::basic_string + + #define TOWSTRING(x) L##x + #define CWSTR(C,STR) gvpp::strFromLit(STR, L##STR) + + template + inline const CharT *strFromLit(const char *str, const wchar_t *wstr); + + template + std::basic_string strFromLit(const CharFrom *str); + + template<> + inline const char *strFromLit(const char *str, const wchar_t *wstr) { return str; } + template<> + inline const wchar_t *strFromLit(const char *str, const wchar_t *wstr) { return wstr; } + + template<> + inline std::string strFromLit(const char *str) { return str; } + template<> + inline std::wstring strFromLit(const wchar_t *wstr) { return wstr; } + + template + struct printLine { + ostreamtype &os; + strtype indent; + }; + + //template using printLine = struct printLine; + + + template class AbstractGraph; + template class Element; + template class Graph; + template class SubGraph; + template class Node; + template class Edge; + + #define ElementT Element + #define AbstractGraphT AbstractGraph + #define GraphT Graph + #define SubGraphT SubGraph + #define NodeT Node + #define EdgeT Edge + #define GvAttributesT GvAttributes + #define printLineT printLine + + template + class GvAttributes : public std::map { + public: + void printTo(printLineT pl) const; + }; + + template + class AbstractGraph { + friend class ElementT; + friend class EdgeT; + friend class GraphT; + friend class SubGraphT; + public: + typedef chartype chartype_t; + AbstractGraph(strtype name) : name(name) {} + AbstractGraph(const AbstractGraph &g) = delete; + ~AbstractGraph(); + virtual bool isDirected() const = 0; + strtype getName() const { return name; } + + virtual const GvAttributesT &getAttributes(AttrType t) const { return getAttrsT(t); } + virtual strtype get(AttrType t, strtype att) const { return getAttrsT(t).at(att); } + virtual bool has(AttrType t, strtype att) const { return getAttrsT(t).find(att) != getAttrsT(t).end(); } + virtual AbstractGraphT &set(AttrType t, strtype att, strtype val) + { getAttrsT(t)[att] = val; return *this; } + + SubGraphT &addSubGraph(strtype name, bool cluster = false, + strtype label = CWSTR(chartype,"")); + NodeT &addNode(strtype id, strtype lab = strtype(), bool forcenew=true); + EdgeT &addEdge(NodeT &n1, NodeT &n2, strtype lab = strtype()); + bool hasNode(strtype id); + NodeT &getNode(strtype id); + + bool hasSubGraph(strtype id); + SubGraphT &getSubGraph(strtype id); + + size_t size() { return elements.size(); } + void printGraphTo(printLineT pl) const; + + protected: + virtual GraphT &getRoot() = 0; + GvAttributesT &getAttrsT(AttrType t); + const GvAttributesT &getAttrsT(AttrType t) const; + private: + std::map nodes; + std::list elements; + strtype name; + virtual strtype getKeyword() const = 0; + GvAttributesT GAttrs, NAttrs, EAttrs; + }; + + template + class Element { + friend class AbstractGraphT; + public: + Element(AbstractGraphT& parent) : parent(parent) {} + Element(const Element &e) = delete; + virtual ~Element() {}; + AbstractGraphT &getParent() const { return parent; } + virtual GraphT &getRootGraph() const { return parent.getRoot(); } + virtual const GvAttributesT &getAttributes() const { return getAttrs(); } + virtual strtype get(strtype att) const { return getAttrs().at(att); } + virtual bool has(strtype att) const { return getAttrs().find(att) != getAttrs().end(); } + virtual ElementT &set(strtype att, strtype val) { getAttrs()[att] = val; return *this; } + strtype &operator[](const strtype& k) { return getAttrs()[k]; } + strtype &operator[](strtype&& k) { return getAttrs()[k]; } + protected: + virtual void printTo(printLineT pl) const = 0; + virtual GvAttributesT &getAttrs() { return attrs; } + virtual const GvAttributesT &getAttrs() const { return attrs; } + private: + GvAttributesT attrs; + AbstractGraphT &parent; + }; + + template + class Node : public ElementT { + friend class AbstractGraphT; + public: + const strtype getId() const { return id; } + virtual Node &set(strtype att, strtype val) override + { ElementT::set(att, val); return *this; } + protected: + void printTo(printLineT pl) const; + private: + Node(AbstractGraphT &g, strtype id, strtype lab) : ElementT(g), id(id) { + if (lab.length() > 0) + (*this)[CWSTR(chartype,"label")] = lab; + } + strtype id; + }; + + template + class Edge : public std::pair, public ElementT { + friend class AbstractGraphT; + public: + Edge(AbstractGraphT &g, NodeT &n1, NodeT &n2, strtype lab) : + std::pair(n1, n2), ElementT(g) + { if (lab.length() > 0) set(CWSTR(chartype,"label"), lab); } + NodeT& getFrom() const { return std::get<0>(*this); } + NodeT& getTo() const { return std::get<1>(*this); } + virtual EdgeT &set(strtype att, strtype val) override + { ElementT::set(att, val); return *this; } + protected: + void printTo(printLineT pl) const; + }; + + template + class SubGraph : public AbstractGraphT, public ElementT { + friend class AbstractGraphT; + public: + bool isCluster() const { return cluster; } + bool isDirected() const override { return this->getParent().isDirected(); } + const GvAttributesT &getAttributes(AttrType t) const override + { return AbstractGraphT::getAttributes(t); } + strtype get(AttrType t, strtype att) const override + { return AbstractGraphT::get(t, att); } + bool has(AttrType t, strtype att) const override + { return this->getAttrsT(t).find(att) != this->getAttrsT(t).end(); } + SubGraphT &set(AttrType t, strtype att, strtype val) override + { AbstractGraphT::set(t, att, val); return *this; } + + const GvAttributesT &getAttributes() const override + { return AbstractGraphT::getAttributes(AttrType::GRAPH); } + strtype get(strtype att) const override + { return AbstractGraphT::get(AttrType::GRAPH, att); } + bool has(strtype att) const override + { return AbstractGraphT::has(AttrType::GRAPH, att); } + //SubGraph &set(strtype att, strtype val) override + // { AbstractGraphT::set(AttrType::GRAPH, att, val); return *this; } + protected: + GraphT &getRoot() override { return this->getRootGraph(); } + GvAttributesT &getAttrs() override { return this->getAttrsT(AttrType::GRAPH); }; + const GvAttributesT &getAttrs() const override { return this->getAttrsT(AttrType::GRAPH); }; + void printTo(printLineT pl) const override { this->printGraphTo(pl); } + private: + SubGraph(AbstractGraphT &g, strtype name, strtype label); + bool cluster; + strtype getKeyword() const override; + }; + + template + class Graph : public AbstractGraphT { + public: + Graph(bool dir = true, strtype name = strtype()) : AbstractGraphT(name), + directed(dir) {} + bool isDirected() const override { return directed; } + protected: + Graph &getRoot() override { return *this; } + private: + bool directed; + strtype getKeyword() const override; + }; + + template + ostreamtype &operator<<(ostreamtype&, const GraphT&); + template + int renderToFile(GraphT &g, std::string layout, std::string format, std::string file = ""); + template + inline int renderToScreen(GraphT &g, std::string layout) { return renderToFile(g, layout, "x11"); } +} + +#undef ElementT +#undef AbstractGraphT +#undef GraphT +#undef SubGraphT +#undef NodeT +#undef EdgeT +#undef ostreamtype +#undef strtype + diff --git a/utils/aerodynamics_2_graphviz/main.cpp b/utils/aerodynamics_2_graphviz/main.cpp new file mode 100644 index 0000000000..2ba81f433e --- /dev/null +++ b/utils/aerodynamics_2_graphviz/main.cpp @@ -0,0 +1,198 @@ +using namespace std; + +#include "aerodynamics_2_graphviz.h" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +GLOBAL DATA +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +SGPath RootDir; +SGPath ScriptName; +string AircraftName; +string outputfile; +string imagepath; +bool show_table_png; +std::shared_ptr FDMExec; +aerodynamics_2_graphviz* viz; +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +void PrintHelp(void) +{ + cout << endl << " aerodynamics_2_graphviz version " << viz->GetVersion() << endl << endl; + cout << endl << " JSBSim version " << FDMExec->GetVersion() << endl << endl; + cout << " Usage: aerodynamics_2_graphviz [script file name] [output file names] " << endl << endl; + cout << " options:" << endl; + cout << " --help returns this message" << endl; + cout << " --outputfile= sets (overrides) the name of the output file" << endl; + cout << " --root= specifies the JSBSim root directory (where aircraft/, engine/, etc. reside)" << endl; + cout << " --aircraft= specifies the name of the aircraft to be modeled" << endl; + cout << " --script= specifies a script to run" << endl; + cout << " --show_table_png=on/off specifies whether show table png" << endl; + cout << " --imagepath= specifies table png root directory" << endl; + + cout << " NOTE: There can be no spaces around the = sign when" << endl; + cout << " an option is followed by a filename" << endl << endl; +} + +#define gripe cerr << "Option '" << keyword \ + << "' requires a value, as in '" \ + << keyword << "=something'" << endl << endl;/**/ + +bool options(int count, char** arg) +{ + int i; + bool result = true; + + if (count == 1) { + PrintHelp(); + exit(0); + } + + RootDir = SGPath::fromEnv("JSBSim_ROOT"); + + cout.setf(ios_base::fixed); + + for (i = 1; i < count; i++) { + string argument = string(arg[i]); + string keyword(argument); + string value(""); + string::size_type n = argument.find("="); + + if (n != string::npos && n > 0) { + keyword = argument.substr(0, n); + value = argument.substr(n + 1); + } + + if (keyword == "--help") { + PrintHelp(); + exit(0); + } + else if (keyword == "--outputfile") { + if (n != string::npos) { + outputfile = value.c_str(); + } + else { + gripe; + exit(1); + } + } + else if (keyword == "--root") { + if (n != string::npos) { + RootDir = SGPath::fromLocal8Bit(value.c_str()); + } + else { + gripe; + exit(1); + } + } + else if (keyword == "--aircraft") { + if (n != string::npos) { + AircraftName = value; + } + else { + gripe; + exit(1); + } + } + else if (keyword == "--script") { + if (n != string::npos) { + ScriptName = SGPath::fromLocal8Bit(value.c_str()); + } + else { + gripe; + exit(1); + } + } + else if (keyword == "--show_table_png") { + if (n != string::npos) { + if (value == "on") { + show_table_png = true; + } + else { + show_table_png = false; + } + } + else { + gripe; + exit(1); + } + } + else if (keyword == "--imagepath") { + if (n != string::npos) { + imagepath = value; + } + else { + gripe; + exit(1); + } + } + else //Unknown keyword so print the help file, the bad keyword and abort + { + PrintHelp(); + cerr << "The argument \"" << keyword << "\" cannot be interpreted as a file name or option." << endl; + exit(1); + } + + } + + // Post-processing for script options. check for incompatible options. + + if (!ScriptName.isNull() && !AircraftName.empty()) { + cerr << "You cannot specify an aircraft file with a script." << endl; + result = false; + } + + return result; + +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +int main(int argc, char* argv[]) +{ + bool result = false, success; + success = options(argc, argv); + if (!success) { + PrintHelp(); + exit(-1); + } + + // *** SET UP JSBSIM *** // + FDMExec = make_shared(); + FDMExec->SetRootDir(RootDir); + FDMExec->SetAircraftPath(SGPath("aircraft")); + FDMExec->SetEnginePath(SGPath("engine")); + FDMExec->SetSystemsPath(SGPath("systems")); + + // *** OPTION A: LOAD A SCRIPT, WHICH LOADS EVERYTHING ELSE *** // + if (!ScriptName.isNull()) { + + result = FDMExec->LoadScript(ScriptName); + + if (!result) { + cerr << "Script file " << ScriptName << " was not successfully loaded" << endl; + exit(-1); + } + + // *** OPTION B: LOAD AN AIRCRAFT *** // + } + else if (!AircraftName.empty()) { + + if (!FDMExec->LoadModel(SGPath("aircraft"), + SGPath("engine"), + SGPath("systems"), + AircraftName)) { + cerr << " JSBSim could not be started" << endl << endl; + exit(-1); + } + } + else { + cout << " No Aircraft or Script information given" << endl << endl; + exit(-1); + } + + viz = new aerodynamics_2_graphviz(); + viz->set_imagepath(imagepath); + viz->graph_jsbsim_fdm_aerodynamics(FDMExec, outputfile,show_table_png); +} \ No newline at end of file