Пример #1
0
        /// <summary>
        /// Remove point without locking / thread-safety
        /// </summary>
        public bool RemovePointUnsafe(T value, Vector3d pos)
        {
            Vector3i idx = Indexer.ToGrid(pos);

            return(remove_point(value, idx, false));
        }
Пример #2
0
 public int to_linear(Vector3i ijk)
 {
     return(ijk.x + ni * (ijk.y + nj * ijk.z));
 }
Пример #3
0
        public void Set(Vector3i idx, bool val)
        {
            int i = idx.z * slab_size + idx.y * row_size + idx.x;

            Bits[i] = val;
        }
Пример #4
0
        public Vector3i ToBlockLocal(Vector3i outer_index)
        {
            Vector3i block_idx = ToBlockIndex(outer_index);

            return(outer_index - block_idx * BlockSize);
        }
Пример #5
0
 public float this[Vector3i idx]
 {
     get { return(grid[idx.x, idx.y, idx.z]); }
 }
        protected Vector3i bilerp(ref Vector3i v00, ref Vector3i v10, ref Vector3i v11, ref Vector3i v01, double tx, double ty)
        {
            Vector3d a = Vector3d.Lerp((Vector3d)v00, (Vector3d)v01, ty);
            Vector3d b = Vector3d.Lerp((Vector3d)v10, (Vector3d)v11, ty);
            Vector3d c = Vector3d.Lerp(a, b, tx);

            return(new Vector3i((int)Math.Round(c.x), (int)Math.Round(c.y), (int)Math.Round(c.z)));
        }
Пример #7
0
        public Vector3d FromGrid(Vector3i gridpoint)
        {
            Vector3f pointf = CellSize * (Vector3f)gridpoint;

            return((Vector3d)GridFrame.FromFrameP(pointf));
        }
Пример #8
0
 //! relative translation
 public void Translate(Vector3i vTranslate)
 {
     Min.Add(vTranslate);
     Max.Add(vTranslate);
 }
Пример #9
0
 public AxisAlignedBox3i(int fCubeSize)
 {
     Min = new Vector3i(0, 0, 0);
     Max = new Vector3i(fCubeSize, fCubeSize, fCubeSize);
 }
Пример #10
0
 public AxisAlignedBox3i(int xmin, int ymin, int zmin, int xmax, int ymax, int zmax)
 {
     Min = new Vector3i(xmin, ymin, zmin);
     Max = new Vector3i(xmax, ymax, zmax);
 }
Пример #11
0
 public int Distance(Vector3i v)
 {
     return((int)Math.Sqrt(DistanceSquared(v)));
 }
Пример #12
0
 public bool Contains(Vector3i v)
 {
     return((Min.x <= v.x) && (Min.y <= v.y) && (Min.z <= v.z) &&
            (Max.x >= v.x) && (Max.y >= v.y) && (Max.z >= v.z));
 }
Пример #13
0
 public AxisAlignedBox3i(bool bIgnore)
 {
     Min = new Vector3i(int.MaxValue, int.MaxValue, int.MaxValue);
     Max = new Vector3i(int.MinValue, int.MinValue, int.MinValue);
 }
