Path: blob/devel/ElmerGUI/netgen/libsrc/csg/specpoin.cpp
3206 views
#include <mystdlib.h>1#include <meshing.hpp>2#include <csg.hpp>345/*6Special Point calculation uses the global Flags:78relydegtest when to rely on degeneration ?9calccp calculate points of intersection ?10cpeps1 eps for degenerated poi11calcep calculate points of extreme coordinates ?12epeps1 eps for degenerated edge13epeps2 eps for axis parallel pec14epspointdist eps for distance of special points15*/161718#undef DEVELOP19//#define DEVELOP202122namespace netgen23{24ARRAY<Box<3> > boxes;252627void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp);28293031SpecialPoint :: SpecialPoint (const SpecialPoint & sp)32{33p = sp.p;34v = sp.v;35s1 = sp.s1;36s2 = sp.s2;37s1_orig = sp.s1_orig;38s2_orig = sp.s2_orig;39layer = sp.layer;40unconditional = sp.unconditional;41}4243SpecialPoint & SpecialPoint :: operator= (const SpecialPoint & sp)44{45p = sp.p;46v = sp.v;47s1 = sp.s1;48s2 = sp.s2;49s1_orig = sp.s1_orig;50s2_orig = sp.s2_orig;51layer = sp.layer;52unconditional = sp.unconditional;53return *this;54}555657void SpecialPoint :: Print (ostream & str) const58{59str << "p = " << p << " v = " << v60<< " s1/s2 = " << s1 << "/" << s2;61str << " layer = " << layer62<< " unconditional = " << unconditional63<< endl;64}656667static ARRAY<int> numprim_hist;6869SpecialPointCalculation :: SpecialPointCalculation ()70{71ideps = 1e-9;72}7374void SpecialPointCalculation ::75CalcSpecialPoints (const CSGeometry & ageometry,76ARRAY<MeshPoint> & apoints)77{78geometry = &ageometry;79points = &apoints;8081size = geometry->MaxSize();82(*testout) << "Find Special Points" << endl;83(*testout) << "maxsize = " << size << endl;8485cpeps1 = 1e-6;86epeps1 = 1e-3;87epeps2 = 1e-6;8889epspointdist2 = sqr (size * 1e-8);90relydegtest = size * 1e-4;919293BoxSphere<3> box (Point<3> (-size, -size, -size),94Point<3> ( size, size, size));9596box.CalcDiamCenter();97PrintMessage (3, "main-solids: ", geometry->GetNTopLevelObjects());9899numprim_hist.SetSize (geometry->GetNSurf()+1);100numprim_hist = 0;101102for (int i = 0; i < geometry->GetNTopLevelObjects(); i++)103{104const TopLevelObject * tlo = geometry->GetTopLevelObject(i);105106(*testout) << "tlo " << i << ":" << endl107<< *tlo->GetSolid() << endl;108109if (tlo->GetSolid())110{111ARRAY<Point<3> > hpts;112tlo->GetSolid()->CalcOnePrimitiveSpecialPoints (box, hpts);113// if (hpts.Size())114// cout << "oneprimitivespecialpoints = " << hpts << endl;115for (int j = 0; j < hpts.Size(); j++)116AddPoint (hpts[j], tlo->GetLayer());117}118119CalcSpecialPointsRec (tlo->GetSolid(), tlo->GetLayer(),120box, 1, 1, 1);121}122123124geometry->DeleteIdentPoints();125for (int i = 0; i < geometry->GetNIdentifications(); i++)126{127CloseSurfaceIdentification * ident =128dynamic_cast<CloseSurfaceIdentification * >(geometry->identifications[i]);129130if(!ident || !ident->IsSkewIdentification())131continue;132133for(int j=0; j<points->Size(); j++)134{135if(fabs(ident->GetSurface1().CalcFunctionValue((*points)[j])) < 1e-15)136{137Point<3> auxpoint = (*points)[j];138ident->GetSurface2().SkewProject(auxpoint,ident->GetDirection());139geometry->AddIdentPoint(auxpoint);140geometry->AddIdentPoint((*points)[j]);141AddPoint (auxpoint,1);142143#ifdef DEVELOP144(*testout) << "added identpoint " << auxpoint << "; proj. of "145<< (*points)[j] << endl;146#endif147break;148}149}150}151152153// add user point:154for (int i = 0; i < geometry->GetNUserPoints(); i++)155AddPoint (geometry->GetUserPoint(i), 1);156157158PrintMessage (3, "Found points ", apoints.Size());159160for (int i = 0; i < boxesinlevel.Size(); i++)161(*testout) << "level " << i << " has "162<< boxesinlevel[i] << " boxes" << endl;163(*testout) << "numprim_histogramm = " << endl << numprim_hist << endl;164}165166167168void SpecialPointCalculation ::169CalcSpecialPointsRec (const Solid * sol, int layer,170const BoxSphere<3> & box,171int level, bool calccp, bool calcep)172{173// boxes.Append (box);174175#ifdef DEVELOP176*testout << "lev " << level << ", box = " << box << endl;177*testout << "calccp = " << calccp << ", calcep = " << calcep << endl;178*testout << "locsol = " << *sol << endl;179#endif180181if (multithread.terminate)182{183*testout << "boxes = " << boxes << endl;184*testout << "boxesinlevel = " << boxesinlevel << endl;185throw NgException ("Meshing stopped");186}187188189if (!sol) return;190191if (level >= 100)192{193MyStr err =194MyStr("Problems in CalcSpecialPoints\nPoint: ") + MyStr (box.Center());195throw NgException (err.c_str());196}197198199bool decision;200bool possiblecrossp, possibleexp; // possible cross or extremalpoint201bool surecrossp = 0, sureexp = 0; // sure ...202203static ARRAY<int> locsurf; // attention: array is static204205static int cntbox = 0;206cntbox++;207208if (level <= boxesinlevel.Size())209boxesinlevel.Elem(level)++;210else211boxesinlevel.Append (1);212213/*214numprim = sol -> NumPrimitives();215sol -> GetSurfaceIndices (locsurf);216*/217218geometry -> GetIndependentSurfaceIndices (sol, box, locsurf);219int numprim = locsurf.Size();220221#ifdef DEVELOP222(*testout) << "numprim = " << numprim << endl;223#endif224225numprim_hist[numprim]++;226227Point<3> p = box.Center();228229230// explicit solution for planes only and at most one quadratic231if (numprim <= 5)232{233int nplane = 0, nquad = 0, quadi = -1;234const QuadraticSurface *qsurf = 0, *qsurfi;235236for (int i = 0; i < numprim; i++)237{238qsurfi = dynamic_cast<const QuadraticSurface*>239(geometry->GetSurface(locsurf[i]));240241if (qsurfi) nquad++;242if (dynamic_cast<const Plane*> (qsurfi))243nplane++;244else245{246quadi = i;247qsurf = qsurfi;248}249}250251/*252if (nquad == numprim && nplane == numprim-2)253return;254*/255256#ifdef DEVELOP257(*testout) << "nquad " << nquad << " nplane " << nplane << endl;258#endif259260if (nquad == numprim && nplane >= numprim-1)261{262ARRAY<Point<3> > pts;263ARRAY<int> surfids;264265for (int k1 = 0; k1 < numprim - 2; k1++)266for (int k2 = k1 + 1; k2 < numprim - 1; k2++)267for (int k3 = k2 + 1; k3 < numprim; k3++)268if (k1 != quadi && k2 != quadi && k3 != quadi)269{270ComputeCrossPoints (dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k1])),271dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k2])),272dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k3])),273pts);274275for (int j = 0; j < pts.Size(); j++)276if (Dist (pts[j], box.Center()) < box.Diam()/2)277{278Solid * tansol;279sol -> TangentialSolid (pts[j], tansol, surfids, 1e-9*size);280281if(!tansol)282continue;283284bool ok1 = false, ok2 = false, ok3 = false;285int rep1 = geometry->GetSurfaceClassRepresentant(locsurf[k1]);286int rep2 = geometry->GetSurfaceClassRepresentant(locsurf[k2]);287int rep3 = geometry->GetSurfaceClassRepresentant(locsurf[k3]);288for(int jj=0; jj<surfids.Size(); jj++)289{290int actrep = geometry->GetSurfaceClassRepresentant(surfids[jj]);291if(actrep == rep1) ok1 = true;292if(actrep == rep2) ok2 = true;293if(actrep == rep3) ok3 = true;294}295296297if (tansol && ok1 && ok2 && ok3)298// if (sol -> IsIn (pts[j], 1e-6*size) && !sol->IsStrictIn (pts[j], 1e-6*size))299{300if (AddPoint (pts[j], layer))301(*testout) << "cross point found, 1: " << pts[j] << endl;302}303delete tansol;304}305}306307308if (qsurf)309{310for (int k1 = 0; k1 < numprim - 1; k1++)311for (int k2 = k1 + 1; k2 < numprim; k2++)312if (k1 != quadi && k2 != quadi)313{314ComputeCrossPoints (dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k1])),315dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k2])),316qsurf, pts);317//(*testout) << "checking pot. crosspoints: " << pts << endl;318319for (int j = 0; j < pts.Size(); j++)320if (Dist (pts[j], box.Center()) < box.Diam()/2)321{322Solid * tansol;323sol -> TangentialSolid (pts[j], tansol, surfids, 1e-9*size);324325if(!tansol)326continue;327328bool ok1 = false, ok2 = false, ok3 = true;//false;329int rep1 = geometry->GetSurfaceClassRepresentant(locsurf[k1]);330int rep2 = geometry->GetSurfaceClassRepresentant(locsurf[k2]);331//int rep3 = geometry->GetSurfaceClassRepresentant(quadi);332for(int jj=0; jj<surfids.Size(); jj++)333{334int actrep = geometry->GetSurfaceClassRepresentant(surfids[jj]);335if(actrep == rep1) ok1 = true;336if(actrep == rep2) ok2 = true;337//if(actrep == rep3) ok3 = true;338}339340341if (tansol && ok1 && ok2 && ok3)342//if (sol -> IsIn (pts[j], 1e-6*size) && !sol->IsStrictIn (pts[j], 1e-6*size) )343{344if (AddPoint (pts[j], layer))345(*testout) << "cross point found, 2: " << pts[j] << endl;346}347delete tansol;348}349}350351352for (int k1 = 0; k1 < numprim; k1++)353if (k1 != quadi)354{355ComputeExtremalPoints (dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k1])),356qsurf, pts);357358for (int j = 0; j < pts.Size(); j++)359if (Dist (pts[j], box.Center()) < box.Diam()/2)360{361Solid * tansol;362sol -> TangentialSolid (pts[j], tansol, surfids, 1e-9*size);363if (tansol)364// sol -> IsIn (pts[j], 1e-6*size) && !sol->IsStrictIn (pts[j], 1e-6*size) )365{366if (AddPoint (pts[j], layer))367(*testout) << "extremal point found, 1: " << pts[j] << endl;368}369delete tansol;370}371}372}373374return;375}376}377378379380possiblecrossp = (numprim >= 3) && calccp;381surecrossp = 0;382383if (possiblecrossp && (locsurf.Size() <= 5 || level > 50))384{385decision = 1;386surecrossp = 0;387388for (int k1 = 1; k1 <= locsurf.Size() - 2; k1++)389for (int k2 = k1 + 1; k2 <= locsurf.Size() - 1; k2++)390for (int k3 = k2 + 1; k3 <= locsurf.Size(); k3++)391{392int nc, deg;393nc = CrossPointNewtonConvergence394(geometry->GetSurface(locsurf.Get(k1)),395geometry->GetSurface(locsurf.Get(k2)),396geometry->GetSurface(locsurf.Get(k3)), box );397398deg = CrossPointDegenerated399(geometry->GetSurface(locsurf.Get(k1)),400geometry->GetSurface(locsurf.Get(k2)),401geometry->GetSurface(locsurf.Get(k3)), box );402403if (!nc && !deg) decision = 0;404if (nc) surecrossp = 1;405}406407#ifdef DEVELOP408(*testout) << "dec = " << decision << ", surcp = " << surecrossp << endl;409#endif410411if (decision && surecrossp)412{413for (int k1 = 1; k1 <= locsurf.Size() - 2; k1++)414for (int k2 = k1 + 1; k2 <= locsurf.Size() - 1; k2++)415for (int k3 = k2 + 1; k3 <= locsurf.Size(); k3++)416{417if (CrossPointNewtonConvergence418(geometry->GetSurface(locsurf.Get(k1)),419geometry->GetSurface(locsurf.Get(k2)),420geometry->GetSurface(locsurf.Get(k3)), box ) )421{422423Point<3> pp = p;424CrossPointNewton425(geometry->GetSurface(locsurf.Get(k1)),426geometry->GetSurface(locsurf.Get(k2)),427geometry->GetSurface(locsurf.Get(k3)), pp);428429BoxSphere<3> hbox (pp, pp);430hbox.Increase (1e-8*size);431432if (pp(0) > box.PMin()(0) - 1e-5*size &&433pp(0) < box.PMax()(0) + 1e-5*size &&434pp(1) > box.PMin()(1) - 1e-5*size &&435pp(1) < box.PMax()(1) + 1e-5*size &&436pp(2) > box.PMin()(2) - 1e-5*size &&437pp(2) < box.PMax()(2) + 1e-5*size &&438sol -> IsIn (pp, 1e-6*size) && !sol->IsStrictIn (pp, 1e-6*size) &&439!CrossPointDegenerated440(geometry->GetSurface(locsurf.Get(k1)),441geometry->GetSurface(locsurf.Get(k2)),442geometry->GetSurface(locsurf.Get(k3)), hbox ))443444{445// AddCrossPoint (locsurf, sol, p);446BoxSphere<3> boxp (pp, pp);447boxp.Increase (1e-3*size);448boxp.CalcDiamCenter();449ARRAY<int> locsurf2;450451geometry -> GetIndependentSurfaceIndices (sol, boxp, locsurf2);452453bool found1 = false, found2 = false, found3 = false;454for (int i = 0; i < locsurf2.Size(); i++)455{456if (locsurf2[i] == locsurf.Get(k1)) found1 = true;457if (locsurf2[i] == locsurf.Get(k2)) found2 = true;458if (locsurf2[i] == locsurf.Get(k3)) found3 = true;459}460461if (found1 && found2 && found3)462if (AddPoint (pp, layer))463{464(*testout) << "Crosspoint found: " << pp465<< " diam = " << box.Diam()466<< ", surfs: "467<< locsurf.Get(k1) << ","468<< locsurf.Get(k2) << ","469<< locsurf.Get(k3) << endl;470}471}472}473}474}475476if (decision)477possiblecrossp = 0;478}479480481possibleexp = (numprim >= 2) && calcep;482483// (*testout) << "l = " << level << "locsize = " << locsurf.Size() << " possexp = " << possibleexp << "\n";484if (possibleexp && (numprim <= 5 || level >= 50))485{486decision = 1;487sureexp = 0;488489/*490(*testout) << "extremal surfs = ";491for (int k5 = 0; k5 < locsurf.Size(); k5++)492(*testout) << typeid(*geometry->GetSurface(locsurf[k5])).name() << " ";493(*testout) << "\n";494*/495496for (int k1 = 0; k1 < locsurf.Size() - 1; k1++)497for (int k2 = k1+1; k2 < locsurf.Size(); k2++)498{499const Surface * surf1 = geometry->GetSurface(locsurf[k1]);500const Surface * surf2 = geometry->GetSurface(locsurf[k2]);501/*502(*testout) << "edgecheck, types = " << typeid(*surf1).name() << ", " << typeid(*surf2).name()503<< "edge-newton-conv = " << EdgeNewtonConvergence (surf1, surf2, p)504<< "edge-deg = " << EdgeDegenerated (surf1, surf2, box)505<< "\n";506*/507508if (EdgeNewtonConvergence (surf1, surf2, p) )509sureexp = 1;510else511{512if (!EdgeDegenerated (surf1, surf2, box))513decision = 0;514}515}516517// (*testout) << "l = " << level << " dec/sureexp = " << decision << sureexp << endl;518519if (decision && sureexp)520{521for (int k1 = 0; k1 < locsurf.Size() - 1; k1++)522for (int k2 = k1+1; k2 < locsurf.Size(); k2++)523{524const Surface * surf1 = geometry->GetSurface(locsurf[k1]);525const Surface * surf2 = geometry->GetSurface(locsurf[k2]);526527if (EdgeNewtonConvergence (surf1, surf2, p))528{529EdgeNewton (surf1, surf2, p);530531Point<3> pp;532if (IsEdgeExtremalPoint (surf1, surf2, p, pp, box.Diam()/2))533{534(*testout) << "extremalpoint (nearly) found:" << pp << endl;535536if (Dist (pp, box.Center()) < box.Diam()/2 &&537sol -> IsIn (pp, 1e-6*size) && !sol->IsStrictIn (pp, 1e-6*size) )538{539if (AddPoint (pp, layer))540(*testout) << "Extremal point found: " << pp << endl;//"(eps="<<1e-9*size<<")"<< endl;541}542}543}544}545}546if (decision)547possibleexp = 0;548}549550551// (*testout) << "l = " << level << " poss cp/ep sure exp = " << possiblecrossp << " " << possibleexp << " " << sureexp << "\n";552if (possiblecrossp || possibleexp)553{554BoxSphere<3> sbox;555for (int i = 0; i < 8; i++)556{557box.GetSubBox (i, sbox);558sbox.Increase (1e-4 * sbox.Diam());559560Solid * redsol = sol -> GetReducedSolid (sbox);561562if (redsol)563{564CalcSpecialPointsRec (redsol, layer, sbox, level+1, calccp, calcep);565delete redsol;566}567}568}569}570571572573574575/******* Tests for Point of intersection **********************/576577578579bool SpecialPointCalculation ::580CrossPointNewtonConvergence (const Surface * f1,581const Surface * f2,582const Surface * f3,583const BoxSphere<3> & box)584{585Vec<3> grad, rs, x;586Mat<3> jacobi, inv;587Point<3> p = box.Center();588589f1->CalcGradient (p, grad);590jacobi(0,0) = grad(0);591jacobi(0,1) = grad(1);592jacobi(0,2) = grad(2);593594f2->CalcGradient (p, grad);595jacobi(1,0) = grad(0);596jacobi(1,1) = grad(1);597jacobi(1,2) = grad(2);598599f3->CalcGradient (p, grad);600jacobi(2,0) = grad(0);601jacobi(2,1) = grad(1);602jacobi(2,2) = grad(2);603604if (fabs (Det (jacobi)) > 1e-8)605{606double gamma = f1 -> HesseNorm() + f2 -> HesseNorm() + f3 -> HesseNorm();607if (gamma == 0.0) return 1;608609CalcInverse (jacobi, inv);610611rs(0) = f1->CalcFunctionValue (p);612rs(1) = f2->CalcFunctionValue (p);613rs(2) = f3->CalcFunctionValue (p);614615x = inv * rs;616617double beta = 0;618for (int i = 0; i < 3; i++)619{620double sum = 0;621for (int j = 0; j < 3; j++)622sum += fabs (inv(i,j));623if (sum > beta) beta = sum;624}625double eta = Abs (x);626627628#ifdef DEVELOP629*testout << "check Newton: " << "beta = " << beta << ", gamma = " << gamma << ", eta = " << eta << endl;630double rad = 1.0 / (beta * gamma);631*testout << "rad = " << rad << endl;632#endif633634return (beta * gamma * eta < 0.1) && (2 > box.Diam()*beta*gamma);635}636return 0;637638}639640641642643bool SpecialPointCalculation ::644CrossPointDegenerated (const Surface * f1,645const Surface * f2,646const Surface * f3,647const BoxSphere<3> & box) const648{649Mat<3> mat;650Vec<3> g1, g2, g3;651double normprod;652653if (box.Diam() > relydegtest) return 0;654655f1->CalcGradient (box.Center(), g1);656normprod = Abs2 (g1);657658f2->CalcGradient (box.Center(), g2);659normprod *= Abs2 (g2);660661f3->CalcGradient (box.Center(), g3);662normprod *= Abs2 (g3);663664for (int i = 0; i < 3; i++)665{666mat(i,0) = g1(i);667mat(i,1) = g2(i);668mat(i,2) = g3(i);669}670671return sqr (Det (mat)) < sqr(cpeps1) * normprod;672}673674675676677678void SpecialPointCalculation :: CrossPointNewton (const Surface * f1,679const Surface * f2,680const Surface * f3, Point<3> & p)681{682Vec<3> g1, g2, g3;683Vec<3> rs, sol;684Mat<3> mat;685686int i = 10;687while (i > 0)688{689i--;690rs(0) = f1->CalcFunctionValue (p);691rs(1) = f2->CalcFunctionValue (p);692rs(2) = f3->CalcFunctionValue (p);693694f1->CalcGradient (p, g1);695f2->CalcGradient (p, g2);696f3->CalcGradient (p, g3);697698for (int j = 0; j < 3; j++)699{700mat(0, j) = g1(j);701mat(1, j) = g2(j);702mat(2, j) = g3(j);703}704mat.Solve (rs, sol);705if (sol.Length2() < 1e-24 && i > 1) i = 1;706707#ifdef DEVELOP708*testout << "CrossPointNewton, err = " << sol.Length2() << endl;709#endif710p -= sol;711}712}713714715716717/******* Tests for Point on edges **********************/718719720721722bool SpecialPointCalculation ::723EdgeNewtonConvergence (const Surface * f1, const Surface * f2,724const Point<3> & p)725{726Vec<3> g1, g2, sol;727Vec<2> vrs;728Mat<2,3> mat;729Mat<3,2> inv;730731f1->CalcGradient (p, g1);732f2->CalcGradient (p, g2);733734if ( sqr(g1 * g2) < (1 - 1e-8) * Abs2 (g1) * Abs2 (g2))735{736double gamma = f1 -> HesseNorm() + f2 -> HesseNorm();737if (gamma < 1e-32) return 1;738gamma = sqr (gamma);739740for (int i = 0; i < 3; i++)741{742mat(0,i) = g1(i);743mat(1,i) = g2(i);744}745746CalcInverse (mat, inv);747748vrs(0) = f1->CalcFunctionValue (p);749vrs(1) = f2->CalcFunctionValue (p);750sol = inv * vrs;751752double beta = 0;753for (int i = 0; i < 3; i++)754for (int j = 0; j < 2; j++)755beta += inv(i,j) * inv(i,j);756// beta = sqrt (beta);757758double eta = Abs2 (sol);759760// alpha = beta * gamma * eta;761return (beta * gamma * eta < 0.01);762}763return 0;764}765766767768769bool SpecialPointCalculation ::770EdgeDegenerated (const Surface * f1,771const Surface * f2,772const BoxSphere<3> & box) const773{774// perform newton steps. normals parallel ?775// if not decideable: return 0776777Point<3> p = box.Center();778Vec<3> g1, g2, sol;779Vec<2> vrs;780Mat<2,3> mat;781782int i = 20;783while (i > 0)784{785if (Dist2 (p, box.Center()) > sqr(box.Diam()))786return 0;787788i--;789vrs(0) = f1->CalcFunctionValue (p);790vrs(1) = f2->CalcFunctionValue (p);791792f1->CalcGradient (p, g1);793f2->CalcGradient (p, g2);794795if ( sqr (g1 * g2) > (1 - 1e-10) * Abs2 (g1) * Abs2 (g2))796return 1;797798for (int j = 0; j < 3; j++)799{800mat(0,j) = g1(j);801mat(1,j) = g2(j);802}803mat.Solve (vrs, sol);804805if (Abs2 (sol) < 1e-24 && i > 1) i = 1;806p -= sol;807}808809return 0;810}811812813814815816817void SpecialPointCalculation :: EdgeNewton (const Surface * f1,818const Surface * f2, Point<3> & p)819{820Vec<3> g1, g2, sol;821Vec<2> vrs;822Mat<2,3> mat;823824int i = 10;825while (i > 0)826{827i--;828vrs(0) = f1->CalcFunctionValue (p);829vrs(1) = f2->CalcFunctionValue (p);830831f1->CalcGradient (p, g1);832f2->CalcGradient (p, g2);833834//(*testout) << "p " << p << " f1 " << vrs(0) << " f2 " << vrs(1) << " g1 " << g1 << " g2 " << g2 << endl;835836for (int j = 0; j < 3; j++)837{838mat(0,j) = g1(j);839mat(1,j) = g2(j);840}841mat.Solve (vrs, sol);842843if (Abs2 (sol) < 1e-24 && i > 1) i = 1;844p -= sol;845}846}847848849850bool SpecialPointCalculation ::851IsEdgeExtremalPoint (const Surface * f1, const Surface * f2,852const Point<3> & p, Point<3> & pp, double rad)853{854Vec<3> g1, g2, t, t1, t2;855856f1->CalcGradient (p, g1);857f2->CalcGradient (p, g2);858859t = Cross (g1, g2);860t.Normalize();861862Point<3> p1 = p + rad * t;863Point<3> p2 = p - rad * t;864865EdgeNewton (f1, f2, p1);866EdgeNewton (f1, f2, p2);867868f1->CalcGradient (p1, g1);869f2->CalcGradient (p1, g2);870t1 = Cross (g1, g2);871t1.Normalize();872873f1->CalcGradient (p2, g1);874f2->CalcGradient (p2, g2);875t2 = Cross (g1, g2);876t2.Normalize();877878double val = 1e-8 * rad * rad;879for (int j = 0; j < 3; j++)880if ( (t1(j) * t2(j) < -val) )881{882pp = p;883ExtremalPointNewton (f1, f2, j+1, pp);884return 1;885}886887return 0;888}889890891892893894895896897898/********** Tests of Points of extremal coordinates ****************/899900901void SpecialPointCalculation :: ExtremalPointNewton (const Surface * f1,902const Surface * f2,903int dir, Point<3> & p)904{905Vec<3> g1, g2, v, curv;906Vec<3> rs, x, y1, y2, y;907Mat<3> h1, h2;908Mat<3> jacobi;909910int i = 50;911while (i > 0)912{913i--;914rs(0) = f1->CalcFunctionValue (p);915rs(1) = f2->CalcFunctionValue (p);916917f1 -> CalcGradient (p, g1);918f2 -> CalcGradient (p, g2);919920f1 -> CalcHesse (p, h1);921f2 -> CalcHesse (p, h2);922923v = Cross (g1, g2);924925rs(2) = v(dir-1);926927jacobi(0,0) = g1(0);928jacobi(0,1) = g1(1);929jacobi(0,2) = g1(2);930931jacobi(1,0) = g2(0);932jacobi(1,1) = g2(1);933jacobi(1,2) = g2(2);934935936switch (dir)937{938case 1:939{940y1(0) = 0;941y1(1) = g2(2);942y1(2) = -g2(1);943y2(0) = 0;944y2(1) = -g1(2);945y2(2) = g1(1);946break;947}948case 2:949{950y1(0) = -g2(2);951y1(1) = 0;952y1(2) = g2(0);953y2(0) = g1(2);954y2(1) = 0;955y2(2) = -g1(0);956break;957}958case 3:959{960y1(0) = g2(1);961y1(1) = -g2(0);962y1(2) = 0;963y2(0) = -g1(1);964y2(1) = g1(0);965y2(2) = 0;966break;967}968}969970y = h1 * y1 + h2 * y2;971972jacobi(2,0) = y(0);973jacobi(2,1) = y(1);974jacobi(2,2) = y(2);975976/*977(*testout) << "p " << p << " f1 " << rs(0) << " f2 " << rs(1) << endl978<< " jacobi " << jacobi << endl979<< " rhs " << rs << endl;980*/981982jacobi.Solve (rs, x);983984if (Abs2 (x) < 1e-24 && i > 1)985{986i = 1;987}988989990double minval(Abs2(rs)),minfac(1);991double startval(minval);992for(double fac = 1; fac > 1e-7; fac *= 0.6)993{994Point<3> testpoint = p-fac*x;995996rs(0) = f1->CalcFunctionValue (testpoint);997rs(1) = f2->CalcFunctionValue (testpoint);998999f1 -> CalcGradient (testpoint, g1);1000f2 -> CalcGradient (testpoint, g2);10011002v = Cross (g1, g2);10031004rs(2) = v(dir-1);10051006double val = Abs2(rs);10071008if(val < minval)1009{1010minfac = fac;1011if(val < 0.5 * startval)1012break;1013minval = val;1014}10151016}1017p -= minfac*x;101810191020//p -= x;1021}102210231024if (Abs2 (x) > 1e-20)1025{1026(*testout) << "Error: extremum Newton not convergent" << endl;1027(*testout) << "dir = " << dir << endl;1028(*testout) << "p = " << p << endl;1029(*testout) << "x = " << x << endl;1030}1031}10321033void SpecialPointCalculation ::1034ComputeCrossPoints (const Plane * plane1,1035const Plane * plane2,1036const Plane * plane3,1037ARRAY<Point<3> > & pts)1038{1039Mat<3> mat;1040Vec<3> rhs, sol;1041Point<3> p0(0,0,0);10421043pts.SetSize (0);1044for (int i = 0; i < 3; i++)1045{1046const Plane * pi(NULL);1047switch (i)1048{1049case 0: pi = plane1; break;1050case 1: pi = plane2; break;1051case 2: pi = plane3; break;1052}10531054double val;1055Vec<3> hvec;1056val = pi -> CalcFunctionValue(p0);1057pi -> CalcGradient (p0, hvec);10581059for (int j = 0; j < 3; j++)1060mat(i,j) = hvec(j);1061rhs(i) = -val;1062}10631064if (fabs (Det (mat)) > 1e-8)1065{1066mat.Solve (rhs, sol);1067pts.Append (Point<3> (sol));1068}1069}107010711072107310741075void SpecialPointCalculation ::1076ComputeCrossPoints (const Plane * plane1,1077const Plane * plane2,1078const QuadraticSurface * quadric,1079ARRAY<Point<3> > & pts)1080{1081Mat<2,3> mat;1082Mat<3,2> inv;1083Vec<2> rhs;1084Vec<3> sol, t;1085Point<3> p0(0,0,0);10861087pts.SetSize (0);1088for (int i = 0; i < 2; i++)1089{1090const Plane * pi(NULL);1091switch (i)1092{1093case 0: pi = plane1; break;1094case 1: pi = plane2; break;1095}10961097double val;1098Vec<3> hvec;1099val = pi -> CalcFunctionValue(p0);1100pi -> CalcGradient (p0, hvec);11011102for (int j = 0; j < 3; j++)1103mat(i,j) = hvec(j);1104rhs(i) = -val;1105}1106CalcInverse (mat, inv);1107sol = inv * rhs;1108t = Cross (mat.Row(0), mat.Row(1));11091110if (t.Length() > 1e-8)1111{1112Point<3> p (sol);1113// quadratic on p + s t = 01114double quad_a;1115Vec<3> quad_b;1116Mat<3> quad_c;11171118quad_a = quadric -> CalcFunctionValue(p);1119quadric -> CalcGradient (p, quad_b);1120quadric -> CalcHesse (p, quad_c);11211122double a, b, c;1123a = quad_a;1124b = quad_b * t;1125c = 0.5 * t * (quad_c * t);11261127// a + s b + s^2 c = 0;1128double disc = b*b-4*a*c;1129if (disc > 1e-10 * fabs (b))1130{1131disc = sqrt (disc);1132double s1 = (-b-disc) / (2*c);1133double s2 = (-b+disc) / (2*c);11341135pts.Append (p + s1 * t);1136pts.Append (p + s2 * t);1137}1138}1139}1140114111421143114411451146114711481149115011511152void SpecialPointCalculation ::1153ComputeExtremalPoints (const Plane * plane,1154const QuadraticSurface * quadric,1155ARRAY<Point<3> > & pts)1156{1157// 3 equations:1158// surf1 = 0 <===> plane_a + plane_b x = 0;1159// surf2 = 0 <===> quad_a + quad_b x + x^T quad_c x = 01160// (grad 1 x grad 2)(i) = 0 <====> (grad 1 x e_i) . grad_2 = 011611162pts.SetSize (0);11631164Point<3> p0(0,0,0);1165double plane_a, quad_a;1166Vec<3> plane_b, quad_b, ei;1167Mat<3> quad_c;11681169plane_a = plane -> CalcFunctionValue(p0);1170plane -> CalcGradient (p0, plane_b);11711172quad_a = quadric -> CalcFunctionValue(p0);1173quadric -> CalcGradient (p0, quad_b);1174quadric -> CalcHesse (p0, quad_c);1175for (int i = 0; i < 3; i++)1176for (int j = 0; j < 3; j++)1177quad_c(i,j) *= 0.5;11781179for (int dir = 0; dir <= 2; dir++)1180{1181ei = 0.0; ei(dir) = 1;1182Vec<3> v1 = Cross (plane_b, ei);11831184// grad_2 . v1 ... linear:1185double g2v1_c = v1 * quad_b;1186Vec<3> g2v1_l = 2.0 * (quad_c * v1);11871188// find line of two linear equations:11891190Vec<2> rhs;1191Vec<3> sol;1192Mat<2,3> mat;11931194for (int j = 0; j < 3; j++)1195{1196mat(0,j) = plane_b(j);1197mat(1,j) = g2v1_l(j);1198}1199rhs(0) = -plane_a;1200rhs(1) = -g2v1_c;12011202Vec<3> t = Cross (plane_b, g2v1_l);1203if (Abs2(t) > 0)1204{1205mat.Solve (rhs, sol);12061207// solve quadratic equation along line sol + alpha t ....1208double a = quad_a + quad_b * sol + sol * (quad_c * sol);1209double b = quad_b * t + 2 * (sol * (quad_c * t));1210double c = t * (quad_c * t);12111212// solve a + b alpha + c alpha^2:12131214if (fabs (c) > 1e-32)1215{1216double disc = sqr (0.5*b/c) - a/c;1217if (disc > 0)1218{1219disc = sqrt (disc);1220double alpha1 = -0.5*b/c + disc;1221double alpha2 = -0.5*b/c - disc;12221223pts.Append (Point<3> (sol+alpha1*t));1224pts.Append (Point<3> (sol+alpha2*t));1225/*1226cout << "sol1 = " << sol + alpha1 * t1227<< ", sol2 = " << sol + alpha2 * t << endl;1228*/1229}1230}1231}1232}1233}1234123512361237123812391240/*1241bool SpecialPointCalculation :: ExtremalPointPossible (const Surface * f1,1242const Surface * f2,1243int dir,1244const BoxSphere<3> & box)1245{1246double hn1, hn2, gn1, gn2;1247Point<3> p;1248Vec<3> g1, g2, v;1249double f3;1250double r = box.Diam()/2;12511252p = box.Center();12531254f1 -> CalcGradient (p, g1);1255f2 -> CalcGradient (p, g2);12561257gn1 = g1.Length();1258gn2 = g2.Length();12591260hn1 = f1 -> HesseNorm ();1261hn2 = f2 -> HesseNorm ();12621263v = Cross (g1, g2);1264f3 = fabs (v(dir-1));12651266// (*testout) << "f3 = " << f3 << " r = " << r1267// << "normbound = "1268// << (hn1 * (gn2 + r * hn2) + hn2 * (gn1 + r * hn1)) << endl;12691270return (f3 <= 3 * r * (hn1 * (gn2 + r * hn2) + hn2 * (gn1 + r * hn1)));1271}1272127312741275bool SpecialPointCalculation ::1276ExtremalPointNewtonConvergence (const Surface * f1, const Surface * f2,1277int dir,1278const BoxSphere<3> & box)1279{1280return box.Diam() < 1e-8;1281}128212831284bool SpecialPointCalculation ::1285ExtremalPointDegenerated (const Surface * f1, const Surface * f2,1286int dir, const BoxSphere<3> & box)1287{1288double gn1, gn2;1289Point<3> p;1290Vec<3> g1, g2, v;1291double maxderiv;1292double minv;1293Vec<3> curv, t;1294Vec<2> rs, x;1295Mat<3> h1, h2;1296Mat<2> a, inv;1297double leftside;12981299if (box.Diam() > relydegtest) return 0;13001301p = box.Center();13021303f1 -> CalcGradient (p, g1);1304f2 -> CalcGradient (p, g2);1305gn1 = g1.Length();1306gn2 = g2.Length();13071308v = Cross (g1, g2);1309if (Abs (v) < epeps1 * gn1 * gn2) return 1; // irregular edge13101311f1 -> CalcHesse (p, h1);1312f2 -> CalcHesse (p, h2);13131314// hn1 = f1 -> HesseNorm ();1315// hn2 = f2 -> HesseNorm ();13161317t = v;1318a(0, 0) = g1 * g1;1319a(0, 1) =1320a(1, 0) = g1 * g2;1321a(1, 1) = g2 * g2;13221323rs(0) = g1(dir-1);1324rs(1) = g2(dir-1);13251326a.Solve (rs, x);13271328// (*testout) << "g1 = " << g1 << " g2 = " << g2 << endl;1329// (*testout) << "lam = " << x << endl;1330// (*testout) << "h2 = " << h2 << endl;13311332leftside = fabs (x(0) * ( t * (h1 * t)) +1333x(1) * ( t * (h2 * t)));13341335// (*testout) << "leftside = " << leftside << endl;13361337if (leftside < epeps2 * Abs2 (v)) return 1;13381339return 0;1340}1341*/134213431344bool SpecialPointCalculation :: AddPoint (const Point<3> & p, int layer)1345{1346for (int i = 0; i < points->Size(); i++)1347if (Dist2 ( (*points)[i], p) < epspointdist2 &&1348(*points)[i].GetLayer() == layer)1349return false;13501351points->Append (MeshPoint(p, layer));1352PrintMessageCR (3, "Found points ", points->Size());1353return true;1354}13551356135713581359136013611362void SpecialPointCalculation ::1363AnalyzeSpecialPoints (const CSGeometry & ageometry,1364ARRAY<MeshPoint> & apoints,1365ARRAY<SpecialPoint> & specpoints)1366{1367ARRAY<int> surfind, rep_surfind, surfind2, rep_surfind2, surfind3;13681369ARRAY<Vec<3> > normalvecs;1370Vec<3> nsurf;13711372ARRAY<int> specpoint2point;1373specpoints.SetSize (0);13741375geometry = &ageometry;13761377double geomsize = ageometry.MaxSize();13781379(*testout) << "AnalyzeSpecialPoints\n";13801381if (!apoints.Size()) return;1382138313841385#ifdef VERTSORT1386for (int i = 0; i < apoints.Size(); i++)1387for (int j = 0; j < apoints.Size()-1; j++)1388if (apoints[j](2) > apoints[j+1](2))1389swap (apoints[j], apoints[j+1]);1390#endif13911392139313941395139613971398Box<3> bbox (apoints[0], apoints[0]);1399for (int i = 1; i < apoints.Size(); i++)1400bbox.Add (apoints[i]);1401bbox.Increase (0.1 * bbox.Diam());14021403//testout->precision(20);1404(*testout) << "bbox = " << bbox << endl;1405(*testout) << "points = " << apoints << endl;14061407Point3dTree searchtree (bbox.PMin(), bbox.PMax());1408ARRAY<int> locsearch;14091410for (int si = 0; si < ageometry.GetNTopLevelObjects(); si++)1411{1412const TopLevelObject * tlo = ageometry.GetTopLevelObject(si);14131414const Solid * sol = tlo->GetSolid();1415const Surface * surf = tlo->GetSurface();141614171418for (int i = 0; i < apoints.Size(); i++)1419{1420Point<3> p = apoints[i];14211422#ifdef DEVELOP1423*testout << " test point " << p << endl;1424#endif14251426if (tlo->GetLayer() != apoints[i].GetLayer())1427continue;14281429Solid * locsol;1430sol -> TangentialSolid (p, locsol, surfind, ideps*geomsize);1431143214331434rep_surfind.SetSize (surfind.Size());1435int num_indep_surfs = 0;14361437for (int j = 0; j < surfind.Size(); j++)1438{1439rep_surfind[j] = ageometry.GetSurfaceClassRepresentant (surfind[j]);1440bool found = false;1441for (int k = 0; !found && k < j; k++)1442found = (rep_surfind[k] == rep_surfind[j]);1443if(!found)1444num_indep_surfs++;1445}144614471448#ifdef DEVELOP1449*testout << "surfs = " << surfind << endl;1450*testout << "rep_surfs = " << rep_surfind << endl;1451#endif14521453if (!locsol) continue;14541455// get all surface indices,1456if (surf)1457{1458// locsol -> GetSurfaceIndices (surfind);1459bool hassurf = 0;1460for (int m = 0; m < surfind.Size(); m++)1461if (ageometry.GetSurface(surfind[m]) == surf)1462hassurf = 1;14631464if (!hassurf)1465continue;14661467nsurf = surf->GetNormalVector (p);1468}14691470/*1471// get independent surfaces of tangential solid1472BoxSphere<3> box(p,p);1473box.Increase (1e-6*geomsize);1474box.CalcDiamCenter();1475ageometry.GetIndependentSurfaceIndices (locsol, box, surfind);1476*/14771478// ageometry.GetIndependentSurfaceIndices (surfind);147914801481normalvecs.SetSize(surfind.Size());1482for (int j = 0; j < surfind.Size(); j++)1483normalvecs[j] =1484ageometry.GetSurface(surfind[j]) -> GetNormalVector(apoints[i]);148514861487for (int j = 0; j < normalvecs.Size(); j++)1488for (int k = 0; k < normalvecs.Size(); k++)1489{1490if (rep_surfind[j] == rep_surfind[k]) continue;1491//if (j == k) continue;14921493Vec<3> t;14941495if (dynamic_cast<const Polyhedra*> (ageometry.surf2prim[surfind[j]]) &&1496ageometry.surf2prim[surfind[j]] ==1497ageometry.surf2prim[surfind[k]])1498{1499t = ageometry.surf2prim[surfind[j]] ->1500SpecialPointTangentialVector (p, surfind[j], surfind[k]);1501}1502else1503{1504t = Cross (normalvecs[j], normalvecs[k]);1505}150615071508if (Abs2 (t) < 1e-8)1509continue;15101511#ifdef DEVELOP1512*testout << " tangential vector " << t << endl;1513#endif15141515t.Normalize();151615171518// try tangential direction t1519if (surf && fabs (nsurf * t) > 1e-6)1520continue;152115221523#ifdef DEVELOP1524*testout << " j " << j << " k " << k << endl;1525#endif15261527if (!surf)1528{1529// compute second order approximation1530// c(s) = p + s t + s*s/2 t21531Vec<3> gradj, gradk;1532Mat<3> hessej, hessek;1533ageometry.GetSurface (surfind[j]) -> CalcGradient (p, gradj);1534ageometry.GetSurface (surfind[k]) -> CalcGradient (p, gradk);1535ageometry.GetSurface (surfind[j]) -> CalcHesse (p, hessej);1536ageometry.GetSurface (surfind[k]) -> CalcHesse (p, hessek);15371538Vec<2> rhs;1539Vec<3> t2;1540Mat<2,3> mat;1541Mat<3,2> inv;1542for (int l = 0; l < 3; l++)1543{1544mat(0,l) = gradj(l);1545mat(1,l) = gradk(l);1546}1547rhs(0) = -t * (hessej * t);1548rhs(1) = -t * (hessek * t);15491550CalcInverse (mat, inv);1551t2 = inv * rhs;155215531554/*1555ageometry.GetIndependentSurfaceIndices1556(locsol, p, t, surfind2);1557*/15581559Solid * locsol2;1560locsol -> TangentialSolid3 (p, t, t2, locsol2, surfind2, ideps*geomsize);1561if (!locsol2) continue;15621563// locsol2 -> GetTangentialSurfaceIndices3 (p, t, t2, surfind2, 1e-9*geomsize);15641565rep_surfind2.SetSize (surfind2.Size());1566for (int j2 = 0; j2 < surfind2.Size(); j2++)1567rep_surfind2[j2] = ageometry.GetSurfaceClassRepresentant (surfind2[j2]);15681569#ifdef DEVELOP1570(*testout) << "surfind2 = " << endl << surfind2 << endl;1571#endif1572ARRAY<int> surfind2_aux(surfind2);1573ageometry.GetIndependentSurfaceIndices (surfind2_aux);1574#ifdef DEVELOP1575(*testout) << "surfind2,rep = " << endl << surfind2_aux << endl;1576#endif15771578bool ok = true;15791580// intersecting surfaces must be in second order tangential solid1581/*1582if (!surfind2.Contains(surfind[j]) ||1583!surfind2.Contains(surfind[k]))1584ok = false;1585*/1586if (!surfind2_aux.Contains(rep_surfind[j]) ||1587!surfind2_aux.Contains(rep_surfind[k]))1588ok = false;15891590#ifdef DEVELOP1591(*testout) << "ok,1 = " << ok << endl;1592#endif15931594// there must be 2 different tangential faces to the edge1595int cnt_tang_faces = 0;1596for (int l = 0; l < surfind2.Size(); l++)1597{1598Vec<3> nv =1599ageometry.GetSurface(surfind2[l]) -> GetNormalVector(p);160016011602Vec<3> m1 = Cross (t, nv);1603Vec<3> m2 = -m1;1604bool isface1 = 0, isface2 = 0;16051606Solid * locsol3;16071608// locsol2 -> TangentialSolid2 (p, m1, locsol3, surfind3, 1e-9*geomsize);1609locsol -> TangentialEdgeSolid (p, t, t2, m1, locsol3, surfind3, ideps*geomsize);16101611//ageometry.GetIndependentSurfaceIndices (surfind3);16121613if (surfind3.Contains(surfind2[l]))1614isface1 = 1;1615delete locsol3;16161617// locsol2 -> TangentialSolid2 (p, m2, locsol3, surfind3, 1e-9*geomsize);1618locsol -> TangentialEdgeSolid (p, t, t2, m2, locsol3, surfind3, ideps*geomsize);16191620// ageometry.GetIndependentSurfaceIndices (surfind3);162116221623if (surfind3.Contains(surfind2[l]))1624isface2 = 1;1625delete locsol3;16261627if (isface1 != isface2)1628cnt_tang_faces++;1629}16301631#ifdef DEVELOP1632(*testout) << "cnt_tang = " << cnt_tang_faces << endl;1633#endif16341635if (cnt_tang_faces < 1)1636ok = false;16371638delete locsol2;1639if (!ok) continue;1640}164116421643// edge must be on tangential surface1644bool isedge =1645locsol->VectorIn (p, t) &&1646!locsol->VectorStrictIn (p, t);16471648#ifdef DEVELOP1649(*testout) << "isedge,1 = " << isedge << "\n";1650#endif16511652// there must exist at least two different faces on edge1653if (isedge)1654{1655// *testout << "succ 1" << endl;1656int cnts = 0;1657for (int m = 0; m < surfind.Size(); m++)1658{1659if (fabs (normalvecs[m] * t) > 1e-6)1660continue;16611662Vec<3> s = Cross (normalvecs[m], t);1663Vec<3> t2a = t + 0.01 *s;1664Vec<3> t2b = t - 0.01 *s;16651666bool isface =1667(locsol->VectorIn (p, t2a, 1e-6*geomsize) &&1668!locsol->VectorStrictIn (p, t2a, 1e-6*geomsize))1669||1670(locsol->VectorIn (p, t2b, 1e-6*geomsize) &&1671!locsol->VectorStrictIn (p, t2b, 1e-6*geomsize));16721673/*1674bool isface =1675(locsol->VectorIn (p, t2a) &&1676!locsol->VectorStrictIn (p, t2a))1677||1678(locsol->VectorIn (p, t2b) &&1679!locsol->VectorStrictIn (p, t2b));1680*/16811682if (isface)1683{1684cnts++;1685}1686}1687if (cnts < 2) isedge = 0;1688}16891690if (isedge)1691{1692#ifdef DEVELOP1693*testout << "success" << endl;1694#endif1695int spi = -1;16961697const double searchradius = 1e-4*geomsize;//1e-5*geomsize;1698searchtree.GetIntersecting (apoints[i]-Vec3d(searchradius,searchradius,searchradius),1699apoints[i]+Vec3d(searchradius,searchradius,searchradius),1700locsearch);17011702for (int m = 0; m < locsearch.Size(); m++)1703{1704if (Dist2 (specpoints[locsearch[m]].p, apoints[i]) < 1e-10*geomsize1705&& Abs2(specpoints[locsearch[m]].v - t) < 1e-8)1706{1707spi = locsearch[m];1708break;1709}1710}171117121713if (spi == -1)1714{1715spi = specpoints.Append (SpecialPoint()) - 1;1716specpoint2point.Append (i);1717specpoints.Last().unconditional = 0;1718searchtree.Insert (apoints[i], spi);1719}17201721if(!specpoints[spi].unconditional)1722{1723specpoints[spi].p = apoints[i];1724specpoints[spi].v = t;1725//if (surfind.Size() >= 3)1726if (num_indep_surfs >= 3)1727specpoints[spi].unconditional = 1;1728specpoints[spi].s1 = rep_surfind[j];1729specpoints[spi].s2 = rep_surfind[k];1730specpoints[spi].s1_orig = surfind[j];1731specpoints[spi].s2_orig = surfind[k];1732specpoints[spi].layer = apoints[i].GetLayer();1733for (int up = 0; up < geometry->GetNUserPoints(); up++)1734if (Dist (geometry->GetUserPoint(up), apoints[i]) < 1e-8*geomsize)1735specpoints[spi].unconditional = 1;1736for (int ip = 0; ip < geometry->GetNIdentPoints(); ip++)1737if (Dist (geometry->GetIdentPoint(ip), apoints[i]) < 1e-8*geomsize)1738specpoints[spi].unconditional = 1;1739}1740}17411742}17431744delete locsol;1745}1746}17471748/*1749BitArray testuncond (specpoints.Size());1750testuncond.Clear();1751for(int i = 0; i<specpoints.Size(); i++)1752{1753if(testuncond.Test(i))1754continue;17551756ARRAY<int> same;1757same.Append(i);17581759for(int j = i+1; j<specpoints.Size(); j++)1760{1761if(Dist(specpoints[i].p,specpoints[j].p) < 1e-20)1762{1763same.Append(j);1764testuncond.Set(j);1765}1766}17671768if(same.Size() < 3)1769for(int j=0; j<same.Size(); j++)1770{1771(*testout) << "setting " << specpoints[same[j]].p << "; " << specpoints[same[j]].v << "; "1772<<specpoints[same[j]].unconditional << " to conditional" << endl;1773specpoints[same[j]].unconditional=0;1774}1775}1776*/177717781779// if special point is unconditional on some solid,1780// it must be unconditional everywhere:17811782BitArray uncond (apoints.Size());1783uncond.Clear();17841785for (int i = 0; i < specpoints.Size(); i++)1786if (specpoints[i].unconditional)1787uncond.Set (specpoint2point[i]);17881789for (int i = 0; i < specpoints.Size(); i++)1790specpoints[i].unconditional =1791uncond.Test (specpoint2point[i]) ? 1 : 0;1792}1793}179417951796