/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "topo/Edge.h" #include "topo/Face.h" #include "topo/Loop.h" #include "mg/Curve.h" #include "mg/Surface.h" #include "mg/Pvector.h" #include "mg/Straight.h" #include "mg/CCisect_list.h" #include "mg/CParam_list.h" #include "mg/Tolerance.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif using namespace std; //ボックス枠に囲まれる交点を持つUV曲線を生成する void MGFace::getTrimCrv( double uerror, double verror,//u and v parameter error. const MGBox& box, //parameter (u,v) box of the surface. MGPvector<MGCurve>& vecCrv //paremter curves will be output ) const{ double u0=box[0].low_point(), u1=box[0].high_point(); double v0=box[1].low_point(), v1=box[1].high_point(); // if(u0>159. && v0>-1. && u1<223. && v1<102.) // u0=u0; const int n = number_of_boundaries(); for(int i = 0; i < n; i++){ const MGLoop& lpi = *(loop(i)); if(!lpi.active()) continue; const int m = lpi.number_of_edges(); for(int j = 0; j < m; j++){ const MGEdge& ei = *(lpi.edge(j)); //if(ei.on_surface_perimeter())continue; //ペリメータ以外のバウンダリの処理 MGBox boxEdge(ei.box()); if((boxEdge&box).empty()) continue;//共通ボックスなし std::unique_ptr<MGCurve> atpCrv(ei.curve_limitted()); //エッジが与えられたボックスに含まれるときの処理 if(box >> boxEdge){ //When boxEdge is included in box. //std::cout<<(*atpCrv);///////// vecCrv.push_back(atpCrv.release()); continue; } MGCParam_list isectParamList(atpCrv.get()); isectParamList.append(atpCrv->param_s()); isectParamList.append(atpCrv->param_e()); double dPreWcTol = MGTolerance::set_wc_zero(uerror); isectParamList.append(atpCrv->isect_1D(u0,0)); MGTolerance::set_wc_zero(verror); isectParamList.append(atpCrv->isect_1D(v0,1)); isectParamList.append(atpCrv->isect_1D(v1,1)); MGTolerance::set_wc_zero(dPreWcTol); isectParamList.sort();//std::cout<<isectParamList;////// //パラメータの中間点のUV値がボックス内のとき曲線を分断してベクトルに挿入する MGCParam_list::const_Citerator param_iter = isectParamList.begin(); for(; param_iter != isectParamList.end(); param_iter++){ MGCParam_list::const_Citerator next_param_iter = param_iter; next_param_iter++; //次のパラメータ if(next_param_iter == isectParamList.end()) break; //終了チェック double t0=*param_iter, t1=*next_param_iter; double tmid=(t0+t1)*.5;//中間パラメータ MGPosition UVPos = atpCrv->eval(tmid);//面上パラメータ if(box >> UVPos) vecCrv.push_back(atpCrv->part(t0,t1)); //std::cout<<vecCrv;/////////////// } } } } //Offset. //distance is plus value if the direction is toward normal vector of the //face. Minus if against the normal vector. //エラーコード 0:成功 -1:曲率半径以上のオフセット不可 -2:面生成コンストラクタエラ>> int MGFace::offset(double distance, MGPvector<MGFace>& vecOfsFace)const{ vecOfsFace.clear(); const MGSurface *psrf = surface(); int err; MGPvector<MGSurface> vecOfsSrf = psrf->offset(distance, err); if(err < 0) return err; if(vecOfsSrf.size()==1){ //境界線を取り出す const std::vector<MGBoundary*>& bounds = boundaries(); //Faceを生成する MGFace* f=new MGFace(vecOfsSrf.release(0), bounds);//std::cout<<f; vecOfsFace.push_back(f); return 0; } //trim surface const MGBox& uvbox=box_param(); double uerror=uvbox[0].relative_error()*.2; double verror=uvbox[1].relative_error()*.2; vector<MGSurface*>::const_iterator i=vecOfsSrf.begin(), ie=vecOfsSrf.end(); for(; i!=ie; i++){ const MGSurface& srfi=**i; MGPvector<MGCurve> uvcurves; getTrimCrv(uerror, verror, srfi.box_param(), uvcurves); int n=(int)uvcurves.size(); if(!n){//If no trim curves. if(in_range(srfi.center_param())) vecOfsFace.push_back(new MGFace(srfi)); continue; } //If there were trim curves. int pnum,l; vector<MGCurve*>::const_iterator j; j=uvcurves.begin(); int oldpnum=-1; for(l=0;l<n; j++, l++){ if(srfi.on_perimeter(**j,pnum)){ if(oldpnum==-1) oldpnum=pnum; else if(oldpnum!=pnum) break; }else break; } if(l==n){//If all the uvcurves were on the one perimeter if(in_range(srfi.center_param())) vecOfsFace.push_back(new MGFace(srfi)); }else{ MGFace *pOfsFace = new MGFace(srfi); j=uvcurves.begin(); for(l=0;l<n; j++, l++) pOfsFace->trim(**j); vecOfsFace.push_back(pOfsFace); //std::cout<<(*pOfsFace);////// } } return 0; } //Offset. //distance is plus value if the direction is toward normal vector of the //face. Minus if against the normal vector. //エラーコード 0:成功 -1:面におれがある -2:曲率半径以上のオフセット不可 -3:面生成コンストラクタエラー MGFace MGFace::offset(double distance, int& error)const { //Faceの面をオフセットする const MGSurface *srf = surface(); std::unique_ptr<MGSurface> pofsSrf = srf->offset_c1(distance, error); if(error < 0){ if(error==-1){ //Recover the surface of multiplicity order()-1 //by remove_knot(). MGSurface* srf2=srf->copy_surface(); srf2->remove_knot(); pofsSrf = std::unique_ptr<MGSurface>(srf2->offset_c1(distance, error)); delete srf2; if(error) return MGFace(); }else return MGFace(); } //境界線を取り出す const std::vector<MGBoundary*>& bounds = boundaries(); //Faceを生成する MGFace f2(pofsSrf.release(), bounds);//std::cout<<f2; return f2; } //Offset. //distance is plus value if the direction is toward normal vector of the //FSurface. Minus if against the normal vector. //エラーコード 0:成功 -1:曲率半径以上のオフセット不可 -3:面生成コンストラクタエラー int MGFace::offset_fs(double distance, MGPvector<MGFSurface>& vecOfsFSurface)const{ MGPvector<MGFace> faces; int error=offset(distance,faces); if(error) return error; int n=(int)faces.size(); for(int i=0; i<n; i++) vecOfsFSurface.push_back(faces.release(i)); return 0; }