Пример #14
0
        public bool Get(Vector3i idx)
        {
            int i = idx.z * slab_size + idx.y * row_size + idx.x;

            return(Bits[i]);
        }
        void generate_graph(DenseGrid3f supportGrid, DenseGridTrilinearImplicit distanceField)
        {
            int ni = supportGrid.ni, nj = supportGrid.nj, nk = supportGrid.nk;
            float dx = (float)CellSize;
            Vector3f origin = this.GridOrigin;

            // parameters for initializing cost grid
            float MODEL_SPACE = 0.01f;      // needs small positive so that points on triangles count as inside (eg on ground plane)
            //float MODEL_SPACE = 2.0f*(float)CellSize;
            float CRAZY_DISTANCE = 99999.0f;
            bool UNIFORM_DISTANCE = true;
            float MAX_DIST = 10 * (float)CellSize;

            // parameters for sorting seeds
            Vector3i center_idx = new Vector3i(ni / 2, 0, nk / 2);      // middle
            //Vector3i center_idx = new Vector3i(0, 0, 0);              // corner
            bool reverse_per_layer = true;

            DenseGrid3f costGrid = new DenseGrid3f(supportGrid);
            foreach ( Vector3i ijk in costGrid.Indices() ) {
                Vector3d cell_center = new Vector3f(ijk.x * dx, ijk.y * dx, ijk.z * dx) + origin;
                float f = (float)distanceField.Value(ref cell_center);
                if (f <= MODEL_SPACE)
                    f = CRAZY_DISTANCE;
                else if (UNIFORM_DISTANCE)
                    f = 1.0f;
                else if (f > MAX_DIST)
                    f = MAX_DIST;
                costGrid[ijk] = f;
            }

            // Find seeds on each layer, sort, and add to accumulated bottom-up seeds list.
            // This sorting has an *enormous* effect on the support generation.

            List<Vector3i> seeds = new List<Vector3i>();
            List<Vector3i> layer_seeds = new List<Vector3i>();
            for (int j = 0; j < nj; ++j) {
                layer_seeds.Clear();
                for (int k = 0; k < nk; ++k) {
                    for (int i = 0; i < ni; ++i) {
                        if (supportGrid[i, j, k] == SUPPORT_TIP_BASE)
                            layer_seeds.Add(new Vector3i(i, j, k));
                    }
                }

                layer_seeds.Sort((a, b) => {
                    Vector3i pa = a; pa.y = 0;
                    Vector3i pb = b; pb.y = 0;
                    int sa = (pa-center_idx).LengthSquared, sb = (pb-center_idx).LengthSquared;
                    return sa.CompareTo(sb);
                });

                // reversing sort order is intresting?
                if(reverse_per_layer)
                    layer_seeds.Reverse();

                seeds.AddRange(layer_seeds);
            }
            HashSet<Vector3i> seed_indices = new HashSet<Vector3i>(seeds);

            // gives very different results...
            if (ProcessBottomUp == false)
                seeds.Reverse();

            // for linear index a, is this a node we allow in graph? (ie graph bounds)
            Func<int, bool> node_filter_f = (a) => {
                Vector3i ai = costGrid.to_index(a);
                // why not y check??
                return ai.x > 0 &&  ai.z > 0 && ai.x != ni - 1 && ai.y != nj - 1 && ai.z != nk - 1;
            };

            // distance from linear index a to linear index b
            // this defines the cost field we want to find shortest path through
            Func<int, int, float> node_dist_f = (a, b) => {
                Vector3i ai = costGrid.to_index(a), bi = costGrid.to_index(b);
                if (bi.y >= ai.y)               // b.y should always be a.y-1
                    return float.MaxValue;
                float sg = supportGrid[bi];

                // don't connect to tips
                //if (sg == SUPPORT_TIP_BASE || sg == SUPPORT_TIP_TOP)
                //    return float.MaxValue;
                if (sg == SUPPORT_TIP_TOP)
                    return float.MaxValue;

                if (sg < 0)
                    return -999999;    // if b is already used, we will terminate there, so this is a good choice

                // otherwise cost is sqr-grid-distance + costGrid value  (which is basically distance to surface)
                float c = costGrid[b];
                float f = (float)(Math.Sqrt((bi - ai).LengthSquared) * CellSize);
                //float f = 0;
                return c + f;
            };

            // which linear-index nbrs to consider for linear index a
            Func<int, IEnumerable<int>> neighbour_f = (a) => {
                Vector3i ai = costGrid.to_index(a);
                return down_neighbours(ai, costGrid);
            };

            // when do we terminate
            Func<int, bool> terminate_f = (a) => {
                Vector3i ai = costGrid.to_index(a);
                // terminate if we hit existing support path
                if (seed_indices.Contains(ai) == false && supportGrid[ai] < 0)
                    return true;
                // terminate if we hit ground plane
                if (ai.y == 0)
                    return true;
                return false;
            };

            DijkstraGraphDistance dijkstra = new DijkstraGraphDistance(ni * nj * nk, false,
                node_filter_f, node_dist_f, neighbour_f);
            dijkstra.TrackOrder = true;

            List<int> path = new List<int>();

            Graph = new DGraph3();
            Dictionary<Vector3i, int> CellToGraph = new Dictionary<Vector3i, int>();
            TipVertices = new HashSet<int>();
            TipBaseVertices = new HashSet<int>();
            GroundVertices = new HashSet<int>();

            // seeds are tip-base points
            for (int k = 0; k < seeds.Count; ++k) {
                // add seed point (which is a tip-base vertex) as seed for dijkstra prop
                int seed = costGrid.to_linear(seeds[k]);
                dijkstra.Reset();
                dijkstra.AddSeed(seed, 0);

                // compute to termination (ground, existing node, etc)
                int base_node = dijkstra.ComputeToNode(terminate_f);
                if (base_node < 0)
                    base_node = dijkstra.GetOrder().Last();

                // extract the path
                path.Clear();
                dijkstra.GetPathToSeed(base_node, path);
                int N = path.Count;

                // first point on path is termination point.
                // create vertex for it if we have not yet
                Vector3i basept_idx = supportGrid.to_index(path[0]);
                int basept_vid;
                if ( CellToGraph.TryGetValue(basept_idx, out basept_vid) == false ) {
                    Vector3d curv = get_cell_center(basept_idx);
                    if (basept_idx.y == 0) {
                        curv.y = 0;
                    }
                    basept_vid = Graph.AppendVertex(curv);
                    if (basept_idx.y == 0) {
                        GroundVertices.Add(basept_vid);
                    }
                    CellToGraph[basept_idx] = basept_vid;
                }

                int cur_vid = basept_vid;

                // now walk up path and create vertices as necessary
                for (int i = 0; i < N; ++i) {
                    int idx = path[i];
                    if ( supportGrid[idx] >= 0 )
                        supportGrid[idx] = SUPPORT_GRID_USED;
                    if ( i > 0 ) {
                        Vector3i next_idx = supportGrid.to_index(path[i]);
                        int next_vid;
                        if (CellToGraph.TryGetValue(next_idx, out next_vid) == false) {
                            Vector3d nextv = get_cell_center(next_idx);
                            next_vid = Graph.AppendVertex(nextv);
                            CellToGraph[next_idx] = next_vid;
                        }
                        Graph.AppendEdge(cur_vid, next_vid);
                        cur_vid = next_vid;
                    }
                }

                // seed was tip-base so we should always get back there. Then we
                // explicitly add tip-top and edge to it.
                if ( supportGrid[path[N-1]] == SUPPORT_TIP_BASE ) {
                    Vector3i vec_idx = supportGrid.to_index(path[N-1]);
                    TipBaseVertices.Add(CellToGraph[vec_idx]);

                    Vector3i tip_idx = vec_idx + Vector3i.AxisY;
                    int tip_vid;
                    if (CellToGraph.TryGetValue(tip_idx, out tip_vid) == false) {
                        Vector3d tipv = get_cell_center(tip_idx);
                        tip_vid = Graph.AppendVertex(tipv);
                        CellToGraph[tip_idx] = tip_vid;
                        Graph.AppendEdge(cur_vid, tip_vid);
                        TipVertices.Add(tip_vid);
                    }
                }

            }

            /*
             * Snap tips to surface
             */

            gParallel.ForEach(TipVertices, (tip_vid) => {
                bool snapped = false;
                Vector3d v = Graph.GetVertex(tip_vid);
                Frame3f hitF;
                // try shooting ray straight up. if that hits, and point is close, we use it
                if (MeshQueries.RayHitPointFrame(Mesh, MeshSpatial, new Ray3d(v, Vector3d.AxisY), out hitF)) {
                    if (v.Distance(hitF.Origin) < 2 * CellSize) {
                        v = hitF.Origin;
                        snapped = true;
                    }
                }

                // if that failed, try straight down
                if (!snapped) {
                    if (MeshQueries.RayHitPointFrame(Mesh, MeshSpatial, new Ray3d(v, -Vector3d.AxisY), out hitF)) {
                        if (v.Distance(hitF.Origin) < CellSize) {
                            v = hitF.Origin;
                            snapped = true;
                        }
                    }
                }

                // if it missed, or hit pt was too far, find nearest point and try that
                if (!snapped) {
                    hitF = MeshQueries.NearestPointFrame(Mesh, MeshSpatial, v);
                    if (v.Distance(hitF.Origin) < 2 * CellSize) {
                        v = hitF.Origin;
                        snapped = true;
                    }
                    // can this ever fail? tips should always be within 2 cells...
                }
                if (snapped)
                    Graph.SetVertex(tip_vid, v);
            });
        }
