/// <summary>
        /// Creates a shape with a RelativeFloatingPort for the node center, attaches it to the shape and all edges
        /// </summary>
        /// <param name="node"></param>
        /// <returns>Shape obstacle for the node with simple port</returns>
        static Shape CreateShapeWithCenterPort(Node node)
        {
            // Debug.Assert(ApproximateComparer.Close(node.BoundaryCurve.BoundingBox, node.BoundingBox), "node's curve doesn't fit its bounds!");
            var shape = new RelativeShape(() => node.BoundaryCurve);
            var port = new RelativeFloatingPort(() => node.BoundaryCurve, () => node.Center);
            shape.Ports.Insert(port);
            foreach (var e in node.InEdges)
                FixPortAtTarget(shape, port, e);
            foreach (var e in node.OutEdges)
                FixPortAtSource(shape, port, e);
            foreach (var e in node.SelfEdges) {
               FixPortAtSource(shape, port, e);
               FixPortAtTarget(shape, port, e);
            }
#if DEBUG
           // shape.UserData = node.ToString();
#endif
            return shape;
        }
 private void RecordRelativePortAndObstacle(Shape obstacle, RelativeFloatingPort port)
 {
     // For relative obstacle ports, associate the shape and pass this association through
     // the file writer/reader.
     if (!this.UseFreePortsForObstaclePorts)
     {
         obstacle.Ports.Insert(port);
     }
     else
     {
         this.FreeRelativePortToShapeMap[port] = obstacle;
     }
 }
        private void ReadPorts()
        {
            Match m;
            this.VerifyIsNextLine(RectFileStrings.BeginPorts);

            // Get to the first line for consistency with the lookahead for multiPort offsets and/or any
            // PortEntries, which will end up reading the following line.
            this.NextLine();

            for (;;)
            {
                if (!(m = ParseOrDone(RectFileStrings.ParsePort, RectFileStrings.EndPorts)).Success)
                {
                    break;
                }

                bool isMultiPort = IsString(m.Groups["type"].ToString(), RectFileStrings.Multi);
                bool isRelative = IsString(m.Groups["type"].ToString(), RectFileStrings.Relative);
                var x = double.Parse(m.Groups["X"].ToString());
                var y = double.Parse(m.Groups["Y"].ToString());
                var portId = int.Parse(m.Groups["portId"].ToString());
                var shapeId = int.Parse(m.Groups["shapeId"].ToString());
                Validate.IsFalse(idToPortMap.ContainsKey(portId), "PortId already exists");
                var location = new Point(x, y);
                Shape shape = GetShapeFromId(shapeId, isMultiPort || isRelative);
                Port port;
                if (isMultiPort)
                {
                    // 'location' was actually the active offset of the multiPort.  Recreate it and reset the
                    // closest-location and verify the active offset index is the same.  This may fail if there
                    // are two identical offsets in the offset list, in which case fix the test setup.
                    int activeOffsetIndex;
                    var offsets = ReadMultiPortOffsets(out activeOffsetIndex);
                    var multiPort = new MultiLocationFloatingPort(() => shape.BoundaryCurve, () => shape.BoundingBox.Center, offsets);
                    multiPort.SetClosestLocation(multiPort.CenterDelegate() + location);
                    Validate.AreEqual(multiPort.ActiveOffsetIndex, activeOffsetIndex, CurrentLineError("ActiveOffsetIndex is not as expected"));
                    port = multiPort;
                }
                else
                {
                    if (isRelative)
                    {
                        // The location in the ParsePort line is the offset for the relative port.
                        port = new RelativeFloatingPort(() => shape.BoundaryCurve, () => shape.BoundingBox.Center, location);
                    }
                    else
                    {
                        Validate.IsTrue(IsString(m.Groups["type"].ToString(), RectFileStrings.Floating), CurrentLineError("Unknown port type"));
                        port = new FloatingPort((null == shape) ? null : shape.BoundaryCurve, location);
                    }
                    this.NextLine();    // Since we didn't read multiPort offsets
                }
                idToPortMap.Add(portId, port);
                if (null != shape)
                {
                    if (!this.UseFreePortsForObstaclePorts)
                    {
                        shape.Ports.Insert(port);
                    }
                    else
                    {
                        FreeRelativePortToShapeMap[port] = shape;
                    }
                }
                ReadPortEntries(port);
            }
        }
 protected FloatingPort MakeSingleRelativeObstaclePort(Shape obstacle, Point offset)
 {
     var port = new RelativeFloatingPort(() => obstacle.BoundaryCurve, () => obstacle.BoundingBox.Center, offset);
     RecordRelativePortAndObstacle(obstacle, port);
     return port;
 }