예제 #1
0
        /// <summary>
        /// Gets the set of floating objects within a given prism.
        /// Both objects used and unused in this simulation step are considered.
        /// </summary>
        public FloatingObjectsSet GetObjectsInPrism(Polygon3D basePolygon, Vector3D vector)
        {
            FloatingObjectsSet insideObjects = new FloatingObjectsSet();
            var topPolygon = basePolygon.Select(vertex => vertex + vector);

            foreach (var key in KeysInBox(new Box3D(basePolygon.Union(topPolygon))))
            {
                insideObjects.UnionWith(v_Grid[key].OldSet.GetHashSet().Where(fltObject =>
                                                                              basePolygon.IntersectsWith(fltObject.Position, fltObject.Position - vector)));
                insideObjects.UnionWith(v_Grid[key].NewSet.GetHashSet().Where(fltObject =>
                                                                              basePolygon.IntersectsWith(fltObject.Position, fltObject.Position - vector)));
            }
            return(insideObjects);
        }
예제 #2
0
        /// <summary>
        /// True if (a) both polygons lie in the same plane (vertical distance up to Msystem.Tolerance), and
        /// (b) they overlap (the overlapping horizontal distance exceeds Msystem.Tolerance)
        /// </summary>
        public bool OverlapsWith(Polygon3D another)
        {
            if (!(Normal.IsParallelTo(another.Normal) &&
                  Plane.AbsoluteDistanceTo(another[0]) < MSystem.Tolerance))
            {
                return(false);
            }

            // If one polygon contains inside a vertex of another, then they overlap
            // Border tolerance is allowed for case that they just touch (do not overlap)
            if (another.Any(t => ContainsPoint(t, MSystem.Tolerance)) ||
                this.Any(t => another.ContainsPoint(t, MSystem.Tolerance)))
            {
                return(true);
            }

            // Now check the case when no vertex of one polygon lies inside another
            var intersections = new HashSet <Point3D>();

            foreach (var edge1 in Edges)
            {
                foreach (var edge2 in another.Edges)
                {
                    var intersection = edge1.ClosestPointsBetween(edge2, true);
                    if (intersection.Item1.DistanceTo(intersection.Item2) < MSystem.Tolerance)
                    {
                        intersections.Add(intersection.Item1);
                    }
                }
            }
            if (!intersections.Any())
            {
                return(false);
            }

            // Again exclude the case when they just touch and do not overlap
            var c = Point3D.Centroid(intersections);

            return(ContainsPoint(c, MSystem.Tolerance) || another.ContainsPoint(c, MSystem.Tolerance));
        }
예제 #3
0
        /// <summary>
        /// Calculates possible pushing of "another" polytope by this segment being itself
        /// pushed by "pushingVector" which MAY cause its intersection with "another".
        /// If this segment already intersects "another", "pushingVector" is returned.
        /// </summary>
        /// <param name="another">The vertices of object to be eventually pushed.</param>
        /// <param name="pushingVector">Pushing vector of this object.</param>
        /// <returns>Pushing vector of another object.</returns>
        public Vector3D PushingOf(IPolytope another, Vector3D pushingVector)
        {
            Polygon3D polygon = another as Polygon3D;

            if (polygon == null || pushingVector.Length < MSystem.Tolerance)  // length must be tested, otherwise the Polygon3D ctor may throw an exception
            {
                return(default(Vector3D));
            }

            if (this.Vector.IsParallelTo(pushingVector))
            {
                var intersection0 = polygon.IntersectionWith(this[0], this[0] + pushingVector);
                var intersection1 = polygon.IntersectionWith(this[1], this[1] + pushingVector);

                var vector0 = intersection0.IsNaN() ? pushingVector : intersection0 - this[0];
                var vector1 = intersection1.IsNaN() ? pushingVector : intersection1 - this[1];

                // Get minimal vector from this segment to the intersection point
                var minVector = vector0.Length > vector1.Length ? vector1 : vector0;
                return(pushingVector - minVector);
            }

            var projectionFace = new Polygon3D(new List <Point3D> {
                this[0], this[1], this[1] + pushingVector, this[0] + pushingVector
            },
                                               Name + "-pushing projection");
            double pLength = pushingVector.Length, distance = pLength;

            foreach (var point in polygon.IntersectionsWith(projectionFace))
            {
                distance = Math.Min(distance, point.DistanceTo(
                                        Edges[0].ClosestPointsBetween(new Line3D(point, point - pushingVector), true).Item2));
            }

            return(pushingVector.ScaleBy((pLength - distance) / pLength));
        }
예제 #4
0
        /// <summary>
        /// Gives the reference point close to a given position around which we search for / add / remove floating objects
        /// inside/outside this object. If the object is not 2D, the first argument is returned.
        /// </summary>
        /// <param name="position">Position on tiles (typically of connector or protein)</param>
        /// <param name="side">Side of the tile</param>
        /// <returns>Reference point corresponding to "inside"/"outside" parameter</returns>
        public Point3D SidePoint(Point3D position, Tile.SideType side)
        {
            Polygon3D polygon = Vertices as Polygon3D;

            return(polygon?.SidePoint(position, side) ?? position);
        }