Пример #16
0
 public AxisAlignedBox3i(int fWidth, int fHeight, int fDepth)
 {
     Min = new Vector3i(0, 0, 0);
     Max = new Vector3i(fWidth, fHeight, fDepth);
 }
 Vector3d get_cell_center(Vector3i ijk)
 {
     return new Vector3d(ijk.x * CellSize, ijk.y * CellSize, ijk.z * CellSize) + this.GridOrigin;
 }
Пример #18
0
 public AxisAlignedBox3i(Vector3i vMin, Vector3i vMax)
 {
     Min = new Vector3i(Math.Min(vMin.x, vMax.x), Math.Min(vMin.y, vMax.y), Math.Min(vMin.z, vMax.z));
     Max = new Vector3i(Math.Max(vMin.x, vMax.x), Math.Max(vMin.y, vMax.y), Math.Max(vMin.z, vMax.z));
 }
        protected Vector3i lerp(ref Vector3i a, ref Vector3i b, double t)
        {
            Vector3d c = Vector3d.Lerp((Vector3d)a, (Vector3d)b, t);

            return(new Vector3i((int)Math.Round(c.x), (int)Math.Round(c.y), (int)Math.Round(c.z)));
        }
Пример #20
0
 public AxisAlignedBox3i(Vector3i vCenter, int fHalfWidth, int fHalfHeight, int fHalfDepth)
 {
     Min = new Vector3i(vCenter.x - fHalfWidth, vCenter.y - fHalfHeight, vCenter.z - fHalfDepth);
     Max = new Vector3i(vCenter.x + fHalfWidth, vCenter.y + fHalfHeight, vCenter.z + fHalfDepth);
 }
