예제 #1
0
        public static double GetMinimalDistance(V3d p, V3d position, V3d direction, double majorRadius, double minorRadius)
        {
            var plane            = new Plane3d(direction, position);
            var planePoint       = p.GetClosestPointOn(plane);
            var distanceOnPlane  = (V3d.Distance(planePoint, position) - majorRadius).Abs();
            var distanceToCircle = (V3d.DistanceSquared(planePoint, p) + distanceOnPlane.Square()).Sqrt();

            return((distanceToCircle - minorRadius).Abs());
        }
예제 #2
0
        /// <summary>
        /// Creates clusters for all points which are within an epsilon
        /// distance from each other. This algorithm uses a hash-grid and
        /// only works fast if the supplied epsilon is small enough that
        /// not too many points fall within each cluster. Thus it is ideal
        /// for merging vertices in meshes and point sets, that are different
        /// due to numerical inaccuracies.
        /// </summary>
        public PointEpsilonClustering(V3d[] pa, double epsilon, IRandomUniform rnd = null)
        {
            rnd = rnd ?? new RandomSystem();
            var count = pa.Length;

            Alloc(count);
            var ca = m_indexArray;
            var dict = new IntDict <int>(count, stackDuplicateKeys: true);
            int rndBits = 0; int bit = 0;
            var ha   = new int[8];
            var eps2 = epsilon * epsilon;

            for (int i = 0; i < count; i++)
            {
                var p  = pa[i]; p.HashCodes8(epsilon, ha);
                int ci = ca[i]; if (ca[ci] != ci)
                {
                    do
                    {
                        ci = ca[ci];
                    } while (ca[ci] != ci); ca[i] = ci;
                }
                for (int hi = 0; hi < 8; hi++)
                {
                    foreach (var j in dict.ValuesWithKey(ha[hi]))
                    {
                        int cj = ca[j]; if (ca[cj] != cj)
                        {
                            do
                            {
                                cj = ca[cj];
                            } while (ca[cj] != cj); ca[j] = cj;
                        }
                        if (ci == cj || V3d.DistanceSquared(p, pa[j]) >= eps2)
                        {
                            continue;
                        }
                        bit >>= 1; if (bit == 0)
                        {
                            rndBits = rnd.UniformInt(); bit = 1 << 30;
                        }
                        if ((rndBits & bit) != 0)
                        {
                            ca[ci] = cj; ca[i] = cj; ci = cj;
                        }
                        else
                        {
                            ca[cj] = ci; ca[j] = ci;
                        }
                    }
                }
                dict[ha[0]] = i;
            }
            Init();
        }
예제 #3
0
        public bool ClosestPoint(int[] objectIndexArray, int firstIndex, int indexCount, V3d queryPoint, Func <IIntersectableObjectSet, int, bool> ios_index_objectFilter, Func <IIntersectableObjectSet, int, int, ObjectClosestPoint, bool> ios_index_part_ocp_pointFilter, ref ObjectClosestPoint closestPoint)
        {
            var minDist2 = closestPoint.DistanceSquared;
            var minIndex = -1;
            var minPos   = V3d.NaN;

            for (int i = 0; i < indexCount; i++)
            {
                var id = objectIndexArray[firstIndex + i];

                if (ios_index_objectFilter(this, id))
                {
                    GetTriangle(id, out V3d p0, out V3d p1, out V3d p2);
                    var p = queryPoint.GetClosestPointOnTriangle(p0, p1, p2);
                    var d = V3d.DistanceSquared(p, queryPoint);

                    if (d < minDist2)
                    {
                        d        = minDist2;
                        minIndex = id;
                        minPos   = p;
                    }
                }
            }

            if (minIndex >= 0)
            {
                closestPoint = new ObjectClosestPoint()
                {
                    Distance        = Fun.Sqrt(minDist2),
                    DistanceSquared = minDist2,
                    Point           = minPos,
                    SetObject       = new SetObject(this, minIndex),
                    ObjectStack     = new List <SetObject>(), // TODO
                    Coord           = V2d.Zero                // TODO
                };

                return(true);
            }
            else
            {
                return(false);
            }
        }
