flightgear/utils/openvsp/vsp2jsbsim.cpp
2022-10-20 20:29:11 +08:00

235 lines
7.0 KiB
C++

#include <iterator>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <vector>
#include <string>
#include <map>
#define DEG2RAD(a) (3.141592657*(a)/180.0)
// https://stackoverflow.com/questions/1120140/how-can-i-read-and-parse-csv-files-in-c
class CSVRow
{
public:
std::string_view operator[](std::size_t index) const
{
return std::string_view(&m_line[m_data[index] + 1], m_data[index + 1] - (m_data[index] + 1));
}
std::size_t size() const
{
return m_data.size() - 1;
}
void readNextRow(std::istream& str)
{
std::getline(str, m_line);
m_data.clear();
m_data.emplace_back(-1);
std::string::size_type pos = 0;
while((pos = m_line.find(',', pos)) != std::string::npos)
{
m_data.emplace_back(pos);
++pos;
}
// This checks for a trailing comma with no data after it.
pos = m_line.size();
m_data.emplace_back(pos);
}
private:
std::string m_line;
std::vector<int> m_data;
};
std::istream& operator>>(std::istream& str, CSVRow& data)
{
data.readNextRow(str);
return str;
}
class CSVIterator
{
public:
typedef std::input_iterator_tag iterator_category;
typedef CSVRow value_type;
typedef std::size_t difference_type;
typedef CSVRow* pointer;
typedef CSVRow& reference;
CSVIterator(std::istream& str) :m_str(str.good()?&str:NULL) { ++(*this); }
CSVIterator() :m_str(NULL) {}
// Pre Increment
CSVIterator& operator++() {if (m_str) { if (!((*m_str) >> m_row)){m_str = NULL;}}return *this;}
// Post increment
CSVIterator operator++(int) {CSVIterator tmp(*this);++(*this);return tmp;}
CSVRow const& operator*() const {return m_row;}
CSVRow const* operator->() const {return &m_row;}
bool operator==(CSVIterator const& rhs) {return ((this == &rhs) || ((this->m_str == NULL) && (rhs.m_str == NULL)));}
bool operator!=(CSVIterator const& rhs) {return !((*this) == rhs);}
private:
std::istream* m_str;
CSVRow m_row;
};
class CSVRange
{
std::istream& stream;
public:
CSVRange(std::istream& str)
: stream(str)
{}
CSVIterator begin() const {return CSVIterator{stream};}
CSVIterator end() const {return CSVIterator{};}
};
// https://stackoverflow.com/questions/17642882/c-2d-map-like-a-2d-array
template<typename T>
class Graph {
private:
typedef std::map<std::pair<size_t,size_t>, T> graph_type;
graph_type graph;
class SrcVertex {
private:
graph_type& graph;
size_t vert_src;
public:
SrcVertex(graph_type& graph): graph(graph) {}
T& operator[](size_t vert_dst) {
return graph[std::make_pair(vert_src, vert_dst)];
}
void set_vert_src(size_t vert_src) {
this->vert_src = vert_src;
}
} src_vertex_proxy;
public:
Graph(): src_vertex_proxy(graph) {}
SrcVertex& operator[](size_t vert_src) {
src_vertex_proxy.set_vert_src(vert_src);
return src_vertex_proxy;
}
};
// own code by Erik Hofman
class JSBSim
{
public:
std::string name;
std::vector<int> date;
std::vector<int> time;
std::vector<double> a, b;
Graph<double> CDi, CDo, CDtot, CDtrefftz;
Graph<double> CFx, CFy, CFz, CL;
Graph<double> CMx, CMy, CMz;
JSBSim(std::istream& file)
{
// every section contains 39 lines
size_t alpha, beta;
for(auto& row: CSVRange(file))
{
if (row[0] == "Results_Name") {
if (row[1] != "VSPAERO_History") break;
name = row[1];
}
char *end;
const char *start = row[row.size()-1].data();
double d = std::strtod(start, &end);
if (row[0] == "Alpha") {
alpha = d*100;
if (!a.size() || d > a.back()) a.push_back(d);
} else if (row[0] == "Beta") {
beta = d*100;
if (!b.size() || d > b.back()) b.push_back(d);
} if (row[0] == "CDi") {
CDi[alpha][beta] = d;
} if (row[0] == "CDo") {
CDo[alpha][beta] = d;
} if (row[0] == "CDtot") {
CDtot[alpha][beta] = d;
} if (row[0] == "CDtrefftz") {
CDtrefftz[alpha][beta] = d;
} if (row[0] == "CFx") {
CFx[alpha][beta] = d;
} if (row[0] == "CFy") {
CFy[alpha][beta] = d;
} if (row[0] == "CFz") {
CFz[alpha][beta] = d;
} if (row[0] == "CL") {
CL[alpha][beta] = d;
} if (row[0] == "CMx") {
CMx[alpha][beta] = d;
} if (row[0] == "CMy") {
CMy[alpha][beta] = d;
} if (row[0] == "CMz") {
CMz[alpha][beta] = d;
}
}
}
~JSBSim() = default;
void print_table(Graph<double>& type, std::string name) {
std::cout << name << std::endl;
std::cout << std::setw(10) << " ";
for (int j=0; j<b.size(); ++j) {
std::cout << std::setw(8) << DEG2RAD(b[j]);
}
std::cout << std::endl;
for (int i=0; i<a.size(); ++i) {
std::cout << std::setw(8) << DEG2RAD(a[i]) << " ";
for (int j=0; j<b.size(); ++j) {
std::cout << std::setw(8) << type[a[i]*100][b[j]*100];
}
std::cout << std::endl;
}
std::cout << std::endl;
}
private:
template <typename T>
void push_vector(std::vector<T>& dst, const CSVRow& row) {
for (int i=1; i<row.size(); ++i)
{
char *end;
const char *start = row[i].data();
double d = std::strtod(start, &end);
dst.push_back(d);
}
}
};
int main(int argc, char *argv[])
{
std::ifstream file(argv[1]);
JSBSim jsb(file);
std::cout << "Name: " << jsb.name << std::endl;
std::cout << std::fixed << std::showpoint << std::setprecision(3);
std::cout << "LIFT:" << std::endl;
jsb.print_table(jsb.CL, "CL");
std::cout << "DRAG:" << std::endl;
jsb.print_table(jsb.CDi, "CDi (Induced Drag)");
jsb.print_table(jsb.CDo, "CDo (Parasitic Drag)");
jsb.print_table(jsb.CDtot, "CDtot (CDi + CDo)");
jsb.print_table(jsb.CDtrefftz, "CDtrefftz (Trefftz Method)");
std::cout << "FORCES:" << std::endl;
jsb.print_table(jsb.CFx, "CFx (Drag)");
jsb.print_table(jsb.CFy, "CFy (Side)");
jsb.print_table(jsb.CFz, "CFz (Lift)");
std::cout << "MOMENTS:" << std::endl;
jsb.print_table(jsb.CMx, "CMx (Roll)");
jsb.print_table(jsb.CMy, "CMy (Pitch)");
jsb.print_table(jsb.CMz, "CMz (Yaw)");
}