#include "MGCLStdAfx.h" #include "mg/Tolerance.h" #include "mg/Position.h" #include "topo/Edge.h" #include "topo/Loop.h" #include "topo/Face.h" #include "Tl2/TL2Parameter.h" #include "Tl2/TL2LPline.h" #include "Tl2/TL2Fan.h" #include "Tl2/TL2Fans.h" #include "Tl2/TL2Triangle.h" #include "Tl2/TL2Triangles.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif using namespace std; /****************************************************************/ /* Copyright (c) 2017 by System fugen G.K. */ /* All rights reserved. */ /****************************************************************/ //////////// mgTL2Fans/////////// ////////// private class ////////// class mgTL2FanEdge{ private: int m_start, m_end;//Edge's start and end ids. public: mgTL2FanEdge(){;}; mgTL2FanEdge(int start, int end):m_start(start),m_end(end){;}; int start()const {return m_start;}; int end()const {return m_end;}; }; class mgTL2FanEdges{ private: std::deque m_edges; public: typedef std::deque::const_iterator eitr; mgTL2FanEdges(){;}; eitr begin()const{return m_edges.begin();}; eitr end()const{return m_edges.end();}; bool empty()const{return m_edges.empty();}; void pop_back(){m_edges.pop_back();}; void push_back(int start, int end){ m_edges.push_back(mgTL2FanEdge(start,end)); }; void push_front(int start, int end){ m_edges.push_front(mgTL2FanEdge(start,end)); }; void push_front(const mgTL2FanEdge& edge){m_edges.push_front(edge);}; }; std::ostream& operator<< (std::ostream& out, const mgTL2FanEdges& edges){ mgTL2FanEdges::eitr i=edges.begin(), ie=edges.end(); for(int j=0; i!=ie; i++, j++){ out<<" "<& polylines//Edges of the polyline that are mgTL2Polyline. ){ size_t npoly=polylines.size(); m_polylines.resize(npoly); for(size_t j=0; j "<< gamma << endl << endl; //求まったステータスに応じた処理を行う if(status==UNKNOWN)continue; //UNKNOWN==0 switch(status){ case TWOTOUCH: continue; //TWOTOUCH==1 case NOTOUCH: edgeStack.push_front(edge); break;//NOTOUCH==2 case REGULAR: //REGULAR==3 push1Vaft(alpha, beta, gamma); push1Vbefore(beta, gamma, alpha); push2V(gamma, alpha, beta); set_edge_used(alpha, beta); set_edge_used(beta, gamma); set_edge_used(gamma, alpha); break; case RIGHTTOUCH: //RIGHTTOUCH==4 push1Vbefore(beta, gamma, alpha); push1Vaft(gamma, alpha, beta); set_edge_used(alpha, beta); set_edge_used(beta, gamma); break; case LEFTTOUCH: //LEFTTOUCH==5 push1Vaft(alpha, beta, gamma); push1Vbefore(gamma, alpha, beta); set_edge_used(alpha, beta); set_edge_used(gamma, alpha); break; default: break;//求まらなかったとき } if(!is_boundary(alpha,gamma) && (status!=RIGHTTOUCH)){ //std::cout<<" Stacking("< 1.5){//3点目が見つからなかった status=UNKNOWN; return gamma; } //ステータスの更新を行う if(!gamma_is_used){//未使用の点のときREGULAR status=REGULAR; }else if(right_touch){ if(left_touch) status=TWOTOUCH; else status = RIGHTTOUCH; }else{ if(left_touch) status=LEFTTOUCH; else status=NOTOUCH; } return gamma; } //線分(v1,v2)が既存のedgeと交点があるかどうかを調べる //Function returns true if (v1,v2) had an isect. bool mgTL2Fans::has_isect( int v1, //線分1の点 int v2 //線分1の点 )const{ if(is_boundary(v1,v2)) return false; double error=MGTolerance::rc_zero(); const MGPosition p1=uv(v1), p2=uv(v2); const MGVector dir1(p2-p1); double udir1=dir1[0], vdir1=dir1[1]; int nfan=size()-1; for(int i=0; i=0.) continue;//This means p3 and p4 are located at the same side about the straight line (p1, p2). // if(-z134<=error) continue;/////////// const MGVector dir2(p4 - p3); double udir2=dir2[0], vdir2=dir2[1]; double z23=vdir31*udir2-udir31*vdir2; double z24=vdir32*udir2-udir32*vdir2; double z234=z23*z24; if(z234>=0.) continue;//This means p1 and p2 are located at the same side about the //straight line (p3, p4). // if(-z234<=error) continue;/////////// return true;//In this case, (p1,p2) and (p3,p4) has and intersection. } } return false; } //Fan生成に必要な変数の準備を行う //edgeStackにedgeのstackを積む void mgTL2Fans::init_edgeStack( mgTL2FanEdges& edgeStack ){ //多角形の辺をスタックに積む、このとき頂点を未使用にしておく //push edges on the stack edgeStack. int nvertices=size(); int im1=nvertices-1; for(int i=0; ibeta){ int temp=alpha; alpha=beta; beta=temp; } int n=size(); if(alpha==0 && beta==n-1) return true; int alpha_n=(alpha+1)%n; return alpha_n==beta; } //目的:中心点(center)がalphaのmgTL2Fanに対し、頂点gammaを基準betaの //後ろに追加する void mgTL2Fans::push1Vaft( int alpha, //中心点のインデックス int beta, //基準となる頂点のインデックス int gamma //追加する頂点のインデックス ){ // std::cout<<"===push1Vaft("<beta){ int temp=alpha; alpha=beta; beta=temp; } mgTL2Fan* fan=m_fans[alpha]; fan->set_edge_used(beta); } //check if vertex(alpha) is used or not. bool mgTL2Fans::used(int alpha) const{ return m_fans[alpha]->vertex_is_used(); } //check if edge(alpha, beta) is used or not. bool mgTL2Fans::used(int alpha, int beta) const{ if(alpha>beta){ int temp=alpha; alpha=beta; beta=temp; } const mgTL2Fan* fan=m_fans[alpha]; return fan->edge_is_used(beta); } MGPosition mgTL2Fans::uv(int i)const{ assert(i tf2.vnum();} }; ///Triangulate polygon. ///The result will be appended onto triangles. void mgTL2Fans::triangulate( mgTL2Triangles& triangles /// fansizes(nfan); for(int i=0; isize()); } std::sort(fansizes.begin(), fansizes.end(), mgTl2fansizeSort()); std::vector vused(nfan,false); //Flag if the corresponding vertex is already processed to make fan. //vused[i] corrsponds to the vertex fans[i] is used or not. for(int ifan=0; ifan verticesIDs(nvert+1);//vertices id vector. int nvTri=1; verticesIDs[0]=center; for(int m=0; m