예제 #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="objectIndexArray"></param>
        /// <param name="firstIndex"></param>
        /// <param name="indexCount"></param>
        /// <param name="query"></param>
        /// <param name="ios_index_objectFilter">not implemented</param>
        /// <param name="ios_index_part_ocp_pointFilter">not implemented</param>
        /// <param name="closest"></param>
        /// <returns></returns>
        public bool ClosestPoint(
            int[] objectIndexArray, int firstIndex, int indexCount,
            V3d query,
            Func <IIntersectableObjectSet, int, bool> ios_index_objectFilter,
            Func <IIntersectableObjectSet, int, int, ObjectClosestPoint, bool> ios_index_part_ocp_pointFilter,
            ref ObjectClosestPoint closest)
        {
            bool result = false;

            for (int i = firstIndex, e = firstIndex + indexCount; i < e; i++)
            {
                int    index = objectIndexArray[i];
                V3d    p     = query.GetClosestPointOn(Sphere3ds[index]);
                double d2    = V3d.DistanceSquared(query, p);
                if (d2 < closest.DistanceSquared)
                {
                    result = closest.Set(d2, p, this, index);
                }
            }
            return(result);
        }
예제 #5
0
        public bool ClosestPoint(
            int[] objectIndexArray, int firstIndex, int indexCount, V3d queryPoint,
            Func <IIntersectableObjectSet, int, bool> ios_index_objectFilter,
            Func <IIntersectableObjectSet, int, int, ObjectClosestPoint, bool> ios_index_part_ocp_pointFilter,
            ref ObjectClosestPoint closestPoint)
        {
            bool result = false;
            var  pa     = m_positionArray;

            for (int i = firstIndex, e = firstIndex + indexCount; i < e; i++)
            {
                int    li = objectIndexArray[i];
                V3d    p  = queryPoint.GetClosestPointOnLine(pa[li], pa[li + 1]);
                double d2 = V3d.DistanceSquared(queryPoint, p);
                if (d2 < closestPoint.DistanceSquared)
                {
                    result = closestPoint.Set(d2, p, this, li);
                }
            }
            return(result);
        }
예제 #6
0
        public bool ClosestPoint(
            int[] objectIndexArray, int firstIndex, int indexCount,
            V3d query,
            Func <IIntersectableObjectSet, int, bool> ios_index_objectFilter,
            Func <IIntersectableObjectSet, int, int, ObjectClosestPoint, bool> ios_index_part_ocp_pointFilter,
            ref ObjectClosestPoint closest)
        {
            var  plist  = Position3dList;
            bool result = false;

            for (int i = firstIndex, e = firstIndex + indexCount; i < e; i++)
            {
                int index = objectIndexArray[i];
                int pi    = index * 3;
                V3d p     = query.GetClosestPointOnTriangle(
                    plist[pi], plist[pi + 1], plist[pi + 2]);
                double d2 = V3d.DistanceSquared(query, p);
                if (d2 < closest.DistanceSquared)
                {
                    result = closest.Set(d2, p, this, index);
                }
            }
            return(result);
        }
예제 #7
0
        public bool ClosestPoint(
            int[] objectIndexArray, int firstIndex, int indexCount,
            V3d queryPoint,
            Func <IIntersectableObjectSet, int, bool> ios_index_objectFilter,
            Func <IIntersectableObjectSet, int, int, ObjectClosestPoint, bool> ios_index_part_ocp_pointFilter,
            ref ObjectClosestPoint closestPoint)
        {
            bool result = false;

            int[] fia = FirstIndexArray, via = VertexIndexArray;
            var   pa  = PositionArray;

            for (int i = firstIndex, e = firstIndex + indexCount; i < e; i++)
            {
                int oi = objectIndexArray[i];
                if (ios_index_objectFilter != null &&
                    !ios_index_objectFilter(this, oi))
                {
                    continue;
                }
                int fvi = fia[oi], fve = fia[oi + 1];
                V3d p0 = pa[via[fvi++]], p1 = pa[via[fvi++]];
                while (fvi < fve)
                {
                    var    p2 = pa[via[fvi++]];
                    V3d    p  = queryPoint.GetClosestPointOnTriangle(p0, p1, p2);
                    double d2 = V3d.DistanceSquared(queryPoint, p);
                    if (d2 < closestPoint.DistanceSquared)
                    {
                        result = closestPoint.Set(d2, p, this, oi);
                    }
                    p1 = p2;
                }
            }
            return(result);
        }
 public bool Contains(V3d pt)
 {
     return(V3d.DistanceSquared(m_sphere.Center, pt) <= m_radiusSquared);
 }
예제 #9
0
        /// <summary>
        /// Creates clusters of planes within a certain epsilon from each other
        /// (euclidean distance between normal vectors and between offsets).
        /// This algorithm uses a 4d hash-grid and only works fast if the supplied
        /// epsilons are small enough that not too many planes fall within each cluster.
        /// Thus it is ideal for merging planes with small variations in orientation and
        /// offset due to numerical inaccuracies.
        /// </summary>
        public PlaneEpsilonClustering(
            int count, TArray pa,
            Func <TArray, int, V3d> getNormal,
            Func <TArray, int, double> getDist,
            double epsNormal, double epsDist,
            double deltaEpsFactor = 0.25, IRandomUniform rnd = null)
        {
            rnd = rnd ?? new RandomSystem();
            Alloc(count);
            var ca = m_indexArray;
            var dict = new IntDict <int>(count, stackDuplicateKeys: true);
            int rndBits = 0; int bit = 0;
            var ha   = new int[16];
            var ne2  = epsNormal * epsNormal;
            var de2  = epsDist * epsDist;
            var deps = (ne2 + de2) * deltaEpsFactor * deltaEpsFactor;

            for (int i = 0; i < count; i++)
            {
                var ni = getNormal(pa, i); var di = getDist(pa, i);
                ni.HashCodes16(di, epsNormal, epsDist, ha);
                int ci = ca[i]; if (ca[ci] != ci)
                {
                    do
                    {
                        ci = ca[ci];
                    } while (ca[ci] != ci); ca[i] = ci;
                }
                double dmin = double.MaxValue;
                for (int hi = 0; hi < 16; hi++)
                {
                    foreach (var j in dict.ValuesWithKey(ha[hi]))
                    {
                        int cj = ca[j]; if (ca[cj] != cj)
                        {
                            do
                            {
                                cj = ca[cj];
                            } while (ca[cj] != cj); ca[j] = cj;
                        }
                        if (ci == cj)
                        {
                            continue;
                        }
                        var dd = Fun.Square(di - getDist(pa, j)); if (dd >= de2)
                        {
                            continue;
                        }
                        var dn = V3d.DistanceSquared(ni, getNormal(pa, j)); if (dn >= ne2)
                        {
                            continue;
                        }
                        var d = dn + dd; if (d < dmin)
                        {
                            dmin = d;
                        }
                        bit >>= 1; if (bit == 0)
                        {
                            rnd.UniformInt(); bit = 1 << 30;
                        }
                        if ((rndBits & bit) != 0)
                        {
                            ca[ci] = cj; ca[i] = cj; ci = cj;
                        }
                        else
                        {
                            ca[cj] = ci; ca[j] = ci;
                        }
                    }
                }
                if (dmin > deps)
                {
                    dict[ha[0]] = i;              // only sparsely populate hashtable for performance reasons
                }
            }
            Init();
        }