netgen/libsrc/meshing/ruler3.cpp

1154 lines
28 KiB
C++
Raw Normal View History

2009-01-13 04:40:13 +05:00
#include <mystdlib.h>
#include "meshing.hpp"
namespace netgen
{
extern double minother;
extern double minwithoutother;
2016-12-11 22:02:16 +05:00
static double CalcElementBadness (const Array<Point3d, PointIndex::BASE> & points,
const Element & elem)
2009-01-13 04:40:13 +05:00
{
double vol, l, l4, l5, l6;
if (elem.GetNP() != 4)
{
if (elem.GetNP() == 5)
{
2016-12-11 22:02:16 +05:00
double z = points[elem.PNum(5)].Z();
2009-01-13 04:40:13 +05:00
if (z > -1e-8) return 1e8;
return (-1 / z) - z; // - 2;
}
return 0;
}
2016-12-11 22:02:16 +05:00
Vec3d v1 = points[elem.PNum(2)] - points[elem.PNum(1)];
Vec3d v2 = points[elem.PNum(3)] - points[elem.PNum(1)];
Vec3d v3 = points[elem.PNum(4)] - points[elem.PNum(1)];
2009-01-13 04:40:13 +05:00
vol = - (Cross (v1, v2) * v3);
2016-12-11 22:02:16 +05:00
l4 = Dist (points[elem.PNum(2)], points[elem.PNum(3)]);
l5 = Dist (points[elem.PNum(2)], points[elem.PNum(4)]);
l6 = Dist (points[elem.PNum(3)], points[elem.PNum(4)]);
2009-01-13 04:40:13 +05:00
l = v1.Length() + v2.Length() + v3.Length() + l4 + l5 + l6;
// testout << "vol = " << vol << " l = " << l << endl;
if (vol < 1e-8) return 1e10;
// (*testout) << "l^3/vol = " << (l*l*l / vol) << endl;
double err = pow (l*l*l/vol, 1.0/3.0) / 12;
return err;
}
int Meshing3 :: ApplyRules
(
2016-12-11 22:02:16 +05:00
Array<Point3d, PointIndex::BASE> & lpoints, // in: local points, out: old+new local points
Array<int, PointIndex::BASE> & allowpoint, // in: 2 .. it is allowed to use pointi, 1..will be allowed later, 0..no means
2009-01-25 17:35:25 +05:00
Array<MiniElement2d> & lfaces, // in: local faces, out: old+new local faces
2009-01-13 04:40:13 +05:00
INDEX lfacesplit, // for local faces in outer radius
INDEX_2_HASHTABLE<int> & connectedpairs, // connected pairs for prism-meshing
2009-01-25 17:35:25 +05:00
Array<Element> & elements, // out: new elements
Array<INDEX> & delfaces, // out: face indices of faces to delete
2009-01-13 04:40:13 +05:00
int tolerance, // quality class: 1 best
double sloppy, // quality strength
int rotind1, // how to rotate base element
float & retminerr // element error
)
{
NgProfiler::RegionTimer regtot(97);
2016-12-11 22:02:16 +05:00
float err, minerr, teterr, minteterr;
2009-01-13 04:40:13 +05:00
char ok, found, hc;
2016-12-11 22:02:16 +05:00
// vnetrule * rule;
2009-01-13 04:40:13 +05:00
Vector oldu, newu, newu1, newu2, allp;
Vec3d ui;
Point3d np;
const MiniElement2d * locface = NULL;
int loktestmode;
2016-12-11 22:02:16 +05:00
Array<int, PointIndex::BASE> pused; // point is already mapped, number of uses
Array<char> fused; // face is already mapped
Array<PointIndex> pmap; // map of reference point to local point
Array<bool, PointIndex::BASE> pfixed; // point mapped by face-map
Array<int> fmapi; // face in reference is mapped to face nr ...
Array<int> fmapr; // face in reference is rotated to map
Array<Point3d> transfreezone; // transformed free-zone
2011-07-25 14:40:23 +06:00
INDEX_2_CLOSED_HASHTABLE<int> ledges(100); // edges in local environment
2009-01-13 04:40:13 +05:00
2011-07-25 14:40:23 +06:00
Array<Point3d> tempnewpoints;
Array<MiniElement2d> tempnewfaces;
Array<int> tempdelfaces;
Array<Element> tempelements;
Array<Box3d> triboxes; // bounding boxes of local faces
2009-01-13 04:40:13 +05:00
2011-07-25 14:40:23 +06:00
Array<int, PointIndex::BASE> pnearness;
Array<int> fnearness;
2009-01-13 04:40:13 +05:00
2011-07-25 14:40:23 +06:00
static int cnt = 0;
2009-01-13 04:40:13 +05:00
cnt++;
delfaces.SetSize (0);
elements.SetSize (0);
// determine topological distance of faces and points to
// base element
pnearness.SetSize (lpoints.Size());
fnearness.SetSize (lfacesplit);
pnearness = INT_MAX/10;
2016-12-11 22:02:16 +05:00
for (PointIndex pi : lfaces[0].PNums())
pnearness[pi] = 0;
2009-01-13 04:40:13 +05:00
NgProfiler::RegionTimer reg2(98);
NgProfiler::StartTimer (90);
for (int loop = 0; loop < 2; loop++)
{
2016-12-11 22:02:16 +05:00
for (int i = 0; i < lfacesplit; i++)
2009-01-13 04:40:13 +05:00
{
const MiniElement2d & hface = lfaces[i];
int minn = INT_MAX-1;
2016-12-11 22:02:16 +05:00
for (PointIndex pi : hface.PNums())
2009-01-13 04:40:13 +05:00
{
2016-12-11 22:02:16 +05:00
int hi = pnearness[pi];
2009-01-13 04:40:13 +05:00
if (hi < minn) minn = hi;
}
if (minn < INT_MAX/10)
2016-12-11 22:02:16 +05:00
for (PointIndex pi : hface.PNums())
if (pnearness[pi] > minn+1)
pnearness[pi] = minn+1;
2009-01-13 04:40:13 +05:00
}
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= connectedpairs.GetNBags(); i++)
for (int j = 1; j <= connectedpairs.GetBagSize(i); j++)
2009-01-13 04:40:13 +05:00
{
INDEX_2 edge;
int val;
connectedpairs.GetData (i, j, edge, val);
if (pnearness[edge.I1()] > pnearness[edge.I2()] + 1)
pnearness[edge.I1()] = pnearness[edge.I2()] + 1;
if (pnearness[edge.I2()] > pnearness[edge.I1()] + 1)
pnearness[edge.I2()] = pnearness[edge.I1()] + 1;
}
}
2016-12-11 22:02:16 +05:00
for (int i : fnearness.Range())
2009-01-13 04:40:13 +05:00
{
int sum = 0;
2016-12-11 22:02:16 +05:00
for (PointIndex pi : lfaces[i].PNums())
sum += pnearness[pi];
2009-01-13 04:40:13 +05:00
fnearness[i] = sum;
}
NgProfiler::StopTimer (90);
NgProfiler::StartTimer (91);
// find bounding boxes of faces
triboxes.SetSize (lfaces.Size());
2016-12-11 22:02:16 +05:00
// for (int i = 0; i < lfaces.Size(); i++)
for (auto i : lfaces.Range())
2009-01-13 04:40:13 +05:00
{
const MiniElement2d & face = lfaces[i];
2016-12-11 22:02:16 +05:00
triboxes[i].SetPoint (lpoints[face[0]]);
for (int j = 1; j < face.GetNP(); j++)
triboxes[i].AddPoint (lpoints[face[j]]);
2009-01-13 04:40:13 +05:00
}
NgProfiler::StopTimer (91);
NgProfiler::StartTimer (92);
2016-12-11 22:02:16 +05:00
bool useedges = false;
for (int ri = 0; ri < rules.Size(); ri++)
if (rules[ri]->GetNEd()) useedges = true;
2009-01-13 04:40:13 +05:00
if (useedges)
{
ledges.SetSize (5 * lfacesplit);
2016-12-11 22:02:16 +05:00
for (int j = 0; j < lfacesplit; j++)
2009-01-13 04:40:13 +05:00
// if (fnearness[j] <= 5)
{
const MiniElement2d & face = lfaces[j];
int newp, oldp;
newp = face[face.GetNP()-1];
2016-12-11 22:02:16 +05:00
for (int k = 0; k < face.GetNP(); k++)
2009-01-13 04:40:13 +05:00
{
oldp = newp;
newp = face[k];
ledges.Set (INDEX_2::Sort(oldp, newp), 1);
}
}
}
NgProfiler::StopTimer (92);
NgProfiler::RegionTimer reg3(99);
pused.SetSize (lpoints.Size());
fused.SetSize (lfaces.Size());
found = 0;
minerr = tolfak * tolerance * tolerance;
minteterr = sloppy * tolerance;
if (testmode)
(*testout) << "cnt = " << cnt << " class = " << tolerance << endl;
// impossible, if no rule can be applied at any tolerance class
bool impossible = 1;
// check each rule:
2016-12-11 22:02:16 +05:00
for (int ri = 1; ri <= rules.Size(); ri++)
{
2009-01-13 04:40:13 +05:00
int base = (lfaces[0].GetNP() == 3) ? 100 : 200;
NgProfiler::RegionTimer regx1(base);
NgProfiler::RegionTimer regx(base+ri);
2014-08-20 01:58:36 +06:00
// sprintf (problems.Elem(ri), "");
*problems.Elem(ri) = '\0';
2009-01-13 04:40:13 +05:00
2016-12-11 22:02:16 +05:00
vnetrule * rule = rules.Get(ri);
2009-01-13 04:40:13 +05:00
if (rule->GetNP(1) != lfaces[0].GetNP())
continue;
if (rule->GetQuality() > tolerance)
{
if (rule->GetQuality() < 100) impossible = 0;
if (testmode)
sprintf (problems.Elem(ri), "Quality not ok");
continue;
}
if (testmode)
sprintf (problems.Elem(ri), "no mapping found");
loktestmode = testmode || rule->TestFlag ('t') || tolerance > 5;
if (loktestmode)
(*testout) << "Rule " << ri << " = " << rule->Name() << endl;
pmap.SetSize (rule->GetNP());
fmapi.SetSize (rule->GetNF());
fmapr.SetSize (rule->GetNF());
fused = 0;
pused = 0;
2016-12-11 22:02:16 +05:00
for (auto & p : pmap) p.Invalidate();
2009-01-13 04:40:13 +05:00
fmapi = 0;
2016-12-11 22:02:16 +05:00
for (int i : fmapr.Range())
fmapr[i] = rule->GetNP(i+1);
2009-01-13 04:40:13 +05:00
fused[0] = 1;
fmapi[0] = 1;
fmapr[0] = rotind1;
2016-12-11 22:02:16 +05:00
for (int j = 1; j <= lfaces[0].GetNP(); j++)
2009-01-13 04:40:13 +05:00
{
2016-12-11 22:02:16 +05:00
PointIndex locpi = lfaces[0].PNumMod (j+rotind1);
2009-01-13 04:40:13 +05:00
pmap.Set (rule->GetPointNr (1, j), locpi);
2016-12-11 22:02:16 +05:00
pused[locpi]++;
2009-01-13 04:40:13 +05:00
}
/*
map all faces
nfok .. first nfok-1 faces are mapped properly
*/
2016-12-11 22:02:16 +05:00
int nfok = 2;
2009-01-13 04:40:13 +05:00
NgProfiler::RegionTimer regfa(300);
NgProfiler::RegionTimer regx2(base+50+ri);
while (nfok >= 2)
{
if (nfok <= rule->GetNOldF())
{
// not all faces mapped
ok = 0;
2016-12-11 22:02:16 +05:00
int locfi = fmapi.Get(nfok);
int locfr = fmapr.Get(nfok);
2009-01-13 04:40:13 +05:00
int actfnp = rule->GetNP(nfok);
while (!ok)
{
locfr++;
if (locfr == actfnp + 1)
{
locfr = 1;
locfi++;
if (locfi > lfacesplit) break;
}
if (fnearness.Get(locfi) > rule->GetFNearness (nfok) ||
fused.Get(locfi) ||
actfnp != lfaces.Get(locfi).GetNP() )
{
// face not feasible in any rotation
locfr = actfnp;
}
else
{
ok = 1;
locface = &lfaces.Get(locfi);
// reference point already mapped differently ?
2016-12-11 22:02:16 +05:00
for (int j = 1; j <= actfnp && ok; j++)
2009-01-13 04:40:13 +05:00
{
2016-12-11 22:02:16 +05:00
PointIndex locpi = pmap.Get(rule->GetPointNr (nfok, j));
if (locpi.IsValid() && locpi != locface->PNumMod(j+locfr))
2009-01-13 04:40:13 +05:00
ok = 0;
}
// local point already used or point outside tolerance ?
2016-12-11 22:02:16 +05:00
for (int j = 1; j <= actfnp && ok; j++)
2009-01-13 04:40:13 +05:00
{
2016-12-11 22:02:16 +05:00
int refpi = rule->GetPointNr (nfok, j);
2009-01-13 04:40:13 +05:00
2016-12-11 22:02:16 +05:00
if (!pmap.Get(refpi).IsValid())
2009-01-13 04:40:13 +05:00
{
2016-12-11 22:02:16 +05:00
PointIndex locpi = locface->PNumMod (j + locfr);
2009-01-13 04:40:13 +05:00
2016-12-11 22:02:16 +05:00
if (pused[locpi])
2009-01-13 04:40:13 +05:00
ok = 0;
else
{
2016-12-11 22:02:16 +05:00
const Point3d & lp = lpoints[locpi];
2009-01-13 04:40:13 +05:00
const Point3d & rp = rule->GetPoint(refpi);
if ( Dist2 (lp, rp) * rule->PointDistFactor(refpi) > minerr)
{
impossible = 0;
ok = 0;
}
}
}
}
}
}
if (ok)
{
// map face nfok
fmapi.Set (nfok, locfi);
fmapr.Set (nfok, locfr);
fused.Set (locfi, 1);
2016-12-11 22:02:16 +05:00
for (int j = 1; j <= rule->GetNP (nfok); j++)
2009-01-13 04:40:13 +05:00
{
2016-12-11 22:02:16 +05:00
PointIndex locpi = locface->PNumMod(j+locfr);
2009-01-13 04:40:13 +05:00
if (rule->GetPointNr (nfok, j) <= 3 &&
pmap.Get(rule->GetPointNr(nfok, j)) != locpi)
(*testout) << "change face1 point, mark1" << endl;
pmap.Set(rule->GetPointNr (nfok, j), locpi);
2016-12-11 22:02:16 +05:00
pused[locpi]++;
2009-01-13 04:40:13 +05:00
}
nfok++;
}
else
{
// backtrack one face
fmapi.Set (nfok, 0);
fmapr.Set (nfok, rule->GetNP(nfok));
nfok--;
fused.Set (fmapi.Get(nfok), 0);
2016-12-11 22:02:16 +05:00
for (int j = 1; j <= rule->GetNP (nfok); j++)
2009-01-13 04:40:13 +05:00
{
2016-12-11 22:02:16 +05:00
int refpi = rule->GetPointNr (nfok, j);
pused[pmap.Get(refpi)]--;
if (pused[pmap.Get(refpi)] == 0)
2009-01-13 04:40:13 +05:00
{
2016-12-11 22:02:16 +05:00
// pmap.Set(refpi, 0);
pmap.Elem(refpi).Invalidate();
2009-01-13 04:40:13 +05:00
}
}
}
}
else
{
NgProfiler::RegionTimer regfb(301);
// all faces are mapped
// now map all isolated points:
if (loktestmode)
{
(*testout) << "Faces Ok" << endl;
sprintf (problems.Elem(ri), "Faces Ok");
}
2016-12-11 22:02:16 +05:00
int npok = 1;
int incnpok = 1;
2009-01-13 04:40:13 +05:00
pfixed.SetSize (pmap.Size());
2016-12-11 22:02:16 +05:00
/*
for (int i = 1; i <= pmap.Size(); i++)
2009-01-13 04:40:13 +05:00
pfixed.Set(i, (pmap.Get(i) != 0) );
2016-12-11 22:02:16 +05:00
*/
for (int i : pmap.Range())
pfixed[i] = pmap[i].IsValid();
2009-01-13 04:40:13 +05:00
while (npok >= 1)
{
if (npok <= rule->GetNOldP())
{
if (pfixed.Get(npok))
{
if (incnpok)
npok++;
else
npok--;
}
else
{
2016-12-11 22:02:16 +05:00
PointIndex locpi = pmap.Elem(npok);
2009-01-13 04:40:13 +05:00
ok = 0;
2016-12-11 22:02:16 +05:00
if (locpi.IsValid())
pused[locpi]--;
2009-01-13 04:40:13 +05:00
2016-12-11 22:02:16 +05:00
while (!ok && locpi < lpoints.Size()-1+PointIndex::BASE)
2009-01-13 04:40:13 +05:00
{
ok = 1;
locpi++;
2016-12-11 22:02:16 +05:00
if (pused[locpi] ||
pnearness[locpi] > rule->GetPNearness(npok))
2009-01-13 04:40:13 +05:00
{
ok = 0;
}
2016-12-11 22:02:16 +05:00
else if (allowpoint[locpi] != 2)
2009-01-13 04:40:13 +05:00
{
ok = 0;
2016-12-11 22:02:16 +05:00
if (allowpoint[locpi] == 1)
2009-01-13 04:40:13 +05:00
impossible = 0;
}
else
{
2016-12-11 22:02:16 +05:00
const Point3d & lp = lpoints[locpi];
2009-01-13 04:40:13 +05:00
const Point3d & rp = rule->GetPoint(npok);
if ( Dist2 (lp, rp) * rule->PointDistFactor(npok) > minerr)
{
ok = 0;
impossible = 0;
}
}
}
if (ok)
{
pmap.Set (npok, locpi);
if (npok <= 3)
(*testout) << "set face1 point, mark3" << endl;
2016-12-11 22:02:16 +05:00
pused[locpi]++;
2009-01-13 04:40:13 +05:00
npok++;
incnpok = 1;
}
else
{
2016-12-11 22:02:16 +05:00
// pmap.Set (npok, 0);
pmap.Elem(npok).Invalidate();
2009-01-13 04:40:13 +05:00
if (npok <= 3)
(*testout) << "set face1 point, mark4" << endl;
npok--;
incnpok = 0;
}
}
}
else
{
NgProfiler::RegionTimer regfa2(302);
// all points are mapped
if (loktestmode)
{
(*testout) << "Mapping found!!: Rule " << rule->Name() << endl;
2016-12-11 22:02:16 +05:00
for (auto pi : pmap)
(*testout) << pi << " ";
2009-01-13 04:40:13 +05:00
(*testout) << endl;
sprintf (problems.Elem(ri), "mapping found");
(*testout) << rule->GetNP(1) << " = " << lfaces.Get(1).GetNP() << endl;
}
ok = 1;
// check mapedges:
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= rule->GetNEd(); i++)
2009-01-13 04:40:13 +05:00
{
INDEX_2 in2(pmap.Get(rule->GetEdge(i).i1),
pmap.Get(rule->GetEdge(i).i2));
in2.Sort();
if (!ledges.Used (in2)) ok = 0;
}
// check prism edges:
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= rule->GetNE(); i++)
2009-01-13 04:40:13 +05:00
{
const Element & el = rule->GetElement (i);
if (el.GetType() == PRISM)
{
2016-12-11 22:02:16 +05:00
for (int j = 1; j <= 3; j++)
2009-01-13 04:40:13 +05:00
{
INDEX_2 in2(pmap.Get(el.PNum(j)),
pmap.Get(el.PNum(j+3)));
in2.Sort();
if (!connectedpairs.Used (in2)) ok = 0;
}
}
if (el.GetType() == PYRAMID)
{
if (loktestmode)
(*testout) << "map pyramid, rule = " << rule->Name() << endl;
2016-12-11 22:02:16 +05:00
for (int j = 1; j <= 2; j++)
2009-01-13 04:40:13 +05:00
{
INDEX_2 in2;
if (j == 1)
{
in2.I1() = pmap.Get(el.PNum(2));
in2.I2() = pmap.Get(el.PNum(3));
}
else
{
in2.I1() = pmap.Get(el.PNum(1));
in2.I2() = pmap.Get(el.PNum(4));
}
in2.Sort();
if (!connectedpairs.Used (in2))
{
ok = 0;
if (loktestmode)
(*testout) << "no pair" << endl;
}
}
}
}
2016-12-11 22:02:16 +05:00
for (int i = rule->GetNOldF() + 1; i <= rule->GetNF(); i++)
2009-01-13 04:40:13 +05:00
fmapi.Set(i, 0);
if (ok)
{
foundmap.Elem(ri)++;
}
// deviation of existing points
oldu.SetSize (3 * rule->GetNOldP());
newu.SetSize (3 * (rule->GetNP() - rule->GetNOldP()));
allp.SetSize (3 * rule->GetNP());
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= rule->GetNOldP(); i++)
2009-01-13 04:40:13 +05:00
{
2016-12-11 22:02:16 +05:00
const Point3d & lp = lpoints[pmap.Get(i)];
2009-01-13 04:40:13 +05:00
const Point3d & rp = rule->GetPoint(i);
oldu (3*i-3) = lp.X()-rp.X();
oldu (3*i-2) = lp.Y()-rp.Y();
oldu (3*i-1) = lp.Z()-rp.Z();
2009-01-13 04:40:13 +05:00
allp (3*i-3) = lp.X();
allp (3*i-2) = lp.Y();
allp (3*i-1) = lp.Z();
2009-01-13 04:40:13 +05:00
}
if (rule->GetNP() > rule->GetNOldP())
{
newu.SetSize (rule->GetOldUToNewU().Height());
rule->GetOldUToNewU().Mult (oldu, newu);
}
// int idiff = 3 * (rule->GetNP()-rule->GetNOldP());
int idiff = 3 * rule->GetNOldP();
2016-12-11 22:02:16 +05:00
for (int i = rule->GetNOldP()+1; i <= rule->GetNP(); i++)
2009-01-13 04:40:13 +05:00
{
const Point3d & rp = rule->GetPoint(i);
allp (3*i-3) = rp.X() + newu(3*i-3 - idiff);
allp (3*i-2) = rp.Y() + newu(3*i-2 - idiff);
allp (3*i-1) = rp.Z() + newu(3*i-1 - idiff);
2009-01-13 04:40:13 +05:00
}
rule->SetFreeZoneTransformation (allp,
tolerance + int(sloppy));
if (!rule->ConvexFreeZone())
{
ok = 0;
sprintf (problems.Elem(ri), "Freezone not convex");
if (loktestmode)
(*testout) << "Freezone not convex" << endl;
}
if (loktestmode)
{
2009-01-25 17:35:25 +05:00
const Array<Point3d> & fz = rule->GetTransFreeZone();
2009-01-13 04:40:13 +05:00
(*testout) << "Freezone: " << endl;
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= fz.Size(); i++)
2009-01-13 04:40:13 +05:00
(*testout) << fz.Get(i) << endl;
}
// check freezone:
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= lpoints.Size(); i++)
2009-01-13 04:40:13 +05:00
{
if ( !pused.Get(i) )
{
const Point3d & lp = lpoints.Get(i);
if (rule->fzbox.IsIn (lp))
{
if (rule->IsInFreeZone(lp))
{
if (loktestmode)
{
(*testout) << "Point " << i
<< " in Freezone" << endl;
sprintf (problems.Elem(ri),
"locpoint %d in Freezone", i);
}
ok = 0;
break;
}
}
}
}
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= lfaces.Size() && ok; i++)
2009-01-13 04:40:13 +05:00
{
2009-01-25 17:35:25 +05:00
static Array<int> lpi(4);
2009-01-13 04:40:13 +05:00
if (!fused.Get(i))
{
int triin;
const MiniElement2d & lfacei = lfaces.Get(i);
if (!triboxes.Elem(i).Intersect (rule->fzbox))
triin = 0;
else
{
int li, lj;
for (li = 1; li <= lfacei.GetNP(); li++)
{
int lpii = 0;
2016-12-11 22:02:16 +05:00
PointIndex pi = lfacei.PNum(li);
2009-01-13 04:40:13 +05:00
for (lj = 1; lj <= rule->GetNOldP(); lj++)
if (pmap.Get(lj) == pi)
lpii = lj;
lpi.Elem(li) = lpii;
}
if (lfacei.GetNP() == 3)
{
triin = rule->IsTriangleInFreeZone
(
2016-12-11 22:02:16 +05:00
lpoints[lfacei.PNum(1)],
lpoints[lfacei.PNum(2)],
lpoints[lfacei.PNum(3)], lpi, 1
2009-01-13 04:40:13 +05:00
);
}
else
{
triin = rule->IsQuadInFreeZone
(
2016-12-11 22:02:16 +05:00
lpoints[lfacei.PNum(1)],
lpoints[lfacei.PNum(2)],
lpoints[lfacei.PNum(3)],
lpoints[lfacei.PNum(4)],
2009-01-13 04:40:13 +05:00
lpi, 1
);
}
}
if (triin == -1)
{
ok = 0;
}
if (triin == 1)
{
#ifdef TEST_JS
ok = 0;
if (loktestmode)
{
(*testout) << "El with " << lfaces.Get(i).GetNP() << " points in freezone: "
<< lfaces.Get(i).PNum(1) << " - "
<< lfaces.Get(i).PNum(2) << " - "
<< lfaces.Get(i).PNum(3) << " - "
<< lfaces.Get(i).PNum(4) << endl;
for (int lj = 1; lj <= lfaces.Get(i).GetNP(); lj++)
2016-12-11 22:02:16 +05:00
(*testout) << lpoints[lfaces.Get(i).PNum(lj)] << " ";
2009-01-13 04:40:13 +05:00
(*testout) << endl;
sprintf (problems.Elem(ri), "triangle (%d, %d, %d) in Freezone",
lfaces.Get(i).PNum(1), lfaces.Get(i).PNum(2),
lfaces.Get(i).PNum(3));
}
#else
if (loktestmode)
{
if (lfacei.GetNP() == 3)
{
(*testout) << "Triangle in freezone: "
<< lfacei.PNum(1) << " - "
<< lfacei.PNum(2) << " - "
<< lfacei.PNum(3)
<< ", or "
2016-12-11 22:02:16 +05:00
<< lpoints[lfacei.PNum(1)] << " - "
<< lpoints[lfacei.PNum(2)] << " - "
<< lpoints[lfacei.PNum(3)]
2009-01-13 04:40:13 +05:00
<< endl;
(*testout) << "lpi = " << lpi.Get(1) << ", "
<< lpi.Get(2) << ", " << lpi.Get(3) << endl;
}
else
(*testout) << "Quad in freezone: "
<< lfacei.PNum(1) << " - "
<< lfacei.PNum(2) << " - "
<< lfacei.PNum(3) << " - "
<< lfacei.PNum(4)
<< ", or "
2016-12-11 22:02:16 +05:00
<< lpoints[lfacei.PNum(1)] << " - "
<< lpoints[lfacei.PNum(2)] << " - "
<< lpoints[lfacei.PNum(3)] << " - "
<< lpoints[lfacei.PNum(4)]
2009-01-13 04:40:13 +05:00
<< endl;
sprintf (problems.Elem(ri), "triangle (%d, %d, %d) in Freezone",
int(lfaces.Get(i).PNum(1)),
int(lfaces.Get(i).PNum(2)),
int(lfaces.Get(i).PNum(3)));
}
hc = 0;
2016-12-11 22:02:16 +05:00
for (int k = rule->GetNOldF() + 1; k <= rule->GetNF(); k++)
2009-01-13 04:40:13 +05:00
{
if (rule->GetPointNr(k, 1) <= rule->GetNOldP() &&
rule->GetPointNr(k, 2) <= rule->GetNOldP() &&
rule->GetPointNr(k, 3) <= rule->GetNOldP())
{
2016-12-11 22:02:16 +05:00
for (int j = 1; j <= 3; j++)
2009-01-13 04:40:13 +05:00
if (lfaces.Get(i).PNumMod(j ) == pmap.Get(rule->GetPointNr(k, 1)) &&
lfaces.Get(i).PNumMod(j+1) == pmap.Get(rule->GetPointNr(k, 3)) &&
lfaces.Get(i).PNumMod(j+2) == pmap.Get(rule->GetPointNr(k, 2)))
{
fmapi.Elem(k) = i;
hc = 1;
// (*testout) << "found from other side: "
// << rule->Name()
// << " ( " << pmap.Get (rule->GetPointNr(k, 1))
// << " - " << pmap.Get (rule->GetPointNr(k, 2))
// << " - " << pmap.Get (rule->GetPointNr(k, 3)) << " ) "
// << endl;
strcpy (problems.Elem(ri), "other");
}
}
}
if (!hc)
{
if (loktestmode)
{
(*testout) << "Triangle in freezone: "
<< lfaces.Get(i).PNum(1) << " - "
<< lfaces.Get(i).PNum(2) << " - "
<< lfaces.Get(i).PNum(3) << endl;
sprintf (problems.Elem(ri), "triangle (%d, %d, %d) in Freezone",
int (lfaces.Get(i).PNum(1)),
int (lfaces.Get(i).PNum(2)),
int (lfaces.Get(i).PNum(3)));
}
ok = 0;
}
#endif
}
}
}
if (ok)
{
err = 0;
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= rule->GetNOldP(); i++)
2009-01-13 04:40:13 +05:00
{
2016-12-11 22:02:16 +05:00
double hf = rule->CalcPointDist (i, lpoints[pmap.Get(i)]);
2009-01-13 04:40:13 +05:00
if (hf > err) err = hf;
}
if (loktestmode)
{
(*testout) << "Rule ok" << endl;
sprintf (problems.Elem(ri), "Rule ok, err = %f", err);
}
// newu = rule->GetOldUToNewU() * oldu;
// set new points:
2016-12-11 22:02:16 +05:00
int oldnp = rule->GetNOldP();
int noldlp = lpoints.Size();
int noldlf = lfaces.Size();
2009-01-13 04:40:13 +05:00
2016-12-11 22:02:16 +05:00
for (int i = oldnp + 1; i <= rule->GetNP(); i++)
2009-01-13 04:40:13 +05:00
{
np = rule->GetPoint(i);
np.X() += newu (3 * (i-oldnp) - 3);
np.Y() += newu (3 * (i-oldnp) - 2);
np.Z() += newu (3 * (i-oldnp) - 1);
lpoints.Append (np);
pmap.Elem(i) = lpoints.Size()-1+PointIndex::BASE;
2009-01-13 04:40:13 +05:00
}
// Set new Faces:
2016-12-11 22:02:16 +05:00
for (int i = rule->GetNOldF() + 1; i <= rule->GetNF(); i++)
2009-01-13 04:40:13 +05:00
if (!fmapi.Get(i))
{
MiniElement2d nface(rule->GetNP(i));
2016-12-11 22:02:16 +05:00
for (int j = 1; j <= nface.GetNP(); j++)
2009-01-13 04:40:13 +05:00
nface.PNum(j) = pmap.Get(rule->GetPointNr (i, j));
lfaces.Append (nface);
}
// Delete old Faces:
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= rule->GetNDelF(); i++)
2009-01-13 04:40:13 +05:00
delfaces.Append (fmapi.Get(rule->GetDelFace(i)));
2016-12-11 22:02:16 +05:00
for (int i = rule->GetNOldF()+1; i <= rule->GetNF(); i++)
2009-01-13 04:40:13 +05:00
if (fmapi.Get(i))
{
delfaces.Append (fmapi.Get(i));
fmapi.Elem(i) = 0;
}
// check orientation
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= rule->GetNO() && ok; i++)
2009-01-13 04:40:13 +05:00
{
const fourint * fouri;
fouri = &rule->GetOrientation(i);
2016-12-11 22:02:16 +05:00
Vec3d v1 (lpoints[pmap.Get(fouri->i1)],
lpoints[pmap.Get(fouri->i2)]);
Vec3d v2 (lpoints[pmap.Get(fouri->i1)],
lpoints[pmap.Get(fouri->i3)]);
Vec3d v3 (lpoints[pmap.Get(fouri->i1)],
lpoints[pmap.Get(fouri->i4)]);
2009-01-13 04:40:13 +05:00
Vec3d n;
Cross (v1, v2, n);
//if (n * v3 >= -1e-7*n.Length()*v3.Length()) // OR -1e-7???
if (n * v3 >= -1e-9)
{
if (loktestmode)
{
sprintf (problems.Elem(ri), "Orientation wrong");
(*testout) << "Orientation wrong ("<< n*v3 << ")" << endl;
}
ok = 0;
}
}
// new points in free-zone ?
2016-12-11 22:02:16 +05:00
for (int i = rule->GetNOldP() + 1; i <= rule->GetNP() && ok; i++)
2009-01-13 04:40:13 +05:00
if (!rule->IsInFreeZone (lpoints.Get(pmap.Get(i))))
{
if (loktestmode)
{
(*testout) << "Newpoint " << lpoints.Get(pmap.Get(i))
<< " outside convex hull" << endl;
sprintf (problems.Elem(ri), "newpoint outside convex hull");
}
ok = 0;
}
// insert new elements
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= rule->GetNE(); i++)
2009-01-13 04:40:13 +05:00
{
elements.Append (rule->GetElement(i));
2016-12-11 22:02:16 +05:00
for (int j = 1; j <= elements.Get(i).NP(); j++)
2009-01-13 04:40:13 +05:00
elements.Elem(i).PNum(j) = pmap.Get(elements.Get(i).PNum(j));
}
// Calculate Element badness
teterr = 0;
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= elements.Size(); i++)
2009-01-13 04:40:13 +05:00
{
2016-12-11 22:02:16 +05:00
double hf = CalcElementBadness (lpoints, elements.Get(i));
2009-01-13 04:40:13 +05:00
if (hf > teterr) teterr = hf;
}
/*
// keine gute Erfahrung am 25.1.2000, js
if (ok && teterr < 100 &&
(rule->TestFlag('b') || tolerance > 10) )
{
(*mycout) << "Reset teterr "
<< rule->Name()
<< " err = " << teterr
<< endl;
teterr = 1;
}
*/
// compare edgelength
if (rule->TestFlag('l'))
{
double oldlen = 0;
double newlen = 0;
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= rule->GetNDelF(); i++)
2009-01-13 04:40:13 +05:00
{
const Element2d & face =
rule->GetFace (rule->GetDelFace(i));
2016-12-11 22:02:16 +05:00
for (int j = 1; j <= 3; j++)
2009-01-13 04:40:13 +05:00
{
const Point3d & p1 =
2016-12-11 22:02:16 +05:00
lpoints[pmap.Get(face.PNumMod(j))];
2009-01-13 04:40:13 +05:00
const Point3d & p2 =
2016-12-11 22:02:16 +05:00
lpoints[pmap.Get(face.PNumMod(j+1))];
2009-01-13 04:40:13 +05:00
oldlen += Dist(p1, p2);
}
}
2016-12-11 22:02:16 +05:00
for (int i = rule->GetNOldF()+1; i <= rule->GetNF(); i++)
2009-01-13 04:40:13 +05:00
{
const Element2d & face = rule->GetFace (i);
2016-12-11 22:02:16 +05:00
for (int j = 1; j <= 3; j++)
2009-01-13 04:40:13 +05:00
{
const Point3d & p1 =
2016-12-11 22:02:16 +05:00
lpoints[pmap.Get(face.PNumMod(j))];
2009-01-13 04:40:13 +05:00
const Point3d & p2 =
2016-12-11 22:02:16 +05:00
lpoints[pmap.Get(face.PNumMod(j+1))];
2009-01-13 04:40:13 +05:00
newlen += Dist(p1, p2);
}
}
if (oldlen < newlen)
{
ok = 0;
if (loktestmode)
sprintf (problems.Elem(ri), "oldlen < newlen");
}
}
if (loktestmode)
(*testout) << "ok = " << int(ok)
<< "teterr = " << teterr
<< "minteterr = " << minteterr << endl;
if (ok && teterr < tolerance)
{
canuse.Elem(ri) ++;
/*
(*testout) << "can use rule " << rule->Name()
<< ", err = " << teterr << endl;
for (i = 1; i <= pmap.Size(); i++)
(*testout) << pmap.Get(i) << " ";
(*testout) << endl;
*/
if (strcmp (problems.Elem(ri), "other") == 0)
{
if (teterr < minother)
minother = teterr;
}
else
{
if (teterr < minwithoutother)
minwithoutother = teterr;
}
}
if (teterr > minteterr) impossible = 0;
if (ok && teterr < minteterr)
{
if (loktestmode)
(*testout) << "use rule" << endl;
found = ri;
minteterr = teterr;
if (testmode)
{
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= rule->GetNOldP(); i++)
2009-01-13 04:40:13 +05:00
{
(*testout) << "P" << i << ": Ref: "
<< rule->GetPoint (i) << " is: "
<< lpoints.Get(pmap.Get(i)) << endl;
}
}
tempnewpoints.SetSize (0);
2016-12-11 22:02:16 +05:00
for (int i = noldlp+1; i <= lpoints.Size(); i++)
2009-01-13 04:40:13 +05:00
tempnewpoints.Append (lpoints.Get(i));
tempnewfaces.SetSize (0);
2016-12-11 22:02:16 +05:00
for (int i = noldlf+1; i <= lfaces.Size(); i++)
2009-01-13 04:40:13 +05:00
tempnewfaces.Append (lfaces.Get(i));
tempdelfaces.SetSize (0);
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= delfaces.Size(); i++)
2009-01-13 04:40:13 +05:00
tempdelfaces.Append (delfaces.Get(i));
tempelements.SetSize (0);
2016-12-11 22:02:16 +05:00
for (int i = 1; i <= elements.Size(); i++)
2009-01-13 04:40:13 +05:00
tempelements.Append (elements.Get(i));
}
lpoints.SetSize (noldlp);
lfaces.SetSize (noldlf);
delfaces.SetSize (0);
elements.SetSize (0);
}
npok = rule->GetNOldP();
incnpok = 0;
}
}
nfok = rule->GetNOldF();
2016-12-11 22:02:16 +05:00
for (int j = 1; j <= rule->GetNP (nfok); j++)
2009-01-13 04:40:13 +05:00
{
2016-12-11 22:02:16 +05:00
int refpi = rule->GetPointNr (nfok, j);
pused[pmap.Get(refpi)]--;
2009-01-13 04:40:13 +05:00
2016-12-11 22:02:16 +05:00
if (pused[pmap.Get(refpi)] == 0)
pmap.Elem(refpi).Invalidate();
2009-01-13 04:40:13 +05:00
}
}
}
if (loktestmode)
(*testout) << "end rule" << endl;
}
if (found)
{
2016-12-11 22:02:16 +05:00
/*
2009-01-13 04:40:13 +05:00
for (i = 1; i <= tempnewpoints.Size(); i++)
lpoints.Append (tempnewpoints.Get(i));
2016-12-11 22:02:16 +05:00
*/
for (Point3d p : tempnewpoints)
lpoints.Append(p);
/*
2009-01-13 04:40:13 +05:00
for (i = 1; i <= tempnewfaces.Size(); i++)
if (tempnewfaces.Get(i).PNum(1))
lfaces.Append (tempnewfaces.Get(i));
2016-12-11 22:02:16 +05:00
*/
for (int i : tempnewfaces.Range())
if (tempnewfaces[i].PNum(1).IsValid())
lfaces.Append (tempnewfaces[i]);
/*
2009-01-13 04:40:13 +05:00
for (i = 1; i <= tempdelfaces.Size(); i++)
delfaces.Append (tempdelfaces.Get(i));
2016-12-11 22:02:16 +05:00
*/
for (int i : tempdelfaces.Range())
delfaces.Append (tempdelfaces[i]);
/*
2009-01-13 04:40:13 +05:00
for (i = 1; i <= tempelements.Size(); i++)
elements.Append (tempelements.Get(i));
2016-12-11 22:02:16 +05:00
*/
for (int i : tempelements.Range())
elements.Append (tempelements[i]);
2009-01-13 04:40:13 +05:00
}
retminerr = minerr;
if (impossible && found == 0)
return -1;
return found;
}
}