public void SafeAdd(T value) { bool lockTaken = false; while (lockTaken == false) { spinlock.Enter(ref lockTaken); } List.Add(value); spinlock.Exit(); }
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(); }); }
// 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; } } }); }
/// <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); }
/// <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); } }