You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
421 lines
13 KiB
C++
421 lines
13 KiB
C++
/*------------------------------------------------------------------------------
|
|
* Copyright (c) 2023 by Bai Bing (seread@163.com)
|
|
* See COPYING file for copying and redistribution conditions.
|
|
*
|
|
* Alians IT Studio.
|
|
*----------------------------------------------------------------------------*/
|
|
#pragma once
|
|
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <map>
|
|
#include <regex>
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "_Define.h"
|
|
#include "core/UUID.h"
|
|
#include "utils/Misc.h"
|
|
#include "ASPoint.h"
|
|
|
|
namespace ais
|
|
{
|
|
template <typename PT = ais::Point>
|
|
class AIS_EXPORT Discontinuity
|
|
{
|
|
public:
|
|
Discontinuity() = default;
|
|
Discontinuity(const char *name_, std::vector<PT> points_) : name(name_), points(points_)
|
|
{
|
|
build_polygon_box();
|
|
};
|
|
|
|
Discontinuity(const char *contents)
|
|
{
|
|
std::istringstream ss(contents);
|
|
std::vector<std::string> lines;
|
|
for (std::string line; std::getline(ss, line);)
|
|
{
|
|
if (!line.empty())
|
|
lines.emplace_back(line);
|
|
}
|
|
|
|
if (!lines.empty())
|
|
{
|
|
auto header = lines[0];
|
|
auto tokens = ais::str_split_all(header, ",");
|
|
|
|
size_t pointCount = std::atoi(tokens[0].c_str());
|
|
bool nodataFlags = bool(std::atoi(tokens[1].c_str()));
|
|
if (pointCount == lines.size() - 1)
|
|
{
|
|
// ensure the header information is correct
|
|
name = tokens.size() > 2 ? tokens[2] : ais::uuid();
|
|
|
|
for (int i = 0; i < pointCount; i++)
|
|
{
|
|
points.emplace_back(PT(lines[i + 1].c_str()));
|
|
}
|
|
}
|
|
}
|
|
|
|
build_polygon_box();
|
|
}
|
|
|
|
~Discontinuity() = default;
|
|
|
|
inline virtual std::string type() const { return "Discontinuity"; }
|
|
std::string name;
|
|
std::vector<PT> points;
|
|
std::vector<PT> polygon; // points which can contain an enclosed polygon
|
|
std::vector<ais::Point> box; // outside box which to help quickly test for grid iteration
|
|
|
|
void build_polygon_box()
|
|
{
|
|
// build the polygon points if exists
|
|
auto i = points.begin();
|
|
auto di = points.end();
|
|
for (; i < di; ++i)
|
|
{
|
|
for (auto j = i + 1; j != di; ++j)
|
|
{
|
|
if (*i == *j)
|
|
{
|
|
di = j;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (di != points.end())
|
|
{
|
|
// the polygon begin and end point are same for an enclosed area
|
|
polygon = std::vector<PT>(i, di + 1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// build box for quick test
|
|
if (!points.empty())
|
|
{
|
|
auto xMinMax = getMinMax(getAxisValues(points, Axis3DType::X));
|
|
auto yMinMax = getMinMax(getAxisValues(points, Axis3DType::Y));
|
|
box = std::vector<ais::Point>{
|
|
{xMinMax.first, yMinMax.first},
|
|
{xMinMax.first, yMinMax.second},
|
|
{xMinMax.second, yMinMax.second},
|
|
{xMinMax.second, yMinMax.first},
|
|
{xMinMax.first, yMinMax.first},
|
|
};
|
|
}
|
|
}
|
|
|
|
const std::string str() const
|
|
{
|
|
std::stringstream ss;
|
|
ss << type() << ": " << name << std::endl;
|
|
ss << "-----------------------------------------------" << std::endl;
|
|
for (auto &p : points)
|
|
{
|
|
ss << p;
|
|
if (std::find(points.begin(), points.end(), p) != points.end())
|
|
ss << " P";
|
|
ss << std::endl;
|
|
}
|
|
|
|
return ss.str();
|
|
}
|
|
};
|
|
|
|
template <typename PT = ais::Point>
|
|
class AIS_EXPORT DiscontinuityFile
|
|
{
|
|
public:
|
|
DiscontinuityFile() = default;
|
|
DiscontinuityFile(const char *filename)
|
|
{
|
|
try
|
|
{
|
|
load(filename);
|
|
}
|
|
catch (const std::exception &e)
|
|
{
|
|
std::cerr << "Error loading " << filename << ", " << e.what() << std::endl;
|
|
}
|
|
}
|
|
|
|
//============================================================================
|
|
///
|
|
/// @param filename
|
|
///
|
|
/// @return count of loaded breaklines
|
|
///
|
|
virtual size_t load(const char *filename)
|
|
{
|
|
size_t lineCount = 0;
|
|
|
|
std::filesystem::path path(filename);
|
|
|
|
if (!std::filesystem::exists(filename))
|
|
{
|
|
std::string msg(filename);
|
|
msg += " is not existed!";
|
|
THROW_INVALID_ARGUMENT(msg.c_str());
|
|
}
|
|
|
|
std::string ext = path.extension().string();
|
|
ext = ais::tolower(ext);
|
|
|
|
if (ext == ".bln")
|
|
{
|
|
lineCount = load_bln_file(filename);
|
|
}
|
|
else if (ext == ".dfd")
|
|
{
|
|
lineCount = load_dfd_file(filename);
|
|
}
|
|
else
|
|
{
|
|
lineCount = load_dat_file(filename);
|
|
}
|
|
|
|
return lineCount;
|
|
}
|
|
|
|
inline virtual void clear() { discontinuities.clear(); };
|
|
|
|
ais::Discontinuity<PT> &operator[](const char *name) const { return discontinuities[name]; };
|
|
|
|
std::map<std::string, Discontinuity<PT>> discontinuities;
|
|
|
|
private:
|
|
virtual size_t load_bln_file(const char *filename)
|
|
{
|
|
std::ifstream file(filename);
|
|
if (!file.good())
|
|
{
|
|
std::string msg("Can't open file ");
|
|
msg += filename;
|
|
THROW_INVALID_ARGUMENT(msg.c_str());
|
|
}
|
|
|
|
bool inLine = false;
|
|
std::smatch m;
|
|
std::regex regHeader("^([\\d]+),([\\d]?)(.*?)$");
|
|
std::regex regexLine("([\\d\\-\\.]+)");
|
|
std::stringstream ss;
|
|
std::string line = "";
|
|
while (getline(file, line))
|
|
{
|
|
if (line[0] == '#' || line.empty())
|
|
{
|
|
|
|
// close current line information
|
|
inLine = false;
|
|
// transfer line informaiton
|
|
auto s = ss.str();
|
|
if (s.empty())
|
|
continue;
|
|
|
|
ais::Discontinuity<PT> discontinuity(s.c_str());
|
|
if (!discontinuity.points.empty())
|
|
{
|
|
discontinuities[discontinuity.name] = discontinuity;
|
|
}
|
|
ss.str("");
|
|
|
|
// skip comments and empty lines
|
|
continue;
|
|
}
|
|
|
|
if (!inLine && std::regex_match(line, m, regHeader))
|
|
{
|
|
// capture header line
|
|
inLine = true;
|
|
ss << line << std::endl;
|
|
continue;
|
|
}
|
|
|
|
if (inLine && std::regex_search(line, m, regexLine))
|
|
{
|
|
ss << line << std::endl;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// for finally line
|
|
auto s = ss.str();
|
|
if (!s.empty())
|
|
{
|
|
ais::Discontinuity<PT> discontinuity(s.c_str());
|
|
if (!discontinuity.points.empty())
|
|
{
|
|
discontinuities[discontinuity.name] = discontinuity;
|
|
}
|
|
}
|
|
|
|
return discontinuities.size();
|
|
}
|
|
|
|
virtual size_t load_dfd_file(const char *filename)
|
|
{
|
|
std::ifstream file(filename);
|
|
if (!file.good())
|
|
{
|
|
std::string msg("Can't open file ");
|
|
msg += filename;
|
|
THROW_INVALID_ARGUMENT(msg.c_str());
|
|
}
|
|
|
|
std::vector<std::string> skipRegexStrings = {"version", "HowToViewCurve", "Property", "Solid", "NoDraw", "#", "NameIn", "Times_New_Roman"};
|
|
|
|
bool inLine = false;
|
|
std::stringstream ss;
|
|
ss << std::fixed << std::setprecision(4);
|
|
std::string line = "";
|
|
size_t linePointCount = 0;
|
|
std::string lineName;
|
|
while (getline(file, line))
|
|
{
|
|
std::smatch m;
|
|
|
|
for (auto &rex : skipRegexStrings)
|
|
{
|
|
std::regex r(rex, std::regex_constants::icase);
|
|
if (std::regex_search(line, m, r))
|
|
{
|
|
// skip comments and empty lines
|
|
continue;
|
|
}
|
|
}
|
|
|
|
std::regex regexHeader("^pline(.*)", std::regex_constants::icase);
|
|
if (std::regex_search(line, m, regexHeader))
|
|
{
|
|
// line start
|
|
inLine = true;
|
|
lineName = m[1].str().substr(1);
|
|
linePointCount = 0;
|
|
ss.str(std::string());
|
|
continue;
|
|
}
|
|
|
|
std::regex regexLine("([\\d\\-\\.]+)");
|
|
if (inLine && std::regex_search(line, m, regexLine))
|
|
{
|
|
// line point information
|
|
ss << line << std::endl;
|
|
linePointCount++;
|
|
continue;
|
|
}
|
|
|
|
if (inLine && line.empty())
|
|
{
|
|
// line end and build discontinuity informaiton
|
|
std::string s = std::to_string(linePointCount) + ",1," + lineName + "\n";
|
|
s += ss.str();
|
|
|
|
// reset line information
|
|
inLine = false;
|
|
linePointCount = 0;
|
|
lineName = "";
|
|
ss.str(std::string());
|
|
|
|
// covert discontinuity to object
|
|
ais::Discontinuity<PT> discontinuity(s.c_str());
|
|
if (!discontinuity.points.empty())
|
|
{
|
|
discontinuities.emplace(discontinuity.name, discontinuity);
|
|
}
|
|
}
|
|
}
|
|
|
|
return discontinuities.size();
|
|
}
|
|
|
|
virtual size_t load_dat_file(const char *filename)
|
|
{
|
|
std::ifstream file(filename);
|
|
if (!file.good())
|
|
{
|
|
std::string msg("Can't open file ");
|
|
msg += filename;
|
|
THROW_INVALID_ARGUMENT(msg.c_str());
|
|
}
|
|
|
|
bool inLine = false;
|
|
std::stringstream ss;
|
|
ss << std::fixed << std::setprecision(4);
|
|
std::string line = "";
|
|
size_t linePointCount = 0;
|
|
std::string lineName;
|
|
while (getline(file, line))
|
|
{
|
|
if (line[0] == '#' || line.empty())
|
|
{
|
|
// skip comments and empty lines
|
|
continue;
|
|
}
|
|
|
|
auto tokens = ais::str_split_all(line, " ");
|
|
double x = 0, y = 0;
|
|
std::string flag;
|
|
std::string name;
|
|
if (tokens.size() != 4)
|
|
{
|
|
// skip line which may incorrectly
|
|
continue;
|
|
}
|
|
|
|
// line infomation
|
|
x = std::stod(tokens[0]);
|
|
y = std::stod(tokens[1]);
|
|
flag = tokens[2];
|
|
name = tokens[3];
|
|
|
|
if (!inLine && flag == "6")
|
|
{
|
|
// line start
|
|
inLine = true;
|
|
lineName = name;
|
|
ss.str(std::string());
|
|
|
|
// put point to line content
|
|
ss << x << "," << y << std::endl;
|
|
linePointCount = 1;
|
|
}
|
|
else if (inLine && flag == "7" && name == lineName)
|
|
{
|
|
// in line, put point to line content
|
|
ss << x << "," << y << std::endl;
|
|
linePointCount++;
|
|
}
|
|
else if (inLine && flag == "8" && name == lineName)
|
|
{
|
|
// line stop
|
|
ss << x << "," << y << std::endl;
|
|
linePointCount++;
|
|
inLine = false;
|
|
|
|
// build discontinuity informaiton
|
|
std::string s = std::to_string(linePointCount) + ",1," + lineName + "\n";
|
|
s += ss.str();
|
|
|
|
// reset line information
|
|
linePointCount = 0;
|
|
lineName = "";
|
|
ss.str(std::string());
|
|
|
|
// covert discontinuity to object
|
|
ais::Discontinuity<PT> discontinuity(s.c_str());
|
|
if (!discontinuity.points.empty())
|
|
{
|
|
discontinuities.emplace(discontinuity.name, discontinuity);
|
|
}
|
|
}
|
|
}
|
|
return discontinuities.size();
|
|
}
|
|
};
|
|
} |