Path: blob/devel/ElmerGUI/netgen/libsrc/csg/extrusion.cpp
3206 views
#include <mystdlib.h>12#include <linalg.hpp>3#include <csg.hpp>456namespace netgen7{89void ExtrusionFace :: Init(void)10{11p0.SetSize(path->GetNSplines());12x_dir.SetSize(path->GetNSplines());13y_dir.SetSize(path->GetNSplines());14z_dir.SetSize(path->GetNSplines());15loc_z_dir.SetSize(path->GetNSplines());16spline3_path.SetSize(path->GetNSplines());17line_path.SetSize(path->GetNSplines());1819for(int i=0; i<path->GetNSplines(); i++)20{21spline3_path[i] = dynamic_cast < const SplineSeg3<3>* >(&path->GetSpline(i));22line_path[i] = dynamic_cast < const LineSeg<3>* >(&path->GetSpline(i));2324if(line_path[i])25{26y_dir[i] = line_path[i]->EndPI() - line_path[i]->StartPI();27y_dir[i].Normalize();28z_dir[i] = glob_z_direction;29Orthogonalize(y_dir[i],z_dir[i]);30x_dir[i] = Cross(y_dir[i],z_dir[i]);31loc_z_dir[i] = z_dir[i];32}33else34{35z_dir[i] = glob_z_direction;36loc_z_dir[i] = glob_z_direction;37}38}3940profile->GetCoeff(profile_spline_coeff);41latest_point3d = -1.111e30;4243}444546ExtrusionFace :: ExtrusionFace(const SplineSeg<2> * profile_in,47const SplineGeometry<3> * path_in,48const Vec<3> & z_direction) :49profile(profile_in), path(path_in), glob_z_direction(z_direction)50{51deletable = false;5253Init();54}5556ExtrusionFace :: ExtrusionFace(const ARRAY<double> & raw_data)57{58deletable = true;5960int pos=0;6162ARRAY< Point<2> > p(3);6364int ptype = int(raw_data[pos]); pos++;6566for(int i=0; i<ptype; i++)67{68p[i](0) = raw_data[pos]; pos++;69p[i](1) = raw_data[pos]; pos++;70}71if(ptype == 2)72{73profile = new LineSeg<2>(GeomPoint<2>(p[0],1),74GeomPoint<2>(p[1],1));75//(*testout) << "appending LineSeg<2> " << p[0]76// << " to " << p[1] << endl;77}78else if(ptype == 3)79{80profile = new SplineSeg3<2>(GeomPoint<2>(p[0],1),81GeomPoint<2>(p[1],1),82GeomPoint<2>(p[2],1));83//(*testout) << "appending SplineSeg<3> "84// << p[0] << " -- " << p[1] << " -- " << p[2] << endl;85}8687path = new SplineGeometry<3>;88pos = const_cast< SplineGeometry<3> *>(path)->Load(raw_data,pos);8990for(int i=0; i<3; i++)91{92glob_z_direction(i) = raw_data[pos];93pos++;94}9596//(*testout) << "read glob_z_direction " << glob_z_direction << endl;9798Init();99100}101102ExtrusionFace :: ~ExtrusionFace()103{104if(deletable)105{106delete profile;107delete path;108}109}110111112int ExtrusionFace :: IsIdentic (const Surface & s2, int & inv, double eps) const113{114const ExtrusionFace * ext2 = dynamic_cast<const ExtrusionFace*>(&s2);115116if(!ext2) return 0;117118if(ext2 == this)119return 1;120121return 0;122}123124void ExtrusionFace :: Orthogonalize(const Vec<3> & v1, Vec<3> & v2) const125{126v2 -= (v1*v2)*v1;127v2.Normalize();128}129130131void ExtrusionFace :: CalcProj(const Point<3> & point3d, Point<2> & point2d,132int & seg, double & t) const133{134if(Dist2(point3d,latest_point3d) < 1e-25*Dist2(path->GetSpline(0).StartPI(),path->GetSpline(0).EndPI()))135{136point2d = latest_point2d;137seg = latest_seg;138t = latest_t;139return;140}141142latest_point3d = point3d;143144double cutdist(-1);145146147148149ARRAY<double> mindist(path->GetNSplines());150151for(int i=0; i<path->GetNSplines(); i++)152{153154double auxcut(-1);155double auxmin(-1);156157if(spline3_path[i])158{159Point<3> startp(path->GetSpline(i).StartPI());160Point<3> endp(path->GetSpline(i).EndPI());161Point<3> tanp(spline3_path[i]->TangentPoint());162double da,db,dc;163164double l;165Vec<3> dir = endp-startp;166l = dir.Length(); dir *= 1./l;167Vec<3> topoint = point3d - startp;168double s = topoint * dir;169if(s<=0)170da = topoint.Length();171else if(s>=l)172da = Dist(endp,point3d);173else174da = sqrt(topoint.Length2() - s*s);175176dir = tanp - startp;177l = dir.Length(); dir *= 1./l;178topoint = point3d - startp;179s = topoint * dir;180if(s<=0)181db = topoint.Length();182else if(s>=l)183db = Dist(tanp,point3d);184else185db = sqrt(topoint.Length2() - s*s);186187dir = endp - tanp;188l = dir.Length(); dir *= 1./l;189topoint = point3d - tanp;190s = topoint * dir;191if(s<=0)192dc = topoint.Length();193else if(s>=l)194dc = Dist(endp,point3d);195else196dc = sqrt(topoint.Length2() - s*s);197198if(da > db && da > dc)199auxcut = da;200else201auxcut = max2(da,min2(db,dc));202203auxmin = min3(da,db,dc);204}205else if(line_path[i])206{207double l;208Vec<3> dir = path->GetSpline(i).EndPI() - path->GetSpline(i).StartPI();209l = dir.Length(); dir *= 1./l;210Vec<3> topoint = point3d - path->GetSpline(i).StartPI();211double s = topoint * dir;212if(s<=0)213auxcut = topoint.Length();214else if(s>=l)215auxcut = Dist(path->GetSpline(i).EndPI(),point3d);216else217auxcut = sqrt(topoint.Length2() - s*s);218219auxmin = auxcut;220}221222223mindist[i] = auxmin;224225if(i==0 || auxcut < cutdist)226cutdist = auxcut;227228229230231/*232double d1 = Dist2(point3d,path.GetSpline(i).StartPI());233double d2 = Dist2(point3d,path.GetSpline(i).EndPI());234if(d1 <= d2)235{236mindist[i] = d1;237if(i==0 || d2 < cutdist)238cutdist = d2;239}240else241{242mindist[i] = d2;243if(i==0 || d1 < cutdist)244cutdist = d1;245}246*/247}248249250//(*testout) << " cutdist " << cutdist << " mindist " << mindist << endl;251252253Point<2> testpoint2d;254Point<3> testpoint3d;255256double minproj(-1);257bool minproj_set(false);258259260//(*testout) << "point "<< point3d << " candidates: ";261for(int i=0; i<path->GetNSplines(); i++)262{263if(mindist[i] > cutdist) continue;264//(*testout) << i << " ";265266double thist = CalcProj(point3d,testpoint2d,i);267testpoint3d = p0[i] + testpoint2d(0)*x_dir[i] + testpoint2d(1)*loc_z_dir[i];268double d = Dist2(point3d,testpoint3d);269//(*testout) << "(d="<<d<<") ";270271if(!minproj_set || d < minproj)272{273minproj_set = true;274minproj = d;275point2d = testpoint2d;276t = thist;277seg = i;278latest_seg = i;279latest_t = t;280latest_point2d = point2d;281}282}283//(*testout) << endl;284//(*testout) << " t " << t << endl;285286}287288double ExtrusionFace :: CalcProj(const Point<3> & point3d, Point<2> & point2d,289const int seg) const290{291double t(-1);292293if(line_path[seg])294{295point2d(0) = (point3d-line_path[seg]->StartPI())*x_dir[seg];296point2d(1) = (point3d-line_path[seg]->StartPI())*z_dir[seg];297double l = Dist(line_path[seg]->StartPI(),298line_path[seg]->EndPI());299t = min2(max2((point3d - line_path[seg]->StartPI()) * y_dir[seg],0.),300l);301p0[seg] = line_path[seg]->StartPI() + t*y_dir[seg];302t *= 1./l;303}304else if(spline3_path[seg])305{306spline3_path[seg]->Project(point3d,p0[seg],t);307308y_dir[seg] = spline3_path[seg]->GetTangent(t); y_dir[seg].Normalize();309loc_z_dir[seg] = z_dir[seg];310Orthogonalize(y_dir[seg],loc_z_dir[seg]);311x_dir[seg] = Cross(y_dir[seg],loc_z_dir[seg]);312Vec<3> dir = point3d-p0[seg];313point2d(0) = x_dir[seg]*dir;314point2d(1) = loc_z_dir[seg]*dir;315}316return t;317}318319double ExtrusionFace :: CalcFunctionValue (const Point<3> & point) const320{321Point<2> p;322323double dummyd;324int dummyi;325326CalcProj(point,p,dummyi,dummyd);327//(*testout) << "spline " << dummyi << " t " << dummyd << endl;328329return profile_spline_coeff(0)*p(0)*p(0) + profile_spline_coeff(1)*p(1)*p(1)330+ profile_spline_coeff(2)*p(0)*p(1) + profile_spline_coeff(3)*p(0)331+ profile_spline_coeff(4)*p(1) + profile_spline_coeff(5);332}333334335void ExtrusionFace :: CalcGradient (const Point<3> & point, Vec<3> & grad) const336{337int i;338Point<2> p2d;339340double t_path;341int seg;342CalcProj(point,p2d,seg,t_path);343344Point<3> phi;345Vec<3> phip,phipp,phi_minus_point;346347path->GetSpline(seg).GetDerivatives(t_path,phi,phip,phipp);348349phi_minus_point = phi-point;350351Vec<3> grad_t = phip;352353double facA = phipp*phi_minus_point + phip*phip;354355grad_t *= 1./facA;356357ARRAY < Vec<3> > dphi_dX(3);358359for(i=0; i<3; i++)360dphi_dX[i] = grad_t(i)*phip;361362ARRAY < Vec<3> > dy_dir_dX(3);363364double lphip = phip.Length();365366dy_dir_dX[0] = dy_dir_dX[1] = dy_dir_dX[2] =367(1./lphip) * phipp - ((phip*phipp)/pow(lphip,3)) * phip;368369for(i=0; i<3; i++)370dy_dir_dX[i] *= grad_t(i);371372ARRAY < Vec<3> > dx_dir_dX(3);373374for(i=0; i<3; i++)375dx_dir_dX[i] = Cross(dy_dir_dX[i],z_dir[seg]);376377Vec<3> grad_xbar;378379for(i=0; i<3; i++)380grad_xbar(i) = -1.*(phi_minus_point * dx_dir_dX[i]) + x_dir[seg](i) - x_dir[seg] * dphi_dX[i];381382double zy = z_dir[seg]*y_dir[seg];383384Vec<3> grad_ybar;385Vec<3> aux = z_dir[seg] - zy*y_dir[seg];386387for(i=0; i<3; i++)388grad_ybar(i) = ( (z_dir[seg]*dy_dir_dX[i])*y_dir[seg] + zy*dy_dir_dX[i] ) * phi_minus_point +389aux[i] -390aux * dphi_dX[i];391392393const double dFdxbar = 2.*profile_spline_coeff(0)*p2d(0) +394profile_spline_coeff(2)*p2d(1) + profile_spline_coeff(3);395396const double dFdybar = 2.*profile_spline_coeff(1)*p2d(1) +397profile_spline_coeff(2)*p2d(0) + profile_spline_coeff(4);398399400grad = dFdxbar * grad_xbar + dFdybar * grad_ybar;401}402403void ExtrusionFace :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const404{405const double eps = 1e-7*Dist(path->GetSpline(0).StartPI(),path->GetSpline(0).EndPI());406407/*408Point<3> auxpoint1(point),auxpoint2(point);409Vec<3> auxvec,auxgrad1,auxgrad2;410411for(int i=0; i<3; i++)412{413auxpoint1(i) -= eps;414auxpoint2(i) += eps;415CalcGradient(auxpoint1,auxgrad1);416CalcGradient(auxpoint2,auxgrad2);417auxvec = (1./(2.*eps)) * (auxgrad2-auxgrad1);418for(int j=0; j<3; j++)419hesse(i,j) = auxvec(j);420auxpoint1(i) = point(i);421auxpoint2(i) = point(i);422}423*/424425426Vec<3> grad;427CalcGradient(point,grad);428429Point<3> auxpoint(point);430Vec<3> auxvec,auxgrad;431432for(int i=0; i<3; i++)433{434auxpoint(i) -= eps;435CalcGradient(auxpoint,auxgrad);436auxvec = (1./eps) * (grad-auxgrad);437for(int j=0; j<3; j++)438hesse(i,j) = auxvec(j);439auxpoint(i) = point(i);440}441442443444for(int i=0; i<3; i++)445for(int j=i+1; j<3; j++)446hesse(i,j) = hesse(j,i) = 0.5*(hesse(i,j)+hesse(j,i));447}448449450451double ExtrusionFace :: HesseNorm () const452{453return fabs(profile_spline_coeff(0) + profile_spline_coeff(1)) +454sqrt(pow(profile_spline_coeff(0)+profile_spline_coeff(1),2)+4.*pow(profile_spline_coeff(2),2));455}456457double ExtrusionFace :: MaxCurvature () const458{459double retval,actmax;460461retval = profile->MaxCurvature();462for(int i=0; i<path->GetNSplines(); i++)463{464actmax = path->GetSpline(i).MaxCurvature();465if(actmax > retval)466retval = actmax;467}468469return 2.*retval;470}471472473void ExtrusionFace :: Project (Point<3> & p) const474{475double dummyt;476int seg;477Point<2> p2d;478479CalcProj(p,p2d,seg,dummyt);480481profile->Project(p2d,p2d,profile_par);482483p = p0[seg] + p2d(0)*x_dir[seg] + p2d(1)*loc_z_dir[seg];484485Vec<2> tangent2d = profile->GetTangent(profile_par);486profile_tangent = tangent2d(0)*x_dir[seg] + tangent2d(1)*y_dir[seg];487}488489490491Point<3> ExtrusionFace :: GetSurfacePoint () const492{493p0[0] = path->GetSpline(0).GetPoint(0.5);494if(!line_path[0])495{496y_dir[0] = path->GetSpline(0).GetTangent(0.5);497y_dir[0].Normalize();498loc_z_dir[0] = z_dir[0];499Orthogonalize(y_dir[0],loc_z_dir[0]);500x_dir[0] = Cross(y_dir[0],loc_z_dir[0]);501}502503Point<2> locpoint = profile->GetPoint(0.5);504505return p0[0] + locpoint(0)*x_dir[0] + locpoint(1)*loc_z_dir[0];506}507508bool ExtrusionFace :: BoxIntersectsFace(const Box<3> & box) const509{510Point<3> center = box.Center();511512Project(center);513514//(*testout) << "box.Center() " << box.Center() << " projected " << center << " diam " << box.Diam()515// << " dist " << Dist(box.Center(),center) << endl;516517return (Dist(box.Center(),center) < 0.5*box.Diam());518}519520521void ExtrusionFace :: LineIntersections ( const Point<3> & p,522const Vec<3> & v,523const double eps,524int & before,525int & after,526bool & intersecting ) const527{528Point<2> p2d;529Vec<2> v2d;530531intersecting = false;532533double segt;534int seg;535536CalcProj(p,p2d,seg,segt);537538if(seg == 0 && segt < 1e-20)539{540Vec<3> v1,v2;541v1 = path->GetSpline(0).GetTangent(0);542v2 = p-p0[seg];543if(v1*v2 < -eps)544return;545}546if(seg == path->GetNSplines()-1 && 1.-segt < 1e-20)547{548Vec<3> v1,v2;549v1 = path->GetSpline(seg).GetTangent(1);550v2 = p-p0[seg];551if(v1*v2 > eps)552return;553}554555v2d(0) = v * x_dir[seg];556v2d(1) = v * loc_z_dir[seg];557558Vec<2> n(v2d(1),-v2d(0));559ARRAY < Point<2> > ips;560561562profile->LineIntersections(v2d(1),563-v2d(0),564-v2d(1)*p2d(0) + v2d(0)*p2d(1),565ips,eps);566int comp;567568if(fabs(v2d(0)) >= fabs(v2d(1)))569comp = 0;570else571comp = 1;572573//(*testout) << "p2d " << p2d;574575for(int i=0; i<ips.Size(); i++)576{577//(*testout) << " ip " << ips[i];578579double t = (ips[i](comp)-p2d(comp))/v2d(comp);580581if(t < -eps)582before++;583else if(t > eps)584after++;585else586intersecting = true;587}588//(*testout) << endl;589}590591void ExtrusionFace :: Print (ostream & str) const{}592593INSOLID_TYPE ExtrusionFace :: VecInFace ( const Point<3> & p,594const Vec<3> & v,595const double eps ) const596{597598Vec<3> normal1;599CalcGradient(p,normal1); normal1.Normalize();600601double d1 = normal1*v;602603604if(d1 > eps)605return IS_OUTSIDE;606if(d1 < -eps)607return IS_INSIDE;608609610return DOES_INTERSECT;611612/*613Point<2> p2d;614615double t_path;616int seg;617CalcProj(p,p2d,seg,t_path);618619double t;620profile.Project(p2d,p2d,t);621622623624Vec<2> profile_tangent = profile.GetTangent(t);625626double d;627628Vec<3> normal1;629CalcGradient(p,normal1); normal1.Normalize();630631double d1 = normal1*v;632633Vec<2> v2d;634635v2d(0) = v*x_dir[seg];636v2d(1) = v*loc_z_dir[seg];637638639Vec<2> normal(-profile_tangent(1),profile_tangent(0));640641//d = normal*v2d;642643644d = d1;645646647if(d > eps)648return IS_OUTSIDE;649if(d < -eps)650return IS_INSIDE;651652653return DOES_INTERSECT;654*/655}656657658void ExtrusionFace :: GetTriangleApproximation (TriangleApproximation & tas,659const Box<3> & boundingbox,660double facets) const661{662int n = int(facets) + 1;663664int i,j,k;665666667int nump = 0;668for(k=0; k<path->GetNSplines(); k++)669{670for(i=0; i<=n; i++)671{672Point<3> origin = path->GetSpline(k).GetPoint(double(i)/double(n));673if(!line_path[k])674{675y_dir[k] = path->GetSpline(k).GetTangent(double(i)/double(n));676y_dir[k].Normalize();677}678loc_z_dir[k] = z_dir[k];679Orthogonalize(y_dir[k],loc_z_dir[k]);680if(!line_path[k])681x_dir[k] = Cross(y_dir[k],loc_z_dir[k]);682683for(j=0; j<=n; j++)684{685Point<2> locp = profile->GetPoint(double(j)/double(n));686tas.AddPoint(origin + locp(0)*x_dir[k] + locp(1)*loc_z_dir[k]);687nump++;688}689}690}691692for(k=0; k<path->GetNSplines(); k++)693for(i=0; i<n; i++)694for(j=0; j<n; j++)695{696int pi = k*(n+1)*(n+1) + (n+1)*i +j;697698tas.AddTriangle( TATriangle (0, pi,pi+1,pi+n+1));699tas.AddTriangle( TATriangle (0, pi+1,pi+n+1,pi+n+2));700}701}702703704void ExtrusionFace :: GetRawData(ARRAY<double> & data) const705{706data.DeleteAll();707profile->GetRawData(data);708path->GetRawData(data);709for(int i=0; i<3; i++)710data.Append(glob_z_direction[i]);711//(*testout) << "written raw data " << data << endl;712}713714715716Extrusion :: Extrusion(const SplineGeometry<3> & path_in,717const SplineGeometry<2> & profile_in,718const Vec<3> & z_dir) :719path(path_in), profile(profile_in), z_direction(z_dir)720{721surfaceactive.SetSize(0);722surfaceids.SetSize(0);723724for(int j=0; j<profile.GetNSplines(); j++)725{726ExtrusionFace * face = new ExtrusionFace(&(profile.GetSpline(j)),727&path,728z_direction);729faces.Append(face);730surfaceactive.Append(true);731surfaceids.Append(0);732}733734}735736737Extrusion :: ~Extrusion()738{739for(int i=0; i<faces.Size(); i++)740delete faces[i];741}742743744745746747INSOLID_TYPE Extrusion :: BoxInSolid (const BoxSphere<3> & box) const748{749for(int i=0; i<faces.Size(); i++)750{751if(faces[i]->BoxIntersectsFace(box))752return DOES_INTERSECT;753}754755return PointInSolid(box.Center(),0);756}757758759INSOLID_TYPE Extrusion :: PointInSolid (const Point<3> & p,760const double eps,761ARRAY<int> * const facenums) const762{763Vec<3> random_vec(-0.4561,0.7382,0.4970247);764765int before(0), after(0);766bool intersects(false);767bool does_intersect(false);768769for(int i=0; i<faces.Size(); i++)770{771faces[i]->LineIntersections(p,random_vec,eps,before,after,intersects);772773//(*testout) << "intersects " << intersects << " before " << before << " after " << after << endl;774if(intersects)775{776if(facenums)777{778facenums->Append(i);779does_intersect = true;780}781else782return DOES_INTERSECT;783}784}785786if(does_intersect)787return DOES_INTERSECT;788789790if(before % 2 == 0)791return IS_OUTSIDE;792793return IS_INSIDE;794}795796797INSOLID_TYPE Extrusion :: PointInSolid (const Point<3> & p,798double eps) const799{800return PointInSolid(p,eps,NULL);801}802803INSOLID_TYPE Extrusion :: VecInSolid (const Point<3> & p,804const Vec<3> & v,805double eps) const806{807ARRAY<int> facenums;808INSOLID_TYPE pInSolid = PointInSolid(p,eps,&facenums);809810if(pInSolid != DOES_INTERSECT)811return pInSolid;812813814double d(0);815816if(facenums.Size() == 1)817{818Vec<3> normal;819faces[facenums[0]]->CalcGradient(p,normal);820normal.Normalize();821d = normal*v;822823latestfacenum = facenums[0];824}825else if (facenums.Size() == 2)826{827Vec<3> checkvec;828829Point<3> dummy(p);830faces[facenums[0]]->Project(dummy);831if(fabs(faces[facenums[0]]->GetProfilePar()) < 0.1)832{833int aux = facenums[0];834facenums[0] = facenums[1]; facenums[1] = aux;835}836837checkvec = faces[facenums[0]]->GetYDir();838839Vec<3> n0, n1;840faces[facenums[0]]->CalcGradient(p,n0);841faces[facenums[1]]->CalcGradient(p,n1);842n0.Normalize();843n1.Normalize();844845846Vec<3> t = Cross(n0,n1);847if(checkvec*t < 0) t*= (-1.);848849Vec<3> t0 = Cross(n0,t);850Vec<3> t1 = Cross(t,n1);851852t0.Normalize();853t1.Normalize();854855856const double t0v = t0*v;857const double t1v = t1*v;858859if(t0v > t1v)860{861latestfacenum = facenums[0];862d = n0*v;863}864else865{866latestfacenum = facenums[1];867d = n1*v;868}869870if(fabs(t0v) < eps && fabs(t1v) < eps)871latestfacenum = -1;872}873874else875{876cerr << "WHY ARE THERE " << facenums.Size() << " FACES?" << endl;877}878879if(d > eps)880return IS_OUTSIDE;881if(d < -eps)882return IS_INSIDE;883884return DOES_INTERSECT;885}886887888889// checks if lim s->0 lim t->0 p + t(v1 + s v2) in solid890INSOLID_TYPE Extrusion :: VecInSolid2 (const Point<3> & p,891const Vec<3> & v1,892const Vec<3> & v2,893double eps) const894{895INSOLID_TYPE retval;896retval = VecInSolid(p,v1,eps);897898// *testout << "extr, vecinsolid=" << int(retval) << endl;899900if(retval != DOES_INTERSECT)901return retval;902903if(latestfacenum >= 0)904return faces[latestfacenum]->VecInFace(p,v2,0);905else906return VecInSolid(p,v2,eps);907}908909910int Extrusion :: GetNSurfaces() const911{912return faces.Size();913}914915Surface & Extrusion :: GetSurface (int i)916{917return *faces[i];918}919920const Surface & Extrusion :: GetSurface (int i) const921{922return *faces[i];923}924925926void Extrusion :: Reduce (const BoxSphere<3> & box)927{928for(int i=0; i<faces.Size(); i++)929surfaceactive[i] = faces[i]->BoxIntersectsFace(box);930}931932void Extrusion :: UnReduce ()933{934for(int i=0; i<faces.Size(); i++)935surfaceactive[i] = true;936}937938939}940941942