Path: blob/devel/ElmerGUI/netgen/libsrc/csg/solid.cpp
3206 views
#include <mystdlib.h>12#include <linalg.hpp>3#include <csg.hpp>456namespace netgen7{8//using namespace netgen;91011/*12SolidIterator :: SolidIterator ()13{14;15}1617SolidIterator :: ~SolidIterator ()18{19;20}21*/22232425// int Solid :: cntnames = 0;2627Solid :: Solid (Primitive * aprim)28{29op = TERM;30prim = aprim;31s1 = s2 = NULL;32maxh = 1e10;33name = NULL;34}3536Solid :: Solid (optyp aop, Solid * as1, Solid * as2)37{38op = aop;39s1 = as1;40s2 = as2;41prim = NULL;42name = NULL;43maxh = 1e10;44}4546Solid :: ~Solid ()47{48// cout << "delete solid, op = " << int(op) << endl;49delete [] name;5051switch (op)52{53case UNION:54case SECTION:55{56if (s1->op != ROOT) delete s1;57if (s2->op != ROOT) delete s2;58break;59}60case SUB:61// case ROOT:62{63if (s1->op != ROOT) delete s1;64break;65}66case TERM:67{68// cout << "has term" << endl;69delete prim;70break;71}72default:73break;74}75}7677void Solid :: SetName (const char * aname)78{79delete [] name;80name = new char[strlen (aname)+1];81strcpy (name, aname);82}838485Solid * Solid :: Copy (CSGeometry & geom) const86{87Solid * nsol(NULL);88switch (op)89{90case TERM: case TERM_REF:91{92Primitive * nprim = prim->Copy();93geom.AddSurfaces (nprim);94nsol = new Solid (nprim);95break;96}9798case SECTION:99case UNION:100{101nsol = new Solid (op, s1->Copy(geom), s2->Copy(geom));102break;103}104105case SUB:106{107nsol = new Solid (SUB, s1 -> Copy (geom));108break;109}110111case ROOT:112{113nsol = s1->Copy(geom);114break;115}116}117118return nsol;119}120121122void Solid :: Transform (Transformation<3> & trans)123{124switch (op)125{126case TERM: case TERM_REF:127{128prim -> Transform (trans);129break;130}131case SECTION:132case UNION:133{134s1 -> Transform (trans);135s2 -> Transform (trans);136break;137}138139case SUB:140case ROOT:141{142s1 -> Transform (trans);143break;144}145}146}147148149150void Solid :: IterateSolid (SolidIterator & it,151bool only_once)152{153if (only_once)154{155if (visited)156return;157158visited = 1;159}160161it.Do (this);162163switch (op)164{165case SECTION:166{167s1->IterateSolid (it, only_once);168s2->IterateSolid (it, only_once);169break;170}171case UNION:172{173s1->IterateSolid (it, only_once);174s2->IterateSolid (it, only_once);175break;176}177case SUB:178case ROOT:179{180s1->IterateSolid (it, only_once);181break;182}183}184}185186187188189bool Solid :: IsIn (const Point<3> & p, double eps) const190{191switch (op)192{193case TERM: case TERM_REF:194{195INSOLID_TYPE ist = prim->PointInSolid (p, eps);196return ( (ist == IS_INSIDE) || (ist == DOES_INTERSECT) ) ? 1 : 0;197}198case SECTION:199return s1->IsIn (p, eps) && s2->IsIn (p, eps);200case UNION:201return s1->IsIn (p, eps) || s2->IsIn (p, eps);202case SUB:203return !s1->IsStrictIn (p, eps);204case ROOT:205return s1->IsIn (p, eps);206}207return 0;208}209210bool Solid :: IsStrictIn (const Point<3> & p, double eps) const211{212switch (op)213{214case TERM: case TERM_REF:215{216INSOLID_TYPE ist = prim->PointInSolid (p, eps);217return (ist == IS_INSIDE) ? 1 : 0;218}219case SECTION:220return s1->IsStrictIn(p, eps) && s2->IsStrictIn(p, eps);221case UNION:222return s1->IsStrictIn(p, eps) || s2->IsStrictIn(p, eps);223case SUB:224return !s1->IsIn (p, eps);225case ROOT:226return s1->IsStrictIn (p, eps);227}228return 0;229}230231bool Solid :: VectorIn (const Point<3> & p, const Vec<3> & v,232double eps) const233{234Vec<3> hv;235switch (op)236{237case TERM: case TERM_REF:238{239INSOLID_TYPE ist = prim->VecInSolid (p, v, eps);240return (ist == IS_INSIDE || ist == DOES_INTERSECT) ? 1 : 0;241}242case SECTION:243return s1 -> VectorIn (p, v, eps) && s2 -> VectorIn (p, v, eps);244case UNION:245return s1 -> VectorIn (p, v, eps) || s2 -> VectorIn (p, v, eps);246case SUB:247return !s1->VectorStrictIn(p, v, eps);248case ROOT:249return s1->VectorIn(p, v, eps);250}251return 0;252}253254bool Solid :: VectorStrictIn (const Point<3> & p, const Vec<3> & v,255double eps) const256{257Vec<3> hv;258switch (op)259{260case TERM: case TERM_REF:261{262INSOLID_TYPE ist = prim->VecInSolid (p, v, eps);263return (ist == IS_INSIDE) ? true : false;264}265case SECTION:266return s1 -> VectorStrictIn (p, v, eps) &&267s2 -> VectorStrictIn (p, v, eps);268case UNION:269return s1 -> VectorStrictIn (p, v, eps) ||270s2 -> VectorStrictIn (p, v, eps);271case SUB:272return !s1->VectorIn(p, v, eps);273case ROOT:274return s1->VectorStrictIn(p, v, eps);275}276return 0;277}278279280bool Solid::VectorIn2 (const Point<3> & p, const Vec<3> & v1,281const Vec<3> & v2, double eps) const282{283if (VectorStrictIn (p, v1, eps))284return 1;285if (!VectorIn (p, v1, eps))286return 0;287288bool res = VectorIn2Rec (p, v1, v2, eps);289return res;290}291292bool Solid::VectorIn2Rec (const Point<3> & p, const Vec<3> & v1,293const Vec<3> & v2, double eps) const294{295switch (op)296{297case TERM: case TERM_REF:298return (prim->VecInSolid2 (p, v1, v2, eps) != IS_OUTSIDE); // Is this correct????299case SECTION:300return s1->VectorIn2Rec (p, v1, v2, eps) &&301s2->VectorIn2Rec (p, v1, v2, eps);302case UNION:303return s1->VectorIn2Rec (p, v1, v2, eps) ||304s2->VectorIn2Rec (p, v1, v2, eps);305case SUB:306return !s1->VectorIn2Rec (p, v1, v2, eps);307case ROOT:308return s1->VectorIn2Rec (p, v1, v2, eps);309}310return 0;311}312313314315316317318void Solid :: Print (ostream & str) const319{320switch (op)321{322case TERM: case TERM_REF:323{324str << prim->GetSurfaceId(0);325for (int i = 1; i < prim->GetNSurfaces(); i++)326str << "," << prim->GetSurfaceId(i);327break;328}329case SECTION:330{331str << "(";332s1 -> Print (str);333str << " AND ";334s2 -> Print (str);335str << ")";336break;337}338case UNION:339{340str << "(";341s1 -> Print (str);342str << " OR ";343s2 -> Print (str);344str << ")";345break;346}347case SUB:348{349str << " NOT ";350s1 -> Print (str);351break;352}353case ROOT:354{355str << " [" << name << "=";356s1 -> Print (str);357str << "] ";358break;359}360}361}362363364365void Solid :: GetSolidData (ostream & ost, int first) const366{367switch (op)368{369case SECTION:370{371ost << "(";372s1 -> GetSolidData (ost, 0);373ost << " AND ";374s2 -> GetSolidData (ost, 0);375ost << ")";376break;377}378case UNION:379{380ost << "(";381s1 -> GetSolidData (ost, 0);382ost << " OR ";383s2 -> GetSolidData (ost, 0);384ost << ")";385break;386}387case SUB:388{389ost << "NOT ";390s1 -> GetSolidData (ost, 0);391break;392}393case TERM: case TERM_REF:394{395if (name)396ost << name;397else398ost << "(noname)";399break;400}401case ROOT:402{403if (first)404s1 -> GetSolidData (ost, 0);405else406ost << name;407break;408}409}410}411412413414static Solid * CreateSolidExpr (istream & ist, const SYMBOLTABLE<Solid*> & solids);415static Solid * CreateSolidTerm (istream & ist, const SYMBOLTABLE<Solid*> & solids);416static Solid * CreateSolidPrim (istream & ist, const SYMBOLTABLE<Solid*> & solids);417418static void ReadString (istream & ist, char * str)419{420//char * hstr = str;421char ch;422423while (1)424{425ist.get(ch);426if (!ist.good()) break;427428if (!isspace (ch))429{430ist.putback (ch);431break;432}433}434435while (1)436{437ist.get(ch);438if (!ist.good()) break;439if (isalpha(ch) || isdigit(ch))440{441*str = ch;442str++;443}444else445{446ist.putback (ch);447break;448}449}450*str = 0;451// cout << "Read string (" << hstr << ")"452// << "put back: " << ch << endl;453}454455456Solid * CreateSolidExpr (istream & ist, const SYMBOLTABLE<Solid*> & solids)457{458// cout << "create expr" << endl;459460Solid *s1, *s2;461char str[100];462463s1 = CreateSolidTerm (ist, solids);464ReadString (ist, str);465if (strcmp (str, "OR") == 0)466{467// cout << " OR ";468s2 = CreateSolidExpr (ist, solids);469return new Solid (Solid::UNION, s1, s2);470}471472// cout << "no OR found, put back string: " << str << endl;473for (int i = int(strlen(str))-1; i >= 0; i--)474ist.putback (str[i]);475476return s1;477}478479Solid * CreateSolidTerm (istream & ist, const SYMBOLTABLE<Solid*> & solids)480{481// cout << "create term" << endl;482483Solid *s1, *s2;484char str[100];485486s1 = CreateSolidPrim (ist, solids);487ReadString (ist, str);488if (strcmp (str, "AND") == 0)489{490// cout << " AND ";491s2 = CreateSolidTerm (ist, solids);492return new Solid (Solid::SECTION, s1, s2);493}494495496// cout << "no AND found, put back string: " << str << endl;497for (int i = int(strlen(str))-1; i >= 0; i--)498ist.putback (str[i]);499500return s1;501}502503Solid * CreateSolidPrim (istream & ist, const SYMBOLTABLE<Solid*> & solids)504{505Solid * s1;506char ch;507char str[100];508509ist >> ch;510if (ch == '(')511{512s1 = CreateSolidExpr (ist, solids);513ist >> ch; // ')'514// cout << "close back " << ch << endl;515return s1;516}517ist.putback (ch);518519ReadString (ist, str);520if (strcmp (str, "NOT") == 0)521{522// cout << " NOT ";523s1 = CreateSolidPrim (ist, solids);524return new Solid (Solid::SUB, s1);525}526527(*testout) << "get terminal " << str << endl;528s1 = solids.Get(str);529if (s1)530{531// cout << "primitive: " << str << endl;532return s1;533}534cerr << "syntax error" << endl;535536return NULL;537}538539540Solid * Solid :: CreateSolid (istream & ist, const SYMBOLTABLE<Solid*> & solids)541{542Solid * nsol = CreateSolidExpr (ist, solids);543nsol = new Solid (ROOT, nsol);544(*testout) << "Print new sol: ";545nsol -> Print (*testout);546(*testout) << endl;547return nsol;548}549550551552void Solid :: Boundaries (const Point<3> & p, ARRAY<int> & bounds) const553{554int in, strin;555bounds.SetSize (0);556RecBoundaries (p, bounds, in, strin);557}558559void Solid :: RecBoundaries (const Point<3> & p, ARRAY<int> & bounds,560int & in, int & strin) const561{562switch (op)563{564case TERM: case TERM_REF:565{566/*567double val;568val = surf->CalcFunctionValue (p);569in = (val < 1e-6);570strin = (val < -1e-6);571if (in && !strin) bounds.Append (id);572*/573if (prim->PointInSolid (p, 1e-6) == DOES_INTERSECT)574bounds.Append (prim->GetSurfaceId (1));575break;576}577case SECTION:578{579int i, in1, in2, strin1, strin2;580ARRAY<int> bounds1, bounds2;581582s1 -> RecBoundaries (p, bounds1, in1, strin1);583s2 -> RecBoundaries (p, bounds2, in2, strin2);584585if (in1 && in2)586{587for (i = 1; i <= bounds1.Size(); i++)588bounds.Append (bounds1.Get(i));589for (i = 1; i <= bounds2.Size(); i++)590bounds.Append (bounds2.Get(i));591}592in = (in1 && in2);593strin = (strin1 && strin2);594break;595}596case UNION:597{598int i, in1, in2, strin1, strin2;599ARRAY<int> bounds1, bounds2;600601s1 -> RecBoundaries (p, bounds1, in1, strin1);602s2 -> RecBoundaries (p, bounds2, in2, strin2);603604if (!strin1 && !strin2)605{606for (i = 1; i <= bounds1.Size(); i++)607bounds.Append (bounds1.Get(i));608for (i = 1; i <= bounds2.Size(); i++)609bounds.Append (bounds2.Get(i));610}611in = (in1 || in2);612strin = (strin1 || strin2);613break;614}615case SUB:616{617int hin, hstrin;618s1 -> RecBoundaries (p, bounds, hin, hstrin);619in = !hstrin;620strin = !hin;621break;622}623624case ROOT:625{626s1 -> RecBoundaries (p, bounds, in, strin);627break;628}629}630}631632633void Solid :: TangentialSolid (const Point<3> & p, Solid *& tansol, ARRAY<int> & surfids, double eps) const634{635int in, strin;636RecTangentialSolid (p, tansol, surfids, in, strin, eps);637surfids.SetSize (0);638if (tansol)639tansol -> GetTangentialSurfaceIndices (p, surfids, eps);640}641642643void Solid :: RecTangentialSolid (const Point<3> & p, Solid *& tansol, ARRAY<int> & surfids,644int & in, int & strin, double eps) const645{646tansol = NULL;647648switch (op)649{650case TERM: case TERM_REF:651{652INSOLID_TYPE ist = prim->PointInSolid(p, eps);653654in = (ist == IS_INSIDE || ist == DOES_INTERSECT);655strin = (ist == IS_INSIDE);656657if (ist == DOES_INTERSECT)658{659tansol = new Solid (prim);660tansol -> op = TERM_REF;661}662break;663}664case SECTION:665{666int in1, in2, strin1, strin2;667Solid * tansol1, * tansol2;668669s1 -> RecTangentialSolid (p, tansol1, surfids, in1, strin1, eps);670s2 -> RecTangentialSolid (p, tansol2, surfids, in2, strin2, eps);671672if (in1 && in2)673{674if (tansol1 && tansol2)675tansol = new Solid (SECTION, tansol1, tansol2);676else if (tansol1)677tansol = tansol1;678else if (tansol2)679tansol = tansol2;680}681in = (in1 && in2);682strin = (strin1 && strin2);683break;684}685case UNION:686{687int in1, in2, strin1, strin2;688Solid * tansol1, * tansol2;689690s1 -> RecTangentialSolid (p, tansol1, surfids, in1, strin1, eps);691s2 -> RecTangentialSolid (p, tansol2, surfids, in2, strin2, eps);692693if (!strin1 && !strin2)694{695if (tansol1 && tansol2)696tansol = new Solid (UNION, tansol1, tansol2);697else if (tansol1)698tansol = tansol1;699else if (tansol2)700tansol = tansol2;701}702in = (in1 || in2);703strin = (strin1 || strin2);704break;705}706case SUB:707{708int hin, hstrin;709Solid * tansol1;710711s1 -> RecTangentialSolid (p, tansol1, surfids, hin, hstrin, eps);712713if (tansol1)714tansol = new Solid (SUB, tansol1);715in = !hstrin;716strin = !hin;717break;718}719case ROOT:720{721s1 -> RecTangentialSolid (p, tansol, surfids, in, strin, eps);722break;723}724}725}726727728729730void Solid :: TangentialSolid2 (const Point<3> & p,731const Vec<3> & t,732Solid *& tansol, ARRAY<int> & surfids, double eps) const733{734int in, strin;735surfids.SetSize (0);736RecTangentialSolid2 (p, t, tansol, surfids, in, strin, eps);737if (tansol)738tansol -> GetTangentialSurfaceIndices2 (p, t, surfids, eps);739}740741void Solid :: RecTangentialSolid2 (const Point<3> & p, const Vec<3> & t,742Solid *& tansol, ARRAY<int> & surfids,743int & in, int & strin, double eps) const744{745tansol = NULL;746747switch (op)748{749case TERM: case TERM_REF:750{751/*752double val;753val = surf->CalcFunctionValue (p);754in = (val < 1e-6);755strin = (val < -1e-6);756if (in && !strin)757tansol = new Solid (surf, id);758*/759760INSOLID_TYPE ist = prim->PointInSolid(p, eps);761if (ist == DOES_INTERSECT)762ist = prim->VecInSolid (p, t, eps);763764in = (ist == IS_INSIDE || ist == DOES_INTERSECT);765strin = (ist == IS_INSIDE);766767if (ist == DOES_INTERSECT)768{769tansol = new Solid (prim);770tansol -> op = TERM_REF;771}772break;773}774case SECTION:775{776int in1, in2, strin1, strin2;777Solid * tansol1, * tansol2;778779s1 -> RecTangentialSolid2 (p, t, tansol1, surfids, in1, strin1, eps);780s2 -> RecTangentialSolid2 (p, t, tansol2, surfids, in2, strin2, eps);781782if (in1 && in2)783{784if (tansol1 && tansol2)785tansol = new Solid (SECTION, tansol1, tansol2);786else if (tansol1)787tansol = tansol1;788else if (tansol2)789tansol = tansol2;790}791in = (in1 && in2);792strin = (strin1 && strin2);793break;794}795case UNION:796{797int in1, in2, strin1, strin2;798Solid * tansol1, * tansol2;799800s1 -> RecTangentialSolid2 (p, t, tansol1, surfids, in1, strin1, eps);801s2 -> RecTangentialSolid2 (p, t, tansol2, surfids, in2, strin2, eps);802803if (!strin1 && !strin2)804{805if (tansol1 && tansol2)806tansol = new Solid (UNION, tansol1, tansol2);807else if (tansol1)808tansol = tansol1;809else if (tansol2)810tansol = tansol2;811}812in = (in1 || in2);813strin = (strin1 || strin2);814break;815}816case SUB:817{818int hin, hstrin;819Solid * tansol1;820821s1 -> RecTangentialSolid2 (p, t, tansol1, surfids, hin, hstrin, eps);822823if (tansol1)824tansol = new Solid (SUB, tansol1);825in = !hstrin;826strin = !hin;827break;828}829case ROOT:830{831s1 -> RecTangentialSolid2 (p, t, tansol, surfids, in, strin, eps);832break;833}834}835}836837838839840841842843844void Solid :: TangentialSolid3 (const Point<3> & p,845const Vec<3> & t, const Vec<3> & t2,846Solid *& tansol, ARRAY<int> & surfids,847double eps) const848{849int in, strin;850surfids.SetSize (0);851RecTangentialSolid3 (p, t, t2, tansol, surfids, in, strin, eps);852853if (tansol)854tansol -> GetTangentialSurfaceIndices3 (p, t, t2, surfids, eps);855}856857void Solid :: RecTangentialSolid3 (const Point<3> & p,858const Vec<3> & t, const Vec<3> & t2,859Solid *& tansol, ARRAY<int> & surfids,860int & in, int & strin, double eps) const861{862tansol = NULL;863864switch (op)865{866case TERM: case TERM_REF:867{868INSOLID_TYPE ist = prim->PointInSolid(p, eps);869870if (ist == DOES_INTERSECT)871{872//(*testout) << "Calling VecInSolid3..." << endl;873ist = prim->VecInSolid3 (p, t, t2, eps);874//(*testout) << "...done" << endl;875}876in = (ist == IS_INSIDE || ist == DOES_INTERSECT);877strin = (ist == IS_INSIDE);878879if (ist == DOES_INTERSECT)880{881tansol = new Solid (prim);882tansol -> op = TERM_REF;883}884break;885}886case SECTION:887{888int in1, in2, strin1, strin2;889Solid * tansol1, * tansol2;890891s1 -> RecTangentialSolid3 (p, t, t2, tansol1, surfids, in1, strin1, eps);892s2 -> RecTangentialSolid3 (p, t, t2, tansol2, surfids, in2, strin2, eps);893894if (in1 && in2)895{896if (tansol1 && tansol2)897tansol = new Solid (SECTION, tansol1, tansol2);898else if (tansol1)899tansol = tansol1;900else if (tansol2)901tansol = tansol2;902}903in = (in1 && in2);904strin = (strin1 && strin2);905break;906}907case UNION:908{909int in1, in2, strin1, strin2;910Solid * tansol1, * tansol2;911912s1 -> RecTangentialSolid3 (p, t, t2, tansol1, surfids, in1, strin1, eps);913s2 -> RecTangentialSolid3 (p, t, t2, tansol2, surfids, in2, strin2, eps);914915if (!strin1 && !strin2)916{917if (tansol1 && tansol2)918tansol = new Solid (UNION, tansol1, tansol2);919else if (tansol1)920tansol = tansol1;921else if (tansol2)922tansol = tansol2;923}924in = (in1 || in2);925strin = (strin1 || strin2);926break;927}928case SUB:929{930int hin, hstrin;931Solid * tansol1;932933s1 -> RecTangentialSolid3 (p, t, t2, tansol1, surfids, hin, hstrin, eps);934935if (tansol1)936tansol = new Solid (SUB, tansol1);937in = !hstrin;938strin = !hin;939break;940}941case ROOT:942{943s1 -> RecTangentialSolid3 (p, t, t2, tansol, surfids, in, strin, eps);944break;945}946}947}948949950951952953954955956957958959void Solid :: TangentialEdgeSolid (const Point<3> & p,960const Vec<3> & t, const Vec<3> & t2, const Vec<3> & m,961Solid *& tansol, ARRAY<int> & surfids,962double eps) const963{964int in, strin;965surfids.SetSize (0);966967// *testout << "tangentialedgesolid,sol = " << (*this) << endl;968RecTangentialEdgeSolid (p, t, t2, m, tansol, surfids, in, strin, eps);969970if (tansol)971tansol -> RecGetTangentialEdgeSurfaceIndices (p, t, t2, m, surfids, eps);972}973974void Solid :: RecTangentialEdgeSolid (const Point<3> & p,975const Vec<3> & t, const Vec<3> & t2, const Vec<3> & m,976Solid *& tansol, ARRAY<int> & surfids,977int & in, int & strin, double eps) const978{979tansol = NULL;980981switch (op)982{983case TERM: case TERM_REF:984{985INSOLID_TYPE ist = prim->PointInSolid(p, eps);986987/*988(*testout) << "tangedgesolid, p = " << p << ", t = " << t989<< " for prim " << typeid (*prim).name()990<< " with surf " << prim->GetSurface() << endl;991(*testout) << "ist = " << ist << endl;992*/993994if (ist == DOES_INTERSECT)995ist = prim->VecInSolid4 (p, t, t2, m, eps);996997// (*testout) << "ist2 = " << ist << endl;998999in = (ist == IS_INSIDE || ist == DOES_INTERSECT);1000strin = (ist == IS_INSIDE);10011002if (ist == DOES_INTERSECT)1003{1004tansol = new Solid (prim);1005tansol -> op = TERM_REF;1006}1007break;1008}1009case SECTION:1010{1011int in1, in2, strin1, strin2;1012Solid * tansol1, * tansol2;10131014s1 -> RecTangentialEdgeSolid (p, t, t2, m, tansol1, surfids, in1, strin1, eps);1015s2 -> RecTangentialEdgeSolid (p, t, t2, m, tansol2, surfids, in2, strin2, eps);10161017if (in1 && in2)1018{1019if (tansol1 && tansol2)1020tansol = new Solid (SECTION, tansol1, tansol2);1021else if (tansol1)1022tansol = tansol1;1023else if (tansol2)1024tansol = tansol2;1025}1026in = (in1 && in2);1027strin = (strin1 && strin2);1028break;1029}1030case UNION:1031{1032int in1, in2, strin1, strin2;1033Solid * tansol1, * tansol2;10341035s1 -> RecTangentialEdgeSolid (p, t, t2, m, tansol1, surfids, in1, strin1, eps);1036s2 -> RecTangentialEdgeSolid (p, t, t2, m, tansol2, surfids, in2, strin2, eps);10371038if (!strin1 && !strin2)1039{1040if (tansol1 && tansol2)1041tansol = new Solid (UNION, tansol1, tansol2);1042else if (tansol1)1043tansol = tansol1;1044else if (tansol2)1045tansol = tansol2;1046}1047in = (in1 || in2);1048strin = (strin1 || strin2);1049break;1050}1051case SUB:1052{1053int hin, hstrin;1054Solid * tansol1;10551056s1 -> RecTangentialEdgeSolid (p, t, t2, m, tansol1, surfids, hin, hstrin, eps);10571058if (tansol1)1059tansol = new Solid (SUB, tansol1);1060in = !hstrin;1061strin = !hin;1062break;1063}1064case ROOT:1065{1066s1 -> RecTangentialEdgeSolid (p, t, t2, m, tansol, surfids, in, strin, eps);1067break;1068}1069}1070}10711072107310741075107610771078107910801081108210831084108510861087int Solid :: Edge (const Point<3> & p, const Vec<3> & v, double eps) const1088{1089int in, strin, faces;1090RecEdge (p, v, in, strin, faces, eps);1091return faces >= 2;1092}10931094int Solid :: OnFace (const Point<3> & p, const Vec<3> & v, double eps) const1095{1096int in, strin, faces;1097RecEdge (p, v, in, strin, faces, eps);1098return faces >= 1;1099}110011011102void Solid :: RecEdge (const Point<3> & p, const Vec<3> & v,1103int & in, int & strin, int & faces, double eps) const1104{1105switch (op)1106{1107case TERM: case TERM_REF:1108{1109INSOLID_TYPE ist = prim->VecInSolid (p, v, eps);1110in = (ist == IS_INSIDE || ist == DOES_INTERSECT);1111strin = (ist == IS_INSIDE);1112/*1113in = VectorIn (p, v);1114strin = VectorStrictIn (p, v);1115*/1116faces = 0;11171118if (in && ! strin)1119{1120// faces = 1;1121int i;1122Vec<3> grad;1123for (i = 0; i < prim->GetNSurfaces(); i++)1124{1125double val = prim->GetSurface(i).CalcFunctionValue(p);1126prim->GetSurface(i).CalcGradient (p, grad);1127if (fabs (val) < eps && fabs (v * grad) < 1e-6)1128faces++;1129}1130}1131// else1132// faces = 0;1133break;1134}1135case SECTION:1136{1137int in1, in2, strin1, strin2, faces1, faces2;11381139s1 -> RecEdge (p, v, in1, strin1, faces1, eps);1140s2 -> RecEdge (p, v, in2, strin2, faces2, eps);11411142faces = 0;1143if (in1 && in2)1144faces = faces1 + faces2;1145in = in1 && in2;1146strin = strin1 && strin2;1147break;1148}1149case UNION:1150{1151int in1, in2, strin1, strin2, faces1, faces2;11521153s1 -> RecEdge (p, v, in1, strin1, faces1, eps);1154s2 -> RecEdge (p, v, in2, strin2, faces2, eps);11551156faces = 0;1157if (!strin1 && !strin2)1158faces = faces1 + faces2;1159in = in1 || in2;1160strin = strin1 || strin2;1161break;1162}1163case SUB:1164{1165int in1, strin1;1166s1 -> RecEdge (p, v, in1, strin1, faces, eps);1167in = !strin1;1168strin = !in1;1169break;1170}1171case ROOT:1172{1173s1 -> RecEdge (p, v, in, strin, faces, eps);1174break;1175}1176}1177}117811791180void Solid :: CalcSurfaceInverse ()1181{1182CalcSurfaceInverseRec (0);1183}11841185void Solid :: CalcSurfaceInverseRec (int inv)1186{1187switch (op)1188{1189case TERM: case TERM_REF:1190{1191bool priminv;1192for (int i = 0; i < prim->GetNSurfaces(); i++)1193{1194priminv = (prim->SurfaceInverted(i) != 0);1195if (inv) priminv = !priminv;1196prim->GetSurface(i).SetInverse (priminv);1197}1198break;1199}1200case UNION:1201case SECTION:1202{1203s1 -> CalcSurfaceInverseRec (inv);1204s2 -> CalcSurfaceInverseRec (inv);1205break;1206}1207case SUB:1208{1209s1 -> CalcSurfaceInverseRec (1 - inv);1210break;1211}1212case ROOT:1213{1214s1 -> CalcSurfaceInverseRec (inv);1215break;1216}1217}1218}121912201221Solid * Solid :: GetReducedSolid (const BoxSphere<3> & box) const1222{1223INSOLID_TYPE in;1224return RecGetReducedSolid (box, in);1225}12261227Solid * Solid :: RecGetReducedSolid (const BoxSphere<3> & box, INSOLID_TYPE & in) const1228{1229Solid * redsol = NULL;12301231switch (op)1232{1233case TERM:1234case TERM_REF:1235{1236in = prim -> BoxInSolid (box);1237if (in == DOES_INTERSECT)1238{1239redsol = new Solid (prim);1240redsol -> op = TERM_REF;1241}1242break;1243}1244case SECTION:1245{1246INSOLID_TYPE in1, in2;1247Solid * redsol1, * redsol2;12481249redsol1 = s1 -> RecGetReducedSolid (box, in1);1250redsol2 = s2 -> RecGetReducedSolid (box, in2);12511252if (in1 == IS_OUTSIDE || in2 == IS_OUTSIDE)1253{1254if (in1 == DOES_INTERSECT) delete redsol1;1255if (in2 == DOES_INTERSECT) delete redsol2;1256in = IS_OUTSIDE;1257}1258else1259{1260if (in1 == DOES_INTERSECT || in2 == DOES_INTERSECT)1261in = DOES_INTERSECT;1262else1263in = IS_INSIDE;12641265if (in1 == DOES_INTERSECT && in2 == DOES_INTERSECT)1266redsol = new Solid (SECTION, redsol1, redsol2);1267else if (in1 == DOES_INTERSECT)1268redsol = redsol1;1269else if (in2 == DOES_INTERSECT)1270redsol = redsol2;1271}1272break;1273}12741275case UNION:1276{1277INSOLID_TYPE in1, in2;1278Solid * redsol1, * redsol2;12791280redsol1 = s1 -> RecGetReducedSolid (box, in1);1281redsol2 = s2 -> RecGetReducedSolid (box, in2);12821283if (in1 == IS_INSIDE || in2 == IS_INSIDE)1284{1285if (in1 == DOES_INTERSECT) delete redsol1;1286if (in2 == DOES_INTERSECT) delete redsol2;1287in = IS_INSIDE;1288}1289else1290{1291if (in1 == DOES_INTERSECT || in2 == DOES_INTERSECT) in = DOES_INTERSECT;1292else in = IS_OUTSIDE;12931294if (in1 == DOES_INTERSECT && in2 == DOES_INTERSECT)1295redsol = new Solid (UNION, redsol1, redsol2);1296else if (in1 == DOES_INTERSECT)1297redsol = redsol1;1298else if (in2 == DOES_INTERSECT)1299redsol = redsol2;1300}1301break;1302}13031304case SUB:1305{1306INSOLID_TYPE in1;1307Solid * redsol1 = s1 -> RecGetReducedSolid (box, in1);13081309switch (in1)1310{1311case IS_OUTSIDE: in = IS_INSIDE; break;1312case IS_INSIDE: in = IS_OUTSIDE; break;1313case DOES_INTERSECT: in = DOES_INTERSECT; break;1314}13151316if (redsol1)1317redsol = new Solid (SUB, redsol1);1318break;1319}13201321case ROOT:1322{1323INSOLID_TYPE in1;1324redsol = s1 -> RecGetReducedSolid (box, in1);1325in = in1;1326break;1327}1328}13291330/*1331if (redsol)1332(*testout) << "getrecsolid, redsol = " << endl << (*redsol) << endl;1333else1334(*testout) << "redsol is null" << endl;1335*/13361337return redsol;1338}133913401341int Solid :: NumPrimitives () const1342{1343switch (op)1344{1345case TERM: case TERM_REF:1346{1347return 1;1348}1349case UNION:1350case SECTION:1351{1352return s1->NumPrimitives () + s2 -> NumPrimitives();1353}1354case SUB:1355case ROOT:1356{1357return s1->NumPrimitives ();1358}1359}1360return 0;1361}13621363void Solid :: GetSurfaceIndices (ARRAY<int> & surfind) const1364{1365surfind.SetSize (0);1366RecGetSurfaceIndices (surfind);1367}13681369void Solid :: RecGetSurfaceIndices (ARRAY<int> & surfind) const1370{1371switch (op)1372{1373case TERM: case TERM_REF:1374{1375/*1376int i;1377for (i = 1; i <= surfind.Size(); i++)1378if (surfind.Get(i) == prim->GetSurfaceId())1379return;1380surfind.Append (prim->GetSurfaceId());1381break;1382*/1383for (int j = 0; j < prim->GetNSurfaces(); j++)1384if (prim->SurfaceActive (j))1385{1386bool found = 0;1387int siprim = prim->GetSurfaceId(j);13881389for (int i = 0; i < surfind.Size(); i++)1390if (surfind[i] == siprim)1391{1392found = 1;1393break;1394}1395if (!found) surfind.Append (siprim);1396}1397break;1398}1399case UNION:1400case SECTION:1401{1402s1 -> RecGetSurfaceIndices (surfind);1403s2 -> RecGetSurfaceIndices (surfind);1404break;1405}1406case SUB:1407case ROOT:1408{1409s1 -> RecGetSurfaceIndices (surfind);1410break;1411}1412}1413}1414141514161417void Solid :: GetTangentialSurfaceIndices (const Point<3> & p, ARRAY<int> & surfind, double eps) const1418{1419surfind.SetSize (0);1420RecGetTangentialSurfaceIndices (p, surfind, eps);1421}14221423void Solid :: RecGetTangentialSurfaceIndices (const Point<3> & p, ARRAY<int> & surfind, double eps) const1424{1425switch (op)1426{1427case TERM: case TERM_REF:1428{1429/*1430for (int j = 0; j < prim->GetNSurfaces(); j++)1431if (fabs (prim->GetSurface(j).CalcFunctionValue (p)) < eps)1432if (!surfind.Contains (prim->GetSurfaceId(j)))1433surfind.Append (prim->GetSurfaceId(j));1434*/1435prim->GetTangentialSurfaceIndices (p, surfind, eps);1436break;1437}1438case UNION:1439case SECTION:1440{1441s1 -> RecGetTangentialSurfaceIndices (p, surfind, eps);1442s2 -> RecGetTangentialSurfaceIndices (p, surfind, eps);1443break;1444}1445case SUB:1446case ROOT:1447{1448s1 -> RecGetTangentialSurfaceIndices (p, surfind, eps);1449break;1450}1451}1452}1453145414551456145714581459void Solid :: GetTangentialSurfaceIndices2 (const Point<3> & p, const Vec<3> & v,1460ARRAY<int> & surfind, double eps) const1461{1462surfind.SetSize (0);1463RecGetTangentialSurfaceIndices2 (p, v, surfind, eps);1464}14651466void Solid :: RecGetTangentialSurfaceIndices2 (const Point<3> & p, const Vec<3> & v,1467ARRAY<int> & surfind, double eps) const1468{1469switch (op)1470{1471case TERM: case TERM_REF:1472{1473for (int j = 0; j < prim->GetNSurfaces(); j++)1474{1475if (fabs (prim->GetSurface(j).CalcFunctionValue (p)) < eps)1476{1477Vec<3> grad;1478prim->GetSurface(j).CalcGradient (p, grad);1479if (sqr (grad * v) < 1e-6 * v.Length2() * grad.Length2())1480{1481if (!surfind.Contains (prim->GetSurfaceId(j)))1482surfind.Append (prim->GetSurfaceId(j));1483}1484}1485}1486break;1487}1488case UNION:1489case SECTION:1490{1491s1 -> RecGetTangentialSurfaceIndices2 (p, v, surfind, eps);1492s2 -> RecGetTangentialSurfaceIndices2 (p, v, surfind, eps);1493break;1494}1495case SUB:1496case ROOT:1497{1498s1 -> RecGetTangentialSurfaceIndices2 (p, v, surfind, eps);1499break;1500}1501}1502}150315041505150615071508150915101511void Solid :: GetTangentialSurfaceIndices3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2,1512ARRAY<int> & surfind, double eps) const1513{1514surfind.SetSize (0);1515RecGetTangentialSurfaceIndices3 (p, v, v2, surfind, eps);1516}15171518void Solid :: RecGetTangentialSurfaceIndices3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2,1519ARRAY<int> & surfind, double eps) const1520{1521switch (op)1522{1523case TERM: case TERM_REF:1524{1525for (int j = 0; j < prim->GetNSurfaces(); j++)1526{1527if (fabs (prim->GetSurface(j).CalcFunctionValue (p)) < eps)1528{1529Vec<3> grad;1530prim->GetSurface(j).CalcGradient (p, grad);1531if (sqr (grad * v) < 1e-6 * v.Length2() * grad.Length2())1532{1533// (*testout) << "p2" << endl;1534Mat<3> hesse;1535prim->GetSurface(j).CalcHesse (p, hesse);1536double hv2 = v2 * grad + v * (hesse * v);15371538if (fabs (hv2) < 1e-6)1539{1540if (!surfind.Contains (prim->GetSurfaceId(j)))1541surfind.Append (prim->GetSurfaceId(j));1542}1543}1544}1545}1546break;1547}1548case UNION:1549case SECTION:1550{1551s1 -> RecGetTangentialSurfaceIndices3 (p, v, v2, surfind, eps);1552s2 -> RecGetTangentialSurfaceIndices3 (p, v, v2, surfind, eps);1553break;1554}1555case SUB:1556case ROOT:1557{1558s1 -> RecGetTangentialSurfaceIndices3 (p, v, v2, surfind, eps);1559break;1560}1561}1562}156315641565156615671568void Solid :: RecGetTangentialEdgeSurfaceIndices (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, const Vec<3> & m,1569ARRAY<int> & surfind, double eps) const1570{1571switch (op)1572{1573case TERM: case TERM_REF:1574{1575// *testout << "check vecinsolid4, p = " << p << ", v = " << v << "; m = " << m << endl;1576if (prim->VecInSolid4 (p, v, v2, m, eps) == DOES_INTERSECT)1577{1578prim->GetTangentialVecSurfaceIndices2 (p, v, m, surfind, eps);1579/*1580for (int j = 0; j < prim->GetNSurfaces(); j++)1581{1582if (fabs (prim->GetSurface(j).CalcFunctionValue (p)) < eps)1583{1584Vec<3> grad;1585prim->GetSurface(j).CalcGradient (p, grad);1586*testout << "grad = " << grad << endl;1587if (sqr (grad * v) < 1e-6 * v.Length2() * grad.Length2() &&1588sqr (grad * m) < 1e-6 * m.Length2() * grad.Length2() ) // new, 18032006 JS15891590{1591*testout << "add surf " << prim->GetSurfaceId(j) << endl;1592if (!surfind.Contains (prim->GetSurfaceId(j)))1593surfind.Append (prim->GetSurfaceId(j));1594}1595}1596}1597*/1598}1599break;1600}1601case UNION:1602case SECTION:1603{1604s1 -> RecGetTangentialEdgeSurfaceIndices (p, v, v2, m, surfind, eps);1605s2 -> RecGetTangentialEdgeSurfaceIndices (p, v, v2, m, surfind, eps);1606break;1607}1608case SUB:1609case ROOT:1610{1611s1 -> RecGetTangentialEdgeSurfaceIndices (p, v, v2, m, surfind, eps);1612break;1613}1614}1615}1616161716181619162016211622162316241625162616271628void Solid :: GetSurfaceIndices (IndexSet & iset) const1629{1630iset.Clear();1631RecGetSurfaceIndices (iset);1632}16331634void Solid :: RecGetSurfaceIndices (IndexSet & iset) const1635{1636switch (op)1637{1638case TERM: case TERM_REF:1639{1640/*1641int i;1642for (i = 1; i <= surfind.Size(); i++)1643if (surfind.Get(i) == prim->GetSurfaceId())1644return;1645surfind.Append (prim->GetSurfaceId());1646break;1647*/1648for (int j = 0; j < prim->GetNSurfaces(); j++)1649if (prim->SurfaceActive (j))1650{1651int siprim = prim->GetSurfaceId(j);1652iset.Add (siprim);1653}1654break;1655}1656case UNION:1657case SECTION:1658{1659s1 -> RecGetSurfaceIndices (iset);1660s2 -> RecGetSurfaceIndices (iset);1661break;1662}1663case SUB:1664case ROOT:1665{1666s1 -> RecGetSurfaceIndices (iset);1667break;1668}1669}1670}167116721673void Solid :: CalcOnePrimitiveSpecialPoints (const Box<3> & box, ARRAY<Point<3> > & pts) const1674{1675double eps = 1e-8 * box.Diam ();16761677pts.SetSize (0);1678this -> RecCalcOnePrimitiveSpecialPoints (pts);1679for (int i = pts.Size()-1; i >= 0; i--)1680{1681if (!IsIn (pts[i],eps) || IsStrictIn (pts[i],eps))1682pts.Delete (i);1683}1684}16851686void Solid :: RecCalcOnePrimitiveSpecialPoints (ARRAY<Point<3> > & pts) const1687{1688switch (op)1689{1690case TERM: case TERM_REF:1691{1692prim -> CalcSpecialPoints (pts);1693break;1694}1695case UNION:1696case SECTION:1697{1698s1 -> RecCalcOnePrimitiveSpecialPoints (pts);1699s2 -> RecCalcOnePrimitiveSpecialPoints (pts);1700break;1701}1702case SUB:1703case ROOT:1704{1705s1 -> RecCalcOnePrimitiveSpecialPoints (pts);1706break;1707}1708}1709}17101711171217131714BlockAllocator Solid :: ball(sizeof (Solid));1715}171617171718