//C++ TO C# CONVERTER WARNING: The original C++ declaration of the following method implementation was not found:
        public void FindInnerBoxes(AdFront2 adfront, testinnerDelegate testinner)
        {
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer = NgProfiler::CreateTimer("LocalH::FindInnerBoxes 2d");
            NgProfiler.RegionTimer reg = new NgProfiler.RegionTimer(FindInnerBoxes_timer);

            for (int i = 0; i < boxes.Size(); i++)
            {
                boxes[i].flags.isinner = 0;
            }

            root.flags.isinner = 0;

            Point <2> rpmid(root.xmid[0], root.xmid[1]);              // , root->xmid[2]);
            Vec <2> rv(root.h2, root.h2);

            Point <2> rx2 = rpmid + rv;

            // Point<2> rx1 = rpmid - rv;


            root.flags.pinner = !adfront.SameSide(rpmid, rx2);

            if (testinner != null)
            {
                (*testout) << "inner = " << root.flags.pinner << " =?= " << testinner(rpmid) << "\n";
            }


            int              nf        = adfront.GetNFL();
            Array <int>      faceinds  = new Array <int>(nf);
            Array <Box <3> > faceboxes = new Array <Box <3> >(nf);

            for (int i = 0; i < nf; i++)
            {
                faceinds[i] = i;
                // adfront->GetFaceBoundingBox(i, faceboxes.Elem(i));

                FrontLine line = adfront.GetLine(i);
                faceboxes[i].Set(adfront.GetPoint(line.L().I1()));
                faceboxes[i].Add(adfront.GetPoint(line.L().I2()));
            }

            for (int i = 0; i < 8; i++)
            {
                FindInnerBoxesRec2(root.childs[i], adfront, faceboxes, faceinds, nf);
            }
        }
//C++ TO C# CONVERTER WARNING: The original C++ declaration of the following method implementation was not found:
        public void BlockFillLocalH(Mesh mesh, MeshingParameters mp)
        {
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer = NgProfiler::CreateTimer("Meshing2::BlockFill");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer1 = NgProfiler::CreateTimer("Meshing2::BlockFill 1");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer2 = NgProfiler::CreateTimer("Meshing2::BlockFill 2");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer3 = NgProfiler::CreateTimer("Meshing2::BlockFill 3");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer4 = NgProfiler::CreateTimer("Meshing2::BlockFill 4");
            NgProfiler.RegionTimer reg = new NgProfiler.RegionTimer(BlockFillLocalH_timer);

            NgProfiler.StartTimer(BlockFillLocalH_timer1);

            double filldist = mp.filldist;

            Console.Write("blockfill local h");
            Console.Write("\n");
            Console.Write("rel filldist = ");
            Console.Write(filldist);
            Console.Write("\n");
            PrintMessage(3, "blockfill local h");

            Array <Point <3> > npoints = new Array <Point <3> >();

            // adfront -> CreateTrees();

            Box <3> bbox(Box <3> .EMPTY_BOX);

            double maxh = 0;

            for (int i = 0; i < adfront.GetNFL(); i++)
            {
                FrontLine line = adfront.GetLine(i);

                const Point <3>& p1 = adfront.GetPoint(line.L().I1());
                const Point <3>& p2 = adfront.GetPoint(line.L().I2());

                maxh = Math.Max(maxh, Dist(p1, p2));

                bbox.Add(p1);
                bbox.Add(p2);
            }


            Console.Write("bbox = ");
            Console.Write(bbox);
            Console.Write("\n");


            // Point<3> mpc = bbox.Center();
            bbox.Increase(bbox.Diam() / 2);
            Box <3> meshbox = bbox;

            NgProfiler.StopTimer(BlockFillLocalH_timer1);
            NgProfiler.StartTimer(BlockFillLocalH_timer2);


            LocalH loch2 = new LocalH(bbox, 1, 2);

            if (mp.maxh < maxh)
            {
                maxh = mp.maxh;
            }

            bool changed;

            do
            {
                mesh.LocalHFunction().ClearFlags();

                for (int i = 0; i < adfront.GetNFL(); i++)
                {
                    FrontLine line = adfront.GetLine(i);

                    Box <3> bbox(adfront.GetPoint(line.L().I1()));

                    bbox.Add(adfront.GetPoint(line.L().I2()));


                    double filld = filldist * bbox.Diam();
                    bbox.Increase(filld);

                    mesh.LocalHFunction().CutBoundary(bbox);
                }


                mesh.LocalHFunction().FindInnerBoxes(adfront, null);

                npoints.SetSize(0);
                mesh.LocalHFunction().GetInnerPoints(npoints);

                changed = false;
                for (int i = 0; i < npoints.Size(); i++)
                {
                    if (mesh.LocalHFunction().GetH(npoints[i]) > 1.2 * maxh)
                    {
                        mesh.LocalHFunction().SetH(npoints[i], maxh);
                        changed = true;
                    }
                }
            } while (changed);

            NgProfiler.StopTimer(BlockFillLocalH_timer2);
            NgProfiler.StartTimer(BlockFillLocalH_timer3);


            if (debugparam.slowchecks)
            {
                (*testout) << "Blockfill with points: " << "\n";
            }
            *testout << "loch = " << mesh.LocalHFunction() << "\n";

            *testout << "npoints = " << "\n" << npoints << "\n";

            for (int i = 1; i <= npoints.Size(); i++)
            {
                if (meshbox.IsIn(npoints.Get(i)))
                {
                    PointIndex gpnum = mesh.AddPoint(npoints.Get(i));
                    adfront.AddPoint(npoints.Get(i), gpnum);

                    if (debugparam.slowchecks)
                    {
                        (*testout) << npoints.Get(i) << "\n";

                        Point <2> p2d(npoints.Get(i)(0), npoints.Get(i)(1));

                        if (!adfront.Inside(p2d))
                        {
                            Console.Write("add outside point");
                            Console.Write("\n");
                            (*testout) << "outside" << "\n";
                        }
                    }
                }
            }

            NgProfiler.StopTimer(BlockFillLocalH_timer3);
            NgProfiler.StartTimer(BlockFillLocalH_timer4);


            // find outer points

            loch2.ClearFlags();

            for (int i = 0; i < adfront.GetNFL(); i++)
            {
                FrontLine line = adfront.GetLine(i);

                Box <3> bbox(adfront.GetPoint(line.L().I1()));

                bbox.Add(adfront.GetPoint(line.L().I2()));

                loch2.SetH(bbox.Center(), bbox.Diam());
            }


            for (int i = 0; i < adfront.GetNFL(); i++)
            {
                FrontLine line = adfront.GetLine(i);

                Box <3> bbox(adfront.GetPoint(line.L().I1()));

                bbox.Add(adfront.GetPoint(line.L().I2()));

                bbox.Increase(filldist * bbox.Diam());
                loch2.CutBoundary(bbox);
            }

            loch2.FindInnerBoxes(adfront, null);

            // outer points : smooth mesh-grading
            npoints.SetSize(0);
            loch2.GetOuterPoints(npoints);

            for (int i = 1; i <= npoints.Size(); i++)
            {
                if (meshbox.IsIn(npoints.Get(i)))
                {
                    PointIndex gpnum = mesh.AddPoint(npoints.Get(i));
                    adfront.AddPoint(npoints.Get(i), gpnum);
                }
            }

            NgProfiler.StopTimer(BlockFillLocalH_timer4);
        }
