Path: blob/devel/ElmerGUI/netgen/libsrc/csg/polyhedra.cpp
3206 views
#include <mystdlib.h>12#include <linalg.hpp>3#include <csg.hpp>45namespace netgen6{78Polyhedra::Face::Face (int pi1, int pi2, int pi3,9const ARRAY<Point<3> > & points,10int ainputnr)11{12inputnr = ainputnr;1314pnums[0] = pi1;15pnums[1] = pi2;16pnums[2] = pi3;171819bbox.Set (points[pi1]);20bbox.Add (points[pi2]);21bbox.Add (points[pi3]);2223v1 = points[pi2] - points[pi1];24v2 = points[pi3] - points[pi1];2526n = Cross (v1, v2);2728nn = n;29nn.Normalize();30// PseudoInverse (v1, v2, w1, w2);3132Mat<2,3> mat;33Mat<3,2> inv;34for (int i = 0; i < 3; i++)35{36mat(0,i) = v1(i);37mat(1,i) = v2(i);38}39CalcInverse (mat, inv);40for (int i = 0; i < 3; i++)41{42w1(i) = inv(i,0);43w2(i) = inv(i,1);44}45}464748Polyhedra :: Polyhedra ()49{50surfaceactive.SetSize(0);51surfaceids.SetSize(0);52eps_base1 = 1e-8;53}5455Polyhedra :: ~Polyhedra ()56{57;58}5960Primitive * Polyhedra :: CreateDefault ()61{62return new Polyhedra();63}6465INSOLID_TYPE Polyhedra :: BoxInSolid (const BoxSphere<3> & box) const66{67/*68for (i = 1; i <= faces.Size(); i++)69if (FaceBoxIntersection (i, box))70return DOES_INTERSECT;71*/72for (int i = 0; i < faces.Size(); i++)73{74if (!faces[i].bbox.Intersect (box))75continue;76//(*testout) << "face " << i << endl;7778const Point<3> & p1 = points[faces[i].pnums[0]];79const Point<3> & p2 = points[faces[i].pnums[1]];80const Point<3> & p3 = points[faces[i].pnums[2]];8182if (fabs (faces[i].nn * (p1 - box.Center())) > box.Diam()/2)83continue;8485//(*testout) << "still in loop" << endl;8687double dist2 = MinDistTP2 (p1, p2, p3, box.Center());88//(*testout) << "p1 " << p1 << " p2 " << p2 << " p3 " << p3 << endl89// << " box.Center " << box.Center() << " box.Diam() " << box.Diam() << endl90// << " dist2 " << dist2 << " sqr(box.Diam()/2) " << sqr(box.Diam()/2) << endl;91if (dist2 < sqr (box.Diam()/2))92{93//(*testout) << "DOES_INTERSECT" << endl;94return DOES_INTERSECT;95}96};9798return PointInSolid (box.Center(), 1e-3 * box.Diam());99}100101102INSOLID_TYPE Polyhedra :: PointInSolid (const Point<3> & p,103double eps) const104{105//(*testout) << "PointInSolid p " << p << " eps " << eps << endl;106//(*testout) << "bbox " << poly_bbox << endl;107108if((p(0) > poly_bbox.PMax()(0) + eps) || (p(0) < poly_bbox.PMin()(0) - eps) ||109(p(1) > poly_bbox.PMax()(1) + eps) || (p(1) < poly_bbox.PMin()(1) - eps) ||110(p(2) > poly_bbox.PMax()(2) + eps) || (p(2) < poly_bbox.PMin()(2) - eps))111{112//(*testout) << "returning IS_OUTSIDE" << endl;113return IS_OUTSIDE;114}115116Vec<3> n, v1, v2;117118// random (?) numbers:119n(0) = -0.424621;120n(1) = 0.15432;121n(2) = 0.89212238;122123int cnt = 0;124125for (int i = 0; i < faces.Size(); i++)126{127const Point<3> & p1 = points[faces[i].pnums[0]];128129Vec<3> v0 = p - p1;130131double lam3 = faces[i].nn * v0;132133if(fabs(lam3) < eps)134{135double lam1 = (faces[i].w1 * v0);136double lam2 = (faces[i].w2 * v0);137if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam1+lam2 <= 1+eps_base1)138{139//(*testout) << "returning DOES_INTERSECT" << endl;140return DOES_INTERSECT;141}142}143else144{145lam3 = -(faces[i].n * v0) / (faces[i].n * n);146147if (lam3 < 0) continue;148149Vec<3> rs = v0 + lam3 * n;150151double lam1 = (faces[i].w1 * rs);152double lam2 = (faces[i].w2 * rs);153if (lam1 >= 0 && lam2 >= 0 && lam1+lam2 <= 1)154cnt++;155}156157}158159//(*testout) << " cnt = " << cnt%2 << endl;160return (cnt % 2) ? IS_INSIDE : IS_OUTSIDE;161}162163164165166void Polyhedra :: GetTangentialSurfaceIndices (const Point<3> & p,167ARRAY<int> & surfind, double eps) const168{169for (int i = 0; i < faces.Size(); i++)170{171const Point<3> & p1 = points[faces[i].pnums[0]];172173Vec<3> v0 = p - p1;174double lam3 = -(faces[i].nn * v0); // n->nn175176if (fabs (lam3) > eps) continue;177178double lam1 = (faces[i].w1 * v0);179double lam2 = (faces[i].w2 * v0);180181if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam1+lam2 <= 1+eps_base1)182if (!surfind.Contains (GetSurfaceId(i)))183surfind.Append (GetSurfaceId(i));184}185186}187188189190INSOLID_TYPE Polyhedra :: VecInSolid (const Point<3> & p,191const Vec<3> & v,192double eps) const193{194ARRAY<int> point_on_faces;195INSOLID_TYPE res(DOES_INTERSECT);196197Vec<3> vn = v;198vn.Normalize();199for (int i = 0; i < faces.Size(); i++)200{201const Point<3> & p1 = points[faces[i].pnums[0]];202203Vec<3> v0 = p - p1;204double lam3 = -(faces[i].nn * v0); // n->nn205206207if (fabs (lam3) > eps) continue;208//(*testout) << "lam3 <= eps" << endl;209210double lam1 = (faces[i].w1 * v0);211double lam2 = (faces[i].w2 * v0);212213if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam1+lam2 <= 1+eps_base1)214{215point_on_faces.Append(i);216217double scal = vn * faces[i].nn; // n->nn218219res = DOES_INTERSECT;220if (scal > eps_base1) res = IS_OUTSIDE;221if (scal < -eps_base1) res = IS_INSIDE;222}223}224225//(*testout) << "point_on_faces.Size() " << point_on_faces.Size()226// << " res " << res << endl;227228if (point_on_faces.Size() == 0)229return PointInSolid (p, 0);230if (point_on_faces.Size() == 1)231return res;232233234235236double mindist(0);237bool first = true;238239for(int i=0; i<point_on_faces.Size(); i++)240{241for(int j=0; j<3; j++)242{243double dist = Dist(p,points[faces[point_on_faces[i]].pnums[j]]);244if(dist > eps && (first || dist < mindist))245{246mindist = dist;247first = false;248}249}250}251252Point<3> p2 = p + (1e-2*mindist) * vn;253res = PointInSolid (p2, eps);254255// (*testout) << "mindist " << mindist << " res " << res << endl;256257return res;258259260}261262263/*264INSOLID_TYPE Polyhedra :: VecInSolid2 (const Point<3> & p,265const Vec<3> & v1,266const Vec<3> & v2,267double eps) const268{269INSOLID_TYPE res;270271res = VecInSolid(p,v1,eps);272if(res != DOES_INTERSECT)273return res;274275int point_on_n_faces = 0;276277Vec<3> v1n = v1;278v1n.Normalize();279Vec<3> v2n = v2;280v2n.Normalize();281282283for (int i = 0; i < faces.Size(); i++)284{285const Point<3> & p1 = points[faces[i].pnums[0]];286287Vec<3> v0 = p - p1;288double lam3 = -(faces[i].n * v0);289290if (fabs (lam3) > eps) continue;291292double lam1 = (faces[i].w1 * v0);293double lam2 = (faces[i].w2 * v0);294295if (lam1 >= -eps && lam2 >= -eps && lam1+lam2 <= 1+eps)296{297double scal1 = v1n * faces[i].n;298if (fabs (scal1) > eps) continue;299300301point_on_n_faces++;302303double scal2 = v2n * faces[i].n;304res = DOES_INTERSECT;305if (scal2 > eps) res = IS_OUTSIDE;306if (scal2 < -eps) res = IS_INSIDE;307}308}309310if (point_on_n_faces == 1)311return res;312313cerr << "primitive::vecinsolid2 makes nonsense for polyhedra" << endl;314315return Primitive :: VecInSolid2 (p, v1, v2, eps);316}317*/318319320321INSOLID_TYPE Polyhedra :: VecInSolid2 (const Point<3> & p,322const Vec<3> & v1,323const Vec<3> & v2,324double eps) const325{326//(*testout) << "VecInSolid2 eps " << eps << endl;327INSOLID_TYPE res = VecInSolid(p,v1,eps);328//(*testout) << "VecInSolid = " <<res <<endl;329330if(res != DOES_INTERSECT)331return res;332333int point_on_n_faces = 0;334335Vec<3> v1n = v1;336v1n.Normalize();337Vec<3> v2n = v2 - (v2 * v1n) * v1n;338v2n.Normalize();339340double cosv2, cosv2max = -1;341342343for (int i = 0; i < faces.Size(); i++)344{345const Point<3> & p1 = points[faces[i].pnums[0]];346347Vec<3> v0 = p - p1;348if (fabs (faces[i].nn * v0) > eps) continue; // n->nn349if (fabs (v1n * faces[i].nn) > eps_base1) continue; // n->nn350351double lam1 = (faces[i].w1 * v0);352double lam2 = (faces[i].w2 * v0);353354if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam1+lam2 <= 1+eps_base1)355{356// v1 is in face357358Point<3> fc = Center (points[faces[i].pnums[0]],359points[faces[i].pnums[1]],360points[faces[i].pnums[2]]);361362Vec<3> vpfc = fc - p;363cosv2 = (v2n * vpfc) / vpfc.Length();364if (cosv2 > cosv2max)365{366cosv2max = cosv2;367point_on_n_faces++;368369double scal2 = v2n * faces[i].nn; // n->nn370res = DOES_INTERSECT;371if (scal2 > eps_base1) res = IS_OUTSIDE;372if (scal2 < -eps_base1) res = IS_INSIDE;373374}375}376}377378if (point_on_n_faces >= 1)379return res;380381(*testout) << "primitive::vecinsolid2 makes nonsense for polyhedra" << endl;382cerr << "primitive::vecinsolid2 makes nonsense for polyhedra" << endl;383384return Primitive :: VecInSolid2 (p, v1, v2, eps);385}386387388389void Polyhedra :: GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,390ARRAY<int> & surfind, double eps) const391{392Vec<3> v1n = v1;393v1n.Normalize();394Vec<3> v2n = v2; // - (v2 * v1n) * v1n;395v2n.Normalize();396397398for (int i = 0; i < faces.Size(); i++)399{400const Point<3> & p1 = points[faces[i].pnums[0]];401402Vec<3> v0 = p - p1;403if (fabs (v0 * faces[i].nn) > eps) continue; // n->nn404if (fabs (v1n * faces[i].nn) > eps_base1) continue; // n->nn405if (fabs (v2n * faces[i].nn) > eps_base1) continue; // n->nn406407double lam01 = (faces[i].w1 * v0);408double lam02 = (faces[i].w2 * v0);409double lam03 = 1-lam01-lam02;410double lam11 = (faces[i].w1 * v1);411double lam12 = (faces[i].w2 * v1);412double lam13 = -lam11-lam12;413double lam21 = (faces[i].w1 * v2);414double lam22 = (faces[i].w2 * v2);415double lam23 = -lam21-lam22;416417bool ok1 = lam01 > eps_base1 ||418lam01 > -eps_base1 && lam11 > eps_base1 ||419lam01 > -eps_base1 && lam11 > -eps_base1 && lam21 > eps_base1;420421bool ok2 = lam02 > eps_base1 ||422lam02 > -eps_base1 && lam12 > eps_base1 ||423lam02 > -eps_base1 && lam12 > -eps_base1 && lam22 > eps_base1;424425bool ok3 = lam03 > eps_base1 ||426lam03 > -eps_base1 && lam13 > eps_base1 ||427lam03 > -eps_base1 && lam13 > -eps_base1 && lam23 > eps_base1;428429if (ok1 && ok2 && ok3)430{431if (!surfind.Contains (GetSurfaceId(faces[i].planenr)))432surfind.Append (GetSurfaceId(faces[i].planenr));433}434}435}436437438439440441442443444445446447448void Polyhedra :: GetPrimitiveData (const char *& classname,449ARRAY<double> & coeffs) const450{451classname = "Polyhedra";452coeffs.SetSize(0);453coeffs.Append (points.Size());454coeffs.Append (faces.Size());455coeffs.Append (planes.Size());456457/*458int i, j;459for (i = 1; i <= planes.Size(); i++)460{461planes.Elem(i)->Print (*testout);462}463for (i = 1; i <= faces.Size(); i++)464{465(*testout) << "face " << i << " has plane " << faces.Get(i).planenr << endl;466for (j = 1; j <= 3; j++)467(*testout) << points.Get(faces.Get(i).pnums[j-1]);468(*testout) << endl;469}470*/471}472473void Polyhedra :: SetPrimitiveData (ARRAY<double> & coeffs)474{475;476}477478void Polyhedra :: Reduce (const BoxSphere<3> & box)479{480for (int i = 0; i < planes.Size(); i++)481surfaceactive[i] = 0;482483for (int i = 0; i < faces.Size(); i++)484if (FaceBoxIntersection (i, box))485surfaceactive[faces[i].planenr] = 1;486}487488void Polyhedra :: UnReduce ()489{490for (int i = 0; i < planes.Size(); i++)491surfaceactive[i] = 1;492}493494int Polyhedra :: AddPoint (const Point<3> & p)495{496if(points.Size() == 0)497poly_bbox.Set(p);498else499poly_bbox.Add(p);500501return points.Append (p);502}503504int Polyhedra :: AddFace (int pi1, int pi2, int pi3, int inputnum)505{506(*testout) << "polyhedra, add face " << pi1 << ", " << pi2 << ", " << pi3 << endl;507508if(pi1 == pi2 || pi2 == pi3 || pi3 == pi1)509{510ostringstream msg;511msg << "Illegal point numbers for polyhedron face: " << pi1+1 << ", " << pi2+1 << ", " << pi3+1;512throw NgException(msg.str());513}514515faces.Append (Face (pi1, pi2, pi3, points, inputnum));516517Point<3> p1 = points[pi1];518Point<3> p2 = points[pi2];519Point<3> p3 = points[pi3];520521Vec<3> v1 = p2 - p1;522Vec<3> v2 = p3 - p1;523524Vec<3> n = Cross (v1, v2);525n.Normalize();526527Plane pl (p1, n);528// int inverse;529// int identicto = -1;530// for (int i = 0; i < planes.Size(); i++)531// if (pl.IsIdentic (*planes[i], inverse, 1e-9*max3(v1.Length(),v2.Length(),Dist(p2,p3))))532// {533// if (!inverse)534// identicto = i;535// }536// // cout << "is identic = " << identicto << endl;537// identicto = -1; // changed April 10, JS538539// if (identicto != -1)540// faces.Last().planenr = identicto;541// else542{543planes.Append (new Plane (p1, n));544surfaceactive.Append (1);545surfaceids.Append (0);546faces.Last().planenr = planes.Size()-1;547}548549// (*testout) << "is plane nr " << faces.Last().planenr << endl;550551return faces.Size();552}553554555556int Polyhedra :: FaceBoxIntersection (int fnr, const BoxSphere<3> & box) const557{558/*559(*testout) << "check face box intersection, fnr = " << fnr << endl;560(*testout) << "box = " << box << endl;561(*testout) << "face-box = " << faces[fnr].bbox << endl;562*/563564if (!faces[fnr].bbox.Intersect (box))565return 0;566567const Point<3> & p1 = points[faces[fnr].pnums[0]];568const Point<3> & p2 = points[faces[fnr].pnums[1]];569const Point<3> & p3 = points[faces[fnr].pnums[2]];570571double dist2 = MinDistTP2 (p1, p2, p3, box.Center());572/*573(*testout) << "p1 = " << p1 << endl;574(*testout) << "p2 = " << p2 << endl;575(*testout) << "p3 = " << p3 << endl;576577(*testout) << "box.Center() = " << box.Center() << endl;578(*testout) << "center = " << box.Center() << endl;579(*testout) << "dist2 = " << dist2 << endl;580(*testout) << "diam = " << box.Diam() << endl;581*/582if (dist2 < sqr (box.Diam()/2))583{584// (*testout) << "intersect" << endl;585return 1;586}587return 0;588}589590591void Polyhedra :: GetPolySurfs(ARRAY < ARRAY<int> * > & polysurfs)592{593int maxnum = -1;594595for(int i = 0; i<faces.Size(); i++)596{597if(faces[i].inputnr > maxnum)598maxnum = faces[i].inputnr;599}600601polysurfs.SetSize(maxnum+1);602for(int i=0; i<polysurfs.Size(); i++)603polysurfs[i] = new ARRAY<int>;604605for(int i = 0; i<faces.Size(); i++)606polysurfs[faces[i].inputnr]->Append(faces[i].planenr);607}608609610void Polyhedra::CalcSpecialPoints (ARRAY<Point<3> > & pts) const611{612for (int i = 0; i < points.Size(); i++)613pts.Append (points[i]);614}615616617void Polyhedra :: AnalyzeSpecialPoint (const Point<3> & pt,618ARRAY<Point<3> > & specpts) const619{620;621}622623Vec<3> Polyhedra :: SpecialPointTangentialVector (const Point<3> & p, int s1, int s2) const624{625const double eps = 1e-10*poly_bbox.Diam();626627for (int fi1 = 0; fi1 < faces.Size(); fi1++)628for (int fi2 = 0; fi2 < faces.Size(); fi2++)629{630int si1 = faces[fi1].planenr;631int si2 = faces[fi2].planenr;632633if (surfaceids[si1] != s1 || surfaceids[si2] != s2) continue;634635//(*testout) << "check pair fi1/fi2 " << fi1 << "/" << fi2 << endl;636637Vec<3> n1 = GetSurface(si1) . GetNormalVector (p);638Vec<3> n2 = GetSurface(si2) . GetNormalVector (p);639Vec<3> t = Cross (n1, n2);640641//(*testout) << "t = " << t << endl;642643644/*645int samepts = 0;646for (int j = 0; j < 3; j++)647for (int k = 0; k < 3; k++)648if (Dist(points[faces[fi1].pnums[j]],649points[faces[fi2].pnums[k]]) < eps)650samepts++;651if (samepts < 2) continue;652*/653654bool shareedge = false;655for(int j = 0; !shareedge && j < 3; j++)656{657Vec<3> v1 = points[faces[fi1].pnums[(j+1)%3]] - points[faces[fi1].pnums[j]];658double smax = v1.Length();659v1 *= 1./smax;660661int pospos;662if(fabs(v1(0)) > 0.5)663pospos = 0;664else if(fabs(v1(1)) > 0.5)665pospos = 1;666else667pospos = 2;668669double sp = (p(pospos) - points[faces[fi1].pnums[j]](pospos)) / v1(pospos);670if(sp < -eps || sp > smax+eps)671continue;672673for (int k = 0; !shareedge && k < 3; k ++)674{675Vec<3> v2 = points[faces[fi2].pnums[(k+1)%3]] - points[faces[fi2].pnums[k]];676v2.Normalize();677if(v2 * v1 > 0)678v2 -= v1;679else680v2 += v1;681682//(*testout) << "v2.Length2() " << v2.Length2() << endl;683684if(v2.Length2() > 1e-18)685continue;686687double sa,sb;688689sa = (points[faces[fi2].pnums[k]](pospos) - points[faces[fi1].pnums[j]](pospos)) / v1(pospos);690sb = (points[faces[fi2].pnums[(k+1)%3]](pospos) - points[faces[fi1].pnums[j]](pospos)) / v1(pospos);691692693if(Dist(points[faces[fi1].pnums[j]] + sa*v1, points[faces[fi2].pnums[k]]) > eps)694continue;695696if(sa > sb)697{698double aux = sa; sa = sb; sb = aux;699}700701//testout->precision(20);702//(*testout) << "sa " << sa << " sb " << sb << " smax " << smax << " sp " << sp << " v1 " << v1 << endl;703//testout->precision(8);704705706shareedge = (sa < -eps && sb > eps) ||707(sa < smax-eps && sb > smax+eps) ||708(sa > -eps && sb < smax+eps);709710if(!shareedge)711continue;712713sa = max2(sa,0.);714sb = min2(sb,smax);715716if(sp < sa+eps)717shareedge = (t * v1 > 0);718else if (sp > sb-eps)719shareedge = (t * v1 < 0);720721}722}723if (!shareedge) continue;724725t.Normalize();726727728return t;729}730731return Vec<3> (0,0,0);732}733734735}736737738739740