Пример #21
0
 public MultigridIndexer3(Vector3i blockSize)
 {
     BlockSize  = blockSize;
     OuterShift = BlockShift = Vector3i.Zero;
 }
Пример #22
0
 public AxisAlignedBox3i(Vector3i vCenter, int fHalfSize)
 {
     Min = new Vector3i(vCenter.x - fHalfSize, vCenter.y - fHalfSize, vCenter.z - fHalfSize);
     Max = new Vector3i(vCenter.x + fHalfSize, vCenter.y + fHalfSize, vCenter.z + fHalfSize);
 }
Пример #23
0
        public Vector3i FromBlock(Vector3i block_idx)
        {
            Vector3i outer_idx = (block_idx + BlockShift) * BlockSize;

            return(outer_idx + OuterShift);
        }
Пример #24
0
 public AxisAlignedBox3i(Vector3i vCenter)
 {
     Min = Max = vCenter;
 }
Пример #25
0
 Vector3f cell_center(Vector3i ijk)
 {
     return(new Vector3f((float)ijk.x * CellSize + grid_origin[0],
                         (float)ijk.y * CellSize + grid_origin[1],
                         (float)ijk.z * CellSize + grid_origin[2]));
 }
Пример #26
0
        /// <summary>
        /// Insert point without locking / thread-safety
        /// </summary>
        public void InsertPointUnsafe(T value, Vector3d pos)
        {
            Vector3i idx = Indexer.ToGrid(pos);

            insert_point(value, idx, false);
        }
Пример #27
0
 public float this[Vector3i ijk] {
     get { return(Buffer[ijk.x + ni * (ijk.y + nj * ijk.z)]); }
     set { Buffer[ijk.x + ni * (ijk.y + nj * ijk.z)] = value; }
 }
Пример #28
0
 public int ToLinear(Vector3i idx)
 {
     return(idx.z * slab_size + idx.y * row_size + idx.x);
 }