version update

This commit is contained in:
2025-01-15 22:42:06 +08:00
parent d9ae10d0e4
commit b0ab1fe089
14 changed files with 307 additions and 114 deletions

View File

@@ -6,18 +6,19 @@ void disp_help(char* proname){
" -d<minimal-depth>/<maximal-depth> \
[-r'WGS84'|'Earth'|'Moon'|<equator-radius>/<pole-radius>|<equator_radius>,<flat-rate>] \
[-o<orient-longitude>/<orient-latitude>] \
[-m<output-msh-filename>] \
[-v<output-vert-loc-filename>] \
[-t<output-tri-cen-filename>] \
[-n<output-tri-neg-filename>] \
[-p<control-point-filename>] \
[-l<control-line-filename>] \
[-g<control-poly-filename>] \
[-c<control-circle-filename>] \
[-s<outline-shape-filename>] \
[-k<hole-shape-filename>] \
[-m<output-msh-file>] \
[-v<output-vert-loc-file>] \
[-t<output-tri-cen-file>] \
[-n<output-tri-neg-file>] \
[-p<control-point-file>] \
[-l<control-line-file>] \
[-g<control-poly-filen>] \
[-c<control-circle-file>] \
[-s<outline-shape-file>] \
[-k<hole-shape-file>] \
[-z<control-topography-file>] \
[-h]";
clog << proname << " - v1.3 A generator of the Spherical Triangular Tessellation (STT)." << endl;
clog << proname << " - v1.4 A generator of the Spherical Triangular Tessellation (STT)." << endl;
clog << "Usage: " << exe_name << endl;
clog << "Options:" << endl;
clog << "\t-d\tMinimal and maximal quad-tree depths of the output STT." << endl;
@@ -33,6 +34,7 @@ void disp_help(char* proname){
clog << "\t-c\tInput control circle location(.txt) filename." << endl;
clog << "\t-s\tInput outline polygon location(.txt) filename." << endl;
clog << "\t-k\tInput hole polygon location(.txt) filename." << endl;
clog << "\t-z\tInput topography(.txt) filename." << endl;
clog << "\t-h\tShow help information." << endl;
}
@@ -50,9 +52,10 @@ int main(int argc, char* argv[]){
9 -> input filename for polygon constraints
10-> input filename for circle constraints
11-> input filename for outline shape constraints
12-> input filename for hole shape constraints*/
char input_options[13][1024];
for (int i = 0; i < 13; i++){
12-> input filename for hole shape constraints
13-> input filename for topography constraints*/
char input_options[14][1024];
for (int i = 0; i < 14; i++){
strcpy(input_options[i],"NULL");
}
@@ -63,7 +66,7 @@ int main(int argc, char* argv[]){
}
int curr, option_number;
while((curr = getopt(argc,argv,"hd:r:o:m:v:t:n:p:l:g:c:s:k:")) != -1){
while((curr = getopt(argc,argv,"hd:r:o:m:v:t:n:p:l:g:c:s:k:z:")) != -1){
// get option number
switch (curr){
case 'h': // show help information
@@ -94,6 +97,8 @@ int main(int argc, char* argv[]){
option_number =11; break;
case 'k':
option_number =12; break;
case 'z':
option_number =13; break;
case '?': //处理未定义或错误参数
if (optopt == 'd' || optopt == 'r' || optopt == 'o' || optopt == 'm' || optopt == 'n'
|| optopt == 'v' || optopt == 't' || optopt == 'p' || optopt == 'l'

View File

@@ -154,4 +154,20 @@ int LocalIndex(int id, Triangle t)
for (int i = 0; i < 3; i++)
if (id == t.ids[i]) return i;
return -1;
}
double data_std(const vector<double> &data)
{
if (data.size() == 0) return 0.0;
double sum = 0.0;
for (int i = 0; i < data.size(); i++)
sum += data[i];
double mean = sum / data.size();
double sq_sum = 0.0;
for (int i = 0; i < data.size(); i++)
sq_sum += (data[i] - mean)*(data[i] - mean);
return sqrt(sq_sum / data.size());
}

View File

@@ -59,6 +59,13 @@ struct ControlPoint{
};
typedef vector<ControlPoint> ControlPointArray;
struct ControlTopo{
int id = -1, max_depth = -1, physic_group = 0;
double minimal_resolution = DBL_MAX;
VertexArray vert; // verts for topo
vector<double> topo;
};
struct ControlLine{
int id = -1, max_depth = -1, physic_group = 0;
double minimal_resolution = -1.0;
@@ -89,4 +96,5 @@ Vertex RotateVertex(Vertex,Vertex,Vertex);
Cpoint LineCrossPlane(Cpoint,Cpoint,Cpoint);
string GetStringIndex(Vertex);
int LocalIndex(int,Triangle);
double data_std(const vector<double> &data);
#endif

View File

@@ -20,8 +20,8 @@ public:
int set_icosahedron_orient(char*);
int Routine(char [][1024]); // for a 2D array. you must specify enough dimensional information to make it unique
void InitialIcosahedron(double,Vertex); //初始化一个二十面体实例 需要给定一个默认半径值 二十面体顶点的经纬坐标 在init_para函数中调用
void CreateBranch(int,int,int,int,int,int,int,QuadTreeNode**); //创建分枝
void CreateTree(int,int,int,int,QuadTree*);//创建树
void CreateBranch(int,int,int,int,int,int,int,QuadTreeNode**,const ControlTopo&); //创建分枝
void CreateTree(int,int,int,int,QuadTree*,const ControlTopo&);//创建树
void DeleteTree(QuadTreeNode**);//清空整颗树
void ReturnLeaf(QuadTreeNode**);//返回叶子
void ReturnDepth(QuadTreeNode**,int);
@@ -34,6 +34,8 @@ public:
int InTriangleLine(QuadTreeNode*);//判断插入线是否穿过节点三角形 使用的是球面下的方法 直接矢量计算 注意因为球面上的特殊关系 两个点之间的夹角不能大于等于180度 因为球面上总是沿着最短路径走 而且通常我们指的也是最短路径
int InTrianglePolygon(QuadTreeNode*);//判断多边形与三角形的关系
int InTriangleCircle(QuadTreeNode*);//判断圆与三角形的关系
int InTriangleTopo(QuadTreeNode*, const ControlTopo& in_topo, double diff_threshold);//判断地形与三角形的关系
int InTriangleTopoSet(QuadTreeNode*, const ControlTopo& in_topo, ControlTopo& out_topo);
int OutPolyOutline(QuadTreeNode*);//判断多边形与三角形的关系 用于切割模型边界
int InPolyOutline(QuadTreeNode*);//判断多边形与三角形的关系 用于切割模型边界 挖洞
int OutputMshFile(char*,double,double);
@@ -43,6 +45,7 @@ public:
int GetControlPoint(char*); //读取额外的点
int GetControlCircle(char*); //读取额外的圆
int GetControlLine(char*,ControlLineArray&); // Get control line arrays
int GetControlTopography(char*); // Get control topography arrays
private:
// record input command line options for output records
string command_record_;
@@ -67,11 +70,15 @@ private:
// pointer array of the extracted quad-tree nodes returned according to conditions
QuadTreeNodePointerArray array_out_tri_pointer_;
// external constraint information (point, line, polygons, circles, outline polygons and hole polygons)
// we add control topo for v1.4
ControlTopo control_topo_;
ControlPointArray array_control_point_;
ControlCircleArray array_control_circle_;
ControlLineArray array_control_line_;
ControlLineArray array_control_polygon_;
ControlLineArray array_outline_polygon_;
ControlLineArray array_hole_polygon_;
// threshold for topography constraint
double topo_max_diff_;
};
#endif

View File

@@ -1,6 +1,7 @@
#include "stt_class.h"
void SttGenerator::CreateBranch(int upper_id,int order_id,int depth,int t_ids0,int t_ids1,int t_ids2,int phy_group,QuadTreeNode** node)
void SttGenerator::CreateBranch(int upper_id,int order_id,int depth,int t_ids0,int t_ids1,int t_ids2,
int phy_group,QuadTreeNode** node,const ControlTopo& in_topo)
{
Vertex local_vert[6];
QuadTreeNode* current_node;
@@ -14,12 +15,16 @@ void SttGenerator::CreateBranch(int upper_id,int order_id,int depth,int t_ids0,i
current_node->id = upper_id*10+order_id;//写入四叉树节点编号
current_node->depth = depth;//记录四叉树深度
ControlTopo out_topo;
InTriangleTopoSet(current_node, in_topo, out_topo);
//额外生长条件 满足其一即可生长 在局部加密模型的过程中 不同物理组的赋值顺序前后顺序为圈 多边形 线 点
if ((depth < tree_depth_ //基本生长条件 所有节点都能达到的深度
|| InTriangleCircle(current_node)
|| InTrianglePolygon(current_node)
|| InTriangleLine(current_node)
|| InTrianglePoint(current_node))
|| InTrianglePoint(current_node)
|| InTriangleTopo(current_node, out_topo, topo_max_diff_))
&& depth < max_depth_) //最大深度限制 所有节点不能超过的深度
{
ivd_ = map_id_vertex_.find(t_ids0);//利用map_ID映射找到四叉树节点的前三个点这三个节点是上一层四叉树产生的必然存在
@@ -52,10 +57,13 @@ void SttGenerator::CreateBranch(int upper_id,int order_id,int depth,int t_ids0,i
}
}
CreateBranch(current_node->id,1,depth+1,local_vert[0].id,local_vert[3].id,local_vert[5].id,current_node->tri.physic_group,&(current_node->children[0]));
CreateBranch(current_node->id,2,depth+1,local_vert[1].id,local_vert[4].id,local_vert[3].id,current_node->tri.physic_group,&(current_node->children[1]));
CreateBranch(current_node->id,3,depth+1,local_vert[2].id,local_vert[5].id,local_vert[4].id,current_node->tri.physic_group,&(current_node->children[2]));
CreateBranch(current_node->id,4,depth+1,local_vert[3].id,local_vert[4].id,local_vert[5].id,current_node->tri.physic_group,&(current_node->children[3]));
CreateBranch(current_node->id,1,depth+1,local_vert[0].id,local_vert[3].id,local_vert[5].id,current_node->tri.physic_group,&(current_node->children[0]), out_topo);
CreateBranch(current_node->id,2,depth+1,local_vert[1].id,local_vert[4].id,local_vert[3].id,current_node->tri.physic_group,&(current_node->children[1]), out_topo);
CreateBranch(current_node->id,3,depth+1,local_vert[2].id,local_vert[5].id,local_vert[4].id,current_node->tri.physic_group,&(current_node->children[2]), out_topo);
CreateBranch(current_node->id,4,depth+1,local_vert[3].id,local_vert[4].id,local_vert[5].id,current_node->tri.physic_group,&(current_node->children[3]), out_topo);
}
out_topo.vert.clear();
out_topo.topo.clear();
return;
}

View File

@@ -1,6 +1,7 @@
#include "stt_class.h"
void SttGenerator::CreateTree(int tree_id,int t_ids0,int t_ids1,int t_ids2,QuadTree* p_tree){
void SttGenerator::CreateTree(int tree_id,int t_ids0,int t_ids1,int t_ids2,
QuadTree* p_tree,const ControlTopo& in_topo){
if (max_depth_ == 0){
p_tree->root->id = 0;
p_tree->root->depth = 0;
@@ -12,8 +13,7 @@ void SttGenerator::CreateTree(int tree_id,int t_ids0,int t_ids1,int t_ids2,QuadT
p_tree->root->children[i] = nullptr;
}
}
else
{
CreateBranch(0,tree_id,0,t_ids0,t_ids1,t_ids2,0,&(p_tree->root));//以根节点开始创建四叉树
else{
CreateBranch(0,tree_id,0,t_ids0,t_ids1,t_ids2,0,&(p_tree->root),in_topo);//以根节点开始创建四叉树
}
}

View File

@@ -0,0 +1,45 @@
#include "stt_class.h"
int SttGenerator::GetControlTopography(char* filename)
{
double one_topo;
stringstream temp_ss;
string temp_str;
Vertex temp_vert;
ifstream infile;
if (!strcmp(filename,"NULL")) return 0;
if (OpenInfile(infile,filename)) return -1;
else{
while (getline(infile,temp_str)){
if (*(temp_str.begin()) == '#' || temp_str == "") continue;
else{
temp_ss = Str2Ss(temp_str);
temp_ss >> topo_max_diff_ >> control_topo_.max_depth >> control_topo_.minimal_resolution >> control_topo_.physic_group;
if (control_topo_.max_depth <= 0) control_topo_.max_depth = 1e+3; //这里直接给一个很大的深度值 节点深度一定小于这个值
if (control_topo_.minimal_resolution <= 0) control_topo_.minimal_resolution = -1.0; //这里直接给成-1
break;
}
}
while (getline(infile,temp_str)){
if (*(temp_str.begin()) == '#' || temp_str == "") continue;
else{
getline(infile,temp_str);
temp_ss = Str2Ss(temp_str);
if (temp_ss >> temp_vert.posis.lon >> temp_vert.posis.lat >> one_topo){
temp_vert.posis.rad = DefaultR;
temp_vert.id = control_topo_.vert.size();
temp_vert.posic = Sphere2Cartesian(temp_vert.posis);
control_topo_.vert.push_back(temp_vert);
control_topo_.topo.push_back(one_topo);
}
}
}
control_topo_.id = 0;
infile.close();
}
return 0;
}

View File

@@ -0,0 +1,47 @@
#include "stt_class.h"
int SttGenerator::InTriangleTopo(QuadTreeNode* node, const ControlTopo& in_topo, double diff_threshold){
//没有插入的地形 直接返回否
if (in_topo.vert.empty()){
return 0;
}
else{
int node_depth;
double node_resolution;
double max_topo = -1e+30, min_topo = 1e+30;
Triangle temp_tri;
for (int j = 0; j < 3; j++){
temp_tri.ids[j] = node->tri.ids[j];
}
node_depth = node->depth;
node_resolution = 0;
for (int i = 0; i < 3; i++){
node_resolution += acos(DotProduct(array_stt_vert_[temp_tri.ids[i]].posic,array_stt_vert_[temp_tri.ids[(i+1)%3]].posic)
/(ModuleLength(array_stt_vert_[temp_tri.ids[i]].posic)*ModuleLength(array_stt_vert_[temp_tri.ids[(i+1)%3]].posic)));
}
node_resolution = node_resolution*60/Pi;
// 将控制点的组别赋值给当前节点
node->tri.physic_group = in_topo.physic_group;
if (data_std(in_topo.topo) >= diff_threshold) return 1;
else return 0;
/*
for (int i = 0; i < in_topo.vert.size(); i++){
// 1. 允许的最大深度大于当前节点的深度
// 2. 允许的最小分辨率小于当前节点的分辨率
if (in_topo.max_depth >= node_depth && node_resolution >= in_topo.minimal_resolution){
// 统计符合条件的地形的最大值与最小值
if (in_topo.topo[i] > max_topo) max_topo = in_topo.topo[i];
if (in_topo.topo[i] < max_topo) min_topo = in_topo.topo[i];
}
}
if (std::abs(max_topo - min_topo) >= diff_threshold) return 1;
return 0;
*/
}
}

View File

@@ -0,0 +1,52 @@
#include "stt_class.h"
int SttGenerator::InTriangleTopoSet(QuadTreeNode* node, const ControlTopo& in_topo, ControlTopo& out_topo){
//没有插入的地形 直接返回否
if (in_topo.vert.empty()){
out_topo.vert.clear();
out_topo.topo.clear();
return 0;
}
else{
out_topo.vert.clear();
out_topo.topo.clear();
out_topo.max_depth = in_topo.max_depth;
out_topo.minimal_resolution = in_topo.minimal_resolution;
out_topo.physic_group = in_topo.physic_group;
int count;
Cpoint tri_nor;
Cpoint cross_point;
Triangle temp_tri;
for (int j = 0; j < 3; j++){
temp_tri.ids[j] = node->tri.ids[j];
}
tri_nor = CrossProduct(array_stt_vert_[temp_tri.ids[1]].posic - array_stt_vert_[temp_tri.ids[0]].posic,
array_stt_vert_[temp_tri.ids[2]].posic - array_stt_vert_[temp_tri.ids[0]].posic);
// 这一步可能会非常耗时
for (int i = 0; i < in_topo.vert.size(); i++){
// 控制点和三角形的法线方向相同(在同一个半球)
if (DotProduct(tri_nor, in_topo.vert[i].posic) > 0){
count = 0;
for (int j = 0; j < 3; j++){
cross_point = LineCrossPlane(array_stt_vert_[temp_tri.ids[j]].posic, tri_nor, in_topo.vert[i].posic);
if (DotProduct(tri_nor,
CrossProduct(array_stt_vert_[temp_tri.ids[(j+1)%3]].posic - array_stt_vert_[temp_tri.ids[j]].posic,
cross_point - array_stt_vert_[temp_tri.ids[j]].posic)) > 0){
count++;
}
}
// 满足条件则 穿透点在三角形内
if (count == 3){
out_topo.vert.push_back(in_topo.vert[i]);
out_topo.topo.push_back(in_topo.topo[i]);
}
}
}
return 0;
}
}

View File

@@ -12,6 +12,7 @@ int SttGenerator::Routine(char input_options[][1024]){
// get outline and hole polygons
if (GetControlPoint(input_options[7])) return -1;
if (GetControlCircle(input_options[10])) return -1;
if (GetControlTopography(input_options[13])) return -1;
if (GetControlLine(input_options[8],array_control_line_)) return -1;
if (GetControlLine(input_options[9],array_control_polygon_)) return -1;
if (GetControlLine(input_options[11],array_outline_polygon_)) return -1;
@@ -42,7 +43,7 @@ int SttGenerator::Routine(char input_options[][1024]){
for (int i = 0; i < 20; i++){
bar->Progressed(i);
// initialize the tree index starts from 50 to avoid possible repetition of vertex's index
CreateTree(i+50,base_icosahedron_.tri[i].ids[0],base_icosahedron_.tri[i].ids[1],base_icosahedron_.tri[i].ids[2], forest_[i]);
CreateTree(i+50,base_icosahedron_.tri[i].ids[0],base_icosahedron_.tri[i].ids[1],base_icosahedron_.tri[i].ids[2], forest_[i], control_topo_);
}
delete bar;