//C++ TO C# CONVERTER WARNING: The original C++ declaration of the following method implementation was not found:
        public void Delaunay(Mesh mesh, int domainnr, MeshingParameters mp)
        {
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer = NgProfiler::CreateTimer("Meshing2::Delaunay - total");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timerstart = NgProfiler::CreateTimer("Meshing2::Delaunay - start");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timerfinish = NgProfiler::CreateTimer("Meshing2::Delaunay - finish");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer1 = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer1a = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental a");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer1b = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental b");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer1c = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental c");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer1d = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental d");
            NgProfiler.RegionTimer reg = new NgProfiler.RegionTimer(Delaunay_timer);



            Console.Write("2D Delaunay meshing (in progress)");
            Console.Write("\n");


            BlockFillLocalH(mesh, mp);

            NgProfiler.StartTimer(Delaunay_timerstart);

            // do the delaunay


            // face bounding box:
            Box <3> bbox(Box <3> .EMPTY_BOX);

            for (int i = 0; i < adfront.GetNFL(); i++)
            {
                FrontLine line = adfront.GetLine(i);
                bbox.Add(Point <3> (adfront.GetPoint(line.L [0])));
                bbox.Add(Point <3> (adfront.GetPoint(line.L [1])));
            }

            for (int i = 0; i < mesh.LockedPoints().Size(); i++)
            {
                bbox.Add(new mesh.Point(mesh.LockedPoints [i]));
            }

            Console.Write("bbox = ");
            Console.Write(bbox);
            Console.Write("\n");

            // external point
            Vec <3> vdiag = bbox.PMax() - bbox.PMin();

            var          old_points = mesh.Points().Range();
            DelaunayTrig startel    = new DelaunayTrig();

            startel[0] = mesh.AddPoint(bbox.PMin() + Vec <3> (-8 * vdiag(0), -8 * vdiag(1), 0));
            startel[1] = mesh.AddPoint(bbox.PMin() + Vec <3> (+8 * vdiag(0), -8 * vdiag(1), 0));
            startel[2] = mesh.AddPoint(bbox.PMin() + Vec <3> (0, 8 * vdiag(1), 0));

            Box <3> hbox;

            hbox.Set(mesh[startel[0]]);
            hbox.Add(mesh[startel[1]]);
            hbox.Add(mesh[startel[2]]);
            Point <3> hp = mesh[startel[0]];

            hp(2) = 1;
            hbox.Add(hp);
            hp(2) = -1;
            hbox.Add(hp);
            BoxTree <3> searchtree(hbox);

            Array <DelaunayTrig> tempels = new Array <DelaunayTrig>();

            startel.CalcCenter(mesh);

            tempels.Append(startel);
            searchtree.Insert(startel.BoundingBox(), 0);

            Array <int>     closeels     = new Array <int>();
            Array <int>     intersecting = new Array <int>();
            Array <INDEX_2> edges        = new Array <INDEX_2>();



            // reorder points
            Array <PointIndex, PointIndex.BASE, PointIndex> mixed = new Array <PointIndex, PointIndex.BASE, PointIndex>(old_points.Size());

            int[] prims = { 11, 13, 17, 19, 23, 29, 31, 37 };
            int   prim;

            {
                int i = 0;
                while (old_points.Size() % prims[i] == 0)
                {
                    i++;
                }
                prim = prims[i];
            }

            foreach (PointIndex pi in old_points)
            {
                mixed[pi] = new PointIndex((prim * pi) % old_points.Size() + PointIndex.BASE);
            }

            NgProfiler.StopTimer(Delaunay_timerstart);
            NgProfiler.StartTimer(Delaunay_timer1);


            foreach (PointIndex i1 in old_points)
            {
                PointIndex i = mixed[i1];

                NgProfiler.StartTimer(Delaunay_timer1a);
                Point <3> newp = mesh[i];
                intersecting.SetSize(0);
                edges.SetSize(0);

                searchtree.GetIntersecting(newp, newp, closeels);
                // for (int jj = 0; jj < closeels.Size(); jj++)
                // for (int j = 0; j < tempels.Size(); j++)
                foreach (int j in closeels)
                {
                    if (tempels[j][0] < 0)
                    {
                        continue;
                    }
                    Point <3> c  = tempels[j].Center();
                    double    r2 = tempels[j].Radius2();

                    bool inside = Dist2(mesh[i], c) < r2;
                    if (inside)
                    {
                        intersecting.Append(j);
                    }
                }

                NgProfiler.StopTimer(Delaunay_timer1a);
                NgProfiler.StartTimer(Delaunay_timer1b);

                // find outer edges
                foreach (var j in intersecting)
                {
                    DelaunayTrig trig = tempels[j];
                    for (int k = 0; k < 3; k++)
                    {
                        int     p1   = trig[k];
                        int     p2   = trig[(k + 1) % 3];
                        INDEX_2 edge = new INDEX_2(p1, p2);
                        edge.Sort();
                        bool found = false;
                        for (int l = 0; l < edges.Size(); l++)
                        {
                            if (edges[l] == edge)
                            {
                                edges.Delete(l);
                                found = true;
                                break;
                            }
                        }
                        if (!found)
                        {
                            edges.Append(edge);
                        }
                    }
                }

                NgProfiler.StopTimer(Delaunay_timer1b);
                NgProfiler.StartTimer(Delaunay_timer1c);

                /*
                 * for (int j = intersecting.Size()-1; j >= 0; j--)
                 * tempels.Delete (intersecting[j]);
                 */
                foreach (int j in intersecting)
                {
                    searchtree.DeleteElement(j);
                    tempels[j][0] = -1;
                    tempels[j][1] = -1;
                    tempels[j][2] = -1;
                }

                NgProfiler.StopTimer(Delaunay_timer1c);
                NgProfiler.StartTimer(Delaunay_timer1d);

                foreach (var edge in edges)
                {
                    DelaunayTrig trig = new DelaunayTrig(edge[0], edge[1], i);
                    trig.CalcCenter(mesh);
                    tempels.Append(trig);
                    searchtree.Insert(trig.BoundingBox(), tempels.Size() - 1);
                }

                NgProfiler.StopTimer(Delaunay_timer1d);
            }

            NgProfiler.StopTimer(Delaunay_timer1);
            NgProfiler.StartTimer(Delaunay_timerfinish);

            foreach (DelaunayTrig trig in tempels)
            {
                if (trig[0] < 0)
                {
                    continue;
                }

                Point <3> c = Center(mesh[trig[0]], mesh[trig[1]], mesh[trig[2]]);
                if (!adfront.Inside(Point <2> (c(0), c(1))))
                {
                    continue;
                }

                Vec <3> n = Cross(mesh[trig[1]] - mesh[trig[0]], mesh[trig[2]] - mesh[trig[0]]);
                if (n(2) < 0)
                {
                    Swap(ref trig[1], ref trig[2]);
                }

                Element2d el = new Element2d(trig[0], trig[1], trig[2]);
                el.SetIndex(domainnr);
                mesh.AddSurfaceElement(el);
            }

            foreach (PointIndex pi in mesh.Points().Range())
            {
                *testout << pi << ": " << mesh[pi].Type() << "\n";
            }

            NgProfiler.StopTimer(Delaunay_timerfinish);
        }