Beispiel #1
0
 /// <summary>
 /// Returns true if connectors are of the same size and they are not both point connectors on 2D tiles.
 /// </summary>
 public bool IsSizeComppatibleWith(ConnectorOnTile connector) => 
     Positions.Count == 1 && connector.Positions.Count == 1 &&
     (OnTile.Vertices is Segment3D || connector.OnTile.Vertices is Segment3D)
     ||
     Positions.Count == 2 && connector.Positions.Count == 2 &&
     Math.Abs(Positions[0].DistanceTo(Positions[1]) -
              connector.Positions[0].DistanceTo(connector.Positions[1])) <= MSystem.Tolerance;
Beispiel #2
0
        /// <summary>
        /// Returns a pair of facet connectors at distinct positions on "tile" which match "glue1" and "glue2" in GlueRelation.
        /// If no such pair exist, then both returned connectors are null.
        /// TODO: check whether connectors are on opposite ends of the tile
        /// </summary>
        public Tuple <ConnectorOnTile, ConnectorOnTile> MatchingConectors(Tile tile, Glue glue1, Glue glue2)
        {
            ConnectorOnTile conn2           = null;
            var             facetConnectors = tile.Connectors.Where(conn => conn.Positions.All(point => tile.Vertices.ContainsPoint(point)));

            var conn1 = facetConnectors.FirstOrDefault(
                connector1 => GlueRelation.MatchAsymmetric(glue1, connector1.Glue) &&
                (conn2 = facetConnectors.FirstOrDefault(
                     connector2 => !Geometry.Overlap(connector1.Positions, connector2.Positions) &&
                     GlueRelation.MatchAsymmetric(glue2, connector2.Glue)))
                != null);

            return(Tuple.Create(conn1, conn2));
        }
Beispiel #3
0
        /// <summary>   TODO low priority: move to class Connector when MSystem is available as singleton
        /// Checks whether two connector are mutually compatible (dimension, size, glues).
        /// Order of connectors matters due to possibly asymmetric glue relation!
        /// </summary>
        /// <param name="connector1"></param>
        /// <param name="connector2"></param>
        public bool AreCompatible(ConnectorOnTileInSpace connector1, ConnectorOnTile connector2)
        {
            // compatible glues and  connector sizes
            bool result = GlueRelation.ContainsKey(Tuple.Create(connector1.Glue, connector2.Glue)) &&
                          connector1.IsSizeComppatibleWith(connector2);

            if (!result || Nu0 <= 0)
            {
                return(result);
            }

            //if Nu0 > 0, then this is a cTAM: check if connector voltage exceeds the threshold
            if (connector2.OnTile.Connectors.Count == 4)
            {
                // Assume that an inner cTAM tile can connect only to an east or south connector
                // It is attachable only if it connects to two connectors simultaneously and
                // the sum o heir voltage exceeds the threshold Tau
                ConnectorOnTileInSpace otherConnector = null;
                if (connector1 == connector1.OnTile.EastConnector)
                {
                    otherConnector = connector1.OnTile.NorthConnector?.ConnectedTo?.OnTile.EastConnector?.ConnectedTo
                                     ?.OnTile.SouthConnector;
                }
                if (connector1 == connector1.OnTile.SouthConnector)
                {
                    otherConnector = connector1.OnTile.WestConnector?.ConnectedTo?.OnTile.SouthConnector?.ConnectedTo
                                     ?.OnTile.EastConnector;
                }
                return(otherConnector != null && otherConnector.Voltage + connector1.Voltage >= Tau);
            }
            else
            {
                // Border cTAM
                return(connector1.Voltage >= Tau);
            }
        }
        /// <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);
        }