Пример #1
0
        virtual protected void ComputeSubMeshes()
        {
            Submeshes = new List <DSubmesh3>();
            KeyToMesh = new Dictionary <object, DSubmesh3>();

            SpinLock data_lock = new SpinLock();

            gParallel.ForEach(TriangleSetKeys, (obj) => {
                DSubmesh3 submesh = new DSubmesh3(Mesh, TriangleSetF(obj), 0);

                bool taken = false;
                data_lock.Enter(ref taken);
                Submeshes.Add(submesh);
                KeyToMesh[obj] = submesh;
                data_lock.Exit();
            });
        }
Пример #2
0
        // TODO: parallel version, cache tri normals
        void Compute_FaceAvg_AreaWeighted()
        {
            int NV = Mesh.MaxVertexID;

            if (NV != Normals.size)
            {
                Normals.resize(NV);
            }

            for (int i = 0; i < NV; ++i)
            {
                Normals[i] = Vector3d.Zero;
            }

            var Normals_lock = new SpinLock();

            gParallel.ForEach(Mesh.TriangleIndices(), (ti) =>
            {
                Index3i tri = Mesh.GetTriangle(ti);
                Vector3d va = Mesh.GetVertex(tri.a);
                Vector3d vb = Mesh.GetVertex(tri.b);
                Vector3d vc = Mesh.GetVertex(tri.c);
                Vector3d N  = MathUtil.Normal(ref va, ref vb, ref vc);
                double a    = MathUtil.Area(ref va, ref vb, ref vc);
                bool taken  = false;
                Normals_lock.Enter(ref taken);
                Normals[tri.a] += a * N;
                Normals[tri.b] += a * N;
                Normals[tri.c] += a * N;
                Normals_lock.Exit();
            });

            gParallel.BlockStartEnd(0, NV - 1, (vi_start, vi_end) =>
            {
                for (int vi = vi_start; vi <= vi_end; vi++)
                {
                    if (Normals[vi].LengthSquared > MathUtil.ZeroTolerancef)
                    {
                        Normals[vi] = Normals[vi].Normalized;
                    }
                }
            });
        }
Пример #3
0
        /// <summary>
        /// check if vertex is in hash table, and if not add new one, with locking if computing in-parallel
        /// </summary>
        int find_or_append_vertex(ref Vector3d pos)
        {
            bool lock_taken = false;

            if (bParallel)
            {
                hash_lock.Enter(ref lock_taken);
            }

            int vid;

            if (VertexHash.TryGetValue(pos, out vid) == false)
            {
                vid             = append_vertex(pos);
                VertexHash[pos] = vid;
            }

            if (lock_taken)
            {
                hash_lock.Exit();
            }

            return(vid);
        }
Пример #4
0
        /// <summary>
        /// Find nearest point in grid, within radius, without locking / thread-safety
        /// You must provided distF which returns distance between query_pt and the point argument
        /// You can ignore specific points via ignoreF lambda.
        /// returned key is InvalidValue if not found
        /// </summary>
        public KeyValuePair <T, double> FindNearestInRadius(Vector3d query_pt, double radius, Func <T, double> distF, Func <T, bool> ignoreF = null)
        {
            Vector3i min_idx = Indexer.ToGrid(query_pt - radius * Vector3d.One);
            Vector3i max_idx = Indexer.ToGrid(query_pt + radius * Vector3d.One);

            double min_dist = double.MaxValue;
            T      nearest  = invalidValue;

            if (ignoreF == null)
            {
                ignoreF = (pt) => { return(false); }
            }
            ;

            for (int zi = min_idx.z; zi <= max_idx.z; zi++)
            {
                for (int yi = min_idx.y; yi <= max_idx.y; yi++)
                {
                    for (int xi = min_idx.x; xi <= max_idx.x; xi++)
                    {
                        Vector3i idx = new Vector3i(xi, yi, zi);
                        List <T> values;
                        if (Hash.TryGetValue(idx, out values) == false)
                        {
                            continue;
                        }
                        foreach (T value in values)
                        {
                            if (ignoreF(value))
                            {
                                continue;
                            }
                            double dist = distF(value);
                            if (dist < radius && dist < min_dist)
                            {
                                nearest  = value;
                                min_dist = dist;
                            }
                        }
                    }
                }
            }

            return(new KeyValuePair <T, double>(nearest, min_dist));
        }

        void insert_point(T value, Vector3i idx, bool threadsafe = true)
        {
            bool lockTaken = false;

            while (threadsafe == true && lockTaken == false)
            {
                spinlock.Enter(ref lockTaken);
            }

            List <T> values;

            if (Hash.TryGetValue(idx, out values))
            {
                values.Add(value);
            }
            else
            {
                Hash[idx] = new List <T>()
                {
                    value
                };
            }

            if (lockTaken)
            {
                spinlock.Exit();
            }
        }

        bool remove_point(T value, Vector3i idx, bool threadsafe = true)
        {
            bool lockTaken = false;

            while (threadsafe == true && lockTaken == false)
            {
                spinlock.Enter(ref lockTaken);
            }

            List <T> values;
            bool     result = false;

            if (Hash.TryGetValue(idx, out values))
            {
                result = values.Remove(value);
            }

            if (lockTaken)
            {
                spinlock.Exit();
            }
            return(result);
        }
        /// <summary>
        /// Variant of FindNearestInRadius that works with squared-distances.
        /// Return value is pair (nearest_index,min_dist) or (invalidValue,double.MaxValue)
        /// </summary>
        public KeyValuePair <T, double> FindNearestInSquaredRadius(Vector2d query_pt, double radiusSqr, Func <T, double> distSqrF, Func <T, bool> ignoreF = null)
        {
            double   search_dist = Math.Sqrt(radiusSqr) + MaxExtent;
            Vector2i min_idx     = Indexer.ToGrid(query_pt - search_dist * Vector2d.One);
            Vector2i max_idx     = Indexer.ToGrid(query_pt + search_dist * Vector2d.One);

            double min_dist_sqr = double.MaxValue;
            T      nearest      = invalidValue;

            if (ignoreF == null)
            {
                ignoreF = (pt) => { return(false); }
            }
            ;

            for (int yi = min_idx.y; yi <= max_idx.y; yi++)
            {
                for (int xi = min_idx.x; xi <= max_idx.x; xi++)
                {
                    Vector2i idx = new Vector2i(xi, yi);
                    List <T> values;
                    if (Hash.TryGetValue(idx, out values) == false)
                    {
                        continue;
                    }
                    foreach (T value in values)
                    {
                        if (ignoreF(value))
                        {
                            continue;
                        }
                        double distSqr = distSqrF(value);
                        if (distSqr < radiusSqr && distSqr < min_dist_sqr)
                        {
                            nearest      = value;
                            min_dist_sqr = distSqr;
                        }
                    }
                }
            }

            return(new KeyValuePair <T, double>(nearest, min_dist_sqr));
        }

        void insert_segment(T value, Vector2i idx, bool threadsafe = true)
        {
            bool lockTaken = false;

            while (threadsafe == true && lockTaken == false)
            {
                spinlock.Enter(ref lockTaken);
            }

            List <T> values;

            if (Hash.TryGetValue(idx, out values))
            {
                values.Add(value);
            }
            else
            {
                Hash[idx] = new List <T>()
                {
                    value
                };
            }

            if (lockTaken)
            {
                spinlock.Exit();
            }
        }

        bool remove_segment(T value, Vector2i idx, bool threadsafe = true)
        {
            bool lockTaken = false;

            while (threadsafe == true && lockTaken == false)
            {
                spinlock.Enter(ref lockTaken);
            }

            List <T> values;
            bool     result = false;

            if (Hash.TryGetValue(idx, out values))
            {
                result = values.Remove(value);
            }

            if (lockTaken)
            {
                spinlock.Exit();
            }
            return(result);
        }
    }