Пример #1
0
        /// <returns>
        /// True if this and another tile are both polygons in the same plane and they overlap.
        /// </returns>
        public bool OverlapsWith(TileInSpace another)
        {
            var p1 = this.Vertices as Polygon3D;
            var p2 = another.Vertices as Polygon3D;

            return(p1 != null && p2 != null && p1.OverlapsWith(p2));
        }
Пример #2
0
        /// <summary>
        /// Calculates pushing of another object intersecting with this one.
        /// </summary>
        /// <param name="another">The tile to be pushed.</param>
        /// <param name="direction">Pushing direction.</param>
        /// <returns>Pushing vector of another object.</returns>
        public Vector3D PushingIntersected(TileInSpace another, UnitVector3D direction)
        {
            // Estimate the maximum length of both intersecting objects (lower bound)
            // Create vector of sum of their lengths in the pushing direction
            var box1 = new Box3D(another.Vertices);
            var box2 = new Box3D(this.Vertices);
            var falsePushingVector = ((box1.MaxCorner - box1.MinCorner).Length + (box2.MaxCorner - box2.MinCorner).Length) * direction;

            // Create false object moved by negation of the created vector as if it was to be pushed to its actual position
            // This false object surely does not intersects with the "another"
            IPolytope falseVertices = CreateVertices(RotateAndMoveCollection(null, -falsePushingVector, Vertices), Name + "-false");

            // The method "PushingOf" returns the actual pushing vector of the intersecting object
            return(falseVertices.PushingOf(another.Vertices, falsePushingVector));
        }
Пример #3
0
        /// <summary>
        /// For a cTAM 1D electric ladder, calculates charges of all tiles and re-colors tiles accordingly
        /// </summary>
        /// <param name="tile">Starting tile of the ladder</param>
        /// <param name="mSystem">M system which simulates a cTAM</param>
        private static void CalculateLadder(TileInSpace tile, MSystem mSystem)
        {
            var ladder = new List <TileInSpace>()
            {
                null
            };                                              // Element ladder[0] is unused, to agree with paper formulas

            // The cycle must terminate as the tiles are passed in increasing X-coordinate order
            while (tile != null)
            {
                ladder.Add(tile);
                // Next tile to the east from the current one
                tile = tile.EastConnector?.ConnectedTo?.OnTile;
            }
            var t = ladder.Count - 1;

            if (t <= 0)
            {
                return;
            }

            var coefR = new double[t + 1];

            coefR[t] = 1;
            var coefV = new double[t + 1];

            coefV[0] = 1;

            for (int k = t - 1; k >= 1; k--)
            {
                coefR[k] = 1 - 1 / (coefR[k + 1] + ladder[k + 1].AlphaRatio + 1);
            }
            for (int k = 1; k <= t; k++)
            {
                tile     = ladder[k];
                coefV[k] = coefV[k - 1] * coefR[k] / (coefR[k] + tile.AlphaRatio);
                tile.EastConnector.Voltage = mSystem.Nu0 * coefV[k];

                // Color change: lower voltage -> darker, but no less than 1/3 of the original light
                var coef      = 0.75 / Math.Max(1 - mSystem.Tau / mSystem.Nu0, 0.01);
                var darkRatio = Math.Max((coefV[k] - 1) * coef + 1, 0);
                var origColor = ((Tile)tile).Color;
                tile.SetNewColor(origColor.A, (int)(origColor.R * darkRatio), (int)(origColor.G * darkRatio), (int)(origColor.B * darkRatio));
            }
        }
Пример #4
0
        /// <summary>
        /// Calculates position and angle of a new tile connecting to this connection and connects it.
        /// The connector given as parameter determines also the connecting object.
        /// </summary>
        /// <param name="connector">Connector on the new tile by which it connects</param>
        /// <returns>New tile in space connected to this connection.</returns>
        public TileInSpace ConnectObject(ConnectorOnTile connector)
        {
            // Place the old and the new object into the same plane or line
            TileInSpace            newTile      = new TileInSpace(connector.OnTile, Point3D.Origin, OnTile.Quaternion);
            int                    index        = connector.OnTile.Connectors.IndexOf(connector);
            ConnectorOnTileInSpace newConnector = newTile.Connectors[index];

            UnitVector3D axis = OnTile.Vertices.Normal;   // rotation axis - TRY REVERSE IN CASE OF MALFUNCTION

            // Edge-to-edge
            if (newConnector.Positions.Count == 2 && Positions.Count == 2)
            {
                // Rotate the new object so that connector directions are opposite
                Vector3D vector1 = Positions[1] - Positions[0];
                Vector3D vector2 = newConnector.Positions[0] - newConnector.Positions[1];
                Angle    angle   = vector2.SignedAngleTo(vector1, axis);
                newTile.Rotate(axis, angle);

                // Rotate the new tile around the connector edge so that
                // the angle between both tiles is the angle associated with the connector
                newTile.Rotate(vector1.Normalize(), Angle.FromDegrees(180) - Angle);    // TRY REVERSE IN CASE OF MALFUNCTION

                // Move the new object so that the connectors match
                newTile.Move(Positions[0] - newConnector.Positions[1]);
            }
            // Point-to-point
            else if (newConnector.Positions.Count == 1 && Positions.Count == 1)
            {
                // Rotate the new object around an axis perpendicular to it by the angle associated with the connector

                var newSegment  = newTile.Vertices as Segment3D;
                var thisSegment = OnTile.Vertices as Segment3D;
                var thisAxis    = thisSegment?.Vector.Normalize() ?? OnTile.Vertices.Normal;

                if (newSegment == null)
                {
                    // Tile connecting to a segment
                    if (thisSegment != null)
                    {
                        axis = newTile.Vertices.Normal.CrossProduct(-Math.Sign(connector.Angle.Radians) * thisSegment.Vector).Normalize();
                    }
                    // ELSE 2D tile connecting to a 2D tile by a single point - should never happen
                }
                else
                {
                    if (OnTile.Vertices is Polygon3D) // Segment connecting to a tile
                    {
                        axis = axis.CrossProduct(-newSegment.Vector).Normalize();
                    }
                    // ELSE segment connecting to a segment - axis set above as a normal to this segment
                }
                newTile.Rotate(axis, Angle);    // TRY REVERSE AXIS OR ROTATION IN CASE OF MALFUNCTION

                // the newly connected object has one degree of freedom - rotate randomly
                newTile.Rotate(thisAxis, Angle.FromRadians(Randomizer.NextDoubleBetween(0, 2 * Math.PI)));
                // Move the new object so that the connectors match
                newTile.Move(Positions[0] - newConnector.Positions[0]);
            }
            else
            {
                throw new ArgumentException("Connecting incompatible connectors:" + this + "\n and" + newConnector);
            }

            ConnectTo(newConnector);
            return(newTile);
        }
Пример #5
0
 /// <summary>
 /// ConnectorOnTileInSpace constructor
 /// </summary>
 /// <param name="tile">Tile on which is this connector placed.</param>
 /// <param name="connector">Base connector from which this connector derives.</param>
 public ConnectorOnTileInSpace(TileInSpace tile, Connector connector)
     : base(tile, connector)
 {
     OnTile      = tile;
     v_Positions = connector.Positions;  // assignment to Positions would cause double  check of positions on tile
 }
Пример #6
0
 /// <summary>
 /// Surface connector constructor
 /// </summary>
 /// <param name="tile">Tile on which is this connector placed.</param>
 public SurfaceConnector(TileInSpace tile)
 {
     v_OnTile = tile;
 }
Пример #7
0
 /// <summary>
 /// Protein constructor.
 /// </summary>
 /// <param name="tile">Tile on which is this protein placed.</param>
 /// <param name="protein">Base protein from which this protein derives.</param>
 public ProteinOnTileInSpace(TileInSpace tile, ProteinOnTile protein) : base(protein.Name, protein.Position)
 {
     m_tile = tile;
 }
Пример #8
0
 /// <returns>
 /// True if this tile intersects or overlaps another tile. Optimized.
 /// </returns>
 public bool CollidesWith(TileInSpace another)
 {
     return(Vertices.IntersectionsWith(another.Vertices).Any());
 }
Пример #9
0
 /// <summary>
 /// Calculates possible pushing of "another" object by this one, being itself
 /// pushed by its "PushingVector" field which MAY cause its intersection with "another".
 /// If this object already intersects "another", its "PushingVector" is returned.
 /// </summary>
 /// <param name="another">The tile to be eventually pushed.</param>
 /// <returns>Pushing vector of another object.</returns>
 public Vector3D PushingNonIntersected(TileInSpace another)
 {
     return(Vertices.PushingOf(another.Vertices, PushingVector));
 }
Пример #10
0
 /// <summary>
 /// Gets the set of floating objects within a reaction distance from the center of a tile.
 /// Only objects unused in this simulation step are considered.
 /// TODO low priority: return floating objects close to the whole shape of the tile except border
 /// </summary>
 public FloatingObjectsSet GetNearObjects(TileInSpace tile, NamedMultiset targetMultiset)
 {
     return(GetNearObjects(tile.Position, targetMultiset));
 }