Beispiel #1
0
        /// <summary>
        /// Compute the probability that a given set of substrokes has the given type.
        /// </summary>
        /// <param name="substrokes"></param>
        /// <param name="type"></param>
        /// <param name="featureSketch"></param>
        /// <returns>a pair containing the recognition probability and the orientation</returns>
        private RecognitionResult computeRecognitionProbabilityForTextOrWire(SubstrokeCollection substrokes, ShapeType type, FeatureSketch featureSketch)
        {
            double probability = 0;
            double orientation = 0;

            PhantomShape shape = new PhantomShape();

            shape.AddSubstrokes(substrokes);

            if (LogicDomain.IsWire(type))
            {
                // the probability it is a wire is defined as
                // (# substrokes classified as wires) / (total # substrokes)

                int numSubstrokes     = substrokes.Count;
                int numWireSubstrokes = 0;

                foreach (Substroke substroke in substrokes)
                {
                    if (_classifications[substroke] == LogicDomain.WIRE_CLASS)
                    {
                        numWireSubstrokes++;
                    }
                }

                probability = (double)numWireSubstrokes / numSubstrokes;
                return(new RecognitionResult(LogicDomain.WIRE, probability, orientation));
            }
            else if (LogicDomain.IsText(type))
            {
                // the probability it is text is defined as
                // (# substrokes classified as text) / (total # substrokes)

                int numSubstrokes     = substrokes.Count;
                int numTextSubstrokes = 0;

                foreach (Substroke substroke in substrokes)
                {
                    if (_classifications[substroke] == LogicDomain.TEXT_CLASS)
                    {
                        numTextSubstrokes++;
                    }
                }

                probability = (double)numTextSubstrokes / numSubstrokes;
                return(new TextRecognitionResult(probability, _textRecognizer.read(shape)));
            }

            return(null);
        }
        /// <summary>
        /// Creates new EndpointPainters whenever
        /// a circuit is created
        /// </summary>
        public void UpdateEndpoints()
        {
            if (!subscribed)
            {
                return;
            }
            // Reinit

            // Highlight endpoints
            foreach (Shape shape in sketchPanel.InkSketch.Sketch.Shapes)
            {
                if (LogicDomain.IsWire(shape.Type))
                {
                    highlightEndpoints(shape);
                }
            }
        }
        /// <summary>
        /// Highlights the endpoints of a single Wire by
        /// creating EndPointPainters for all endpoints.
        ///
        /// Main function for endpoint highlighting.
        ///
        /// Wire must have "AlreadyLabeled" set to true.
        /// </summary>
        /// <param name="wire">The Wire to highlight</param>
        /// <param name="g">The graphics handle to use while creating painters</param>
        private void highlightEndpoints(Shape wire)
        {
            // If this hasn't been recognized or isn't a wire, don not highlight.
            if (!wire.AlreadyLabeled || !LogicDomain.IsWire(wire.Type))
            {
                return;
            }

            List <int>      newEppIds = new List <int>();
            EndPointPainter epp;
            int             eppId;

            foreach (Sketch.EndPoint endpoint in wire.Endpoints)
            {
                epp    = createEndpointPainter(endpoint);
                eppId  = endPointPainterMap.Keys.Count + 1;
                epp.Id = eppId;
                newEppIds.Add(eppId);
                endPointPainterMap.Add(eppId, epp);
            }

            // Update stroke map to point to endpoint painters
            foreach (Sketch.Substroke substroke in wire.Substrokes)
            {
                String iStrokeId = sketchPanel.InkSketch.GetInkStrokeIdBySubstrokeId(substroke.XmlAttrs.Id);
                System.Windows.Ink.Stroke iStroke = sketchPanel.InkSketch.GetInkStrokeById(iStrokeId);

                if (iStrokeId2EndPtPainterId.ContainsKey(iStroke))
                {
                    throw new ApplicationException("Error: encountered one stroke " +
                                                   "that is part of two or more unique meshes");
                }

                if (iStrokeId != null)
                {
                    iStrokeId2EndPtPainterId[iStroke] = newEppIds;
                }
            }

            PaintAllEndpoints();
        }
Beispiel #4
0
        /// <summary>
        /// Connects not bubbles to gates and wires
        /// </summary>
        /// <param name="gate"></param>
        private void connectNotBubble(LogicGate bubble)
        {
            LogicGate parentGate = null;
            WireMesh  wire       = null;

            // Get the components this not bubble is connected to
            foreach (Shape connected in bubble.Shape.ConnectedShapes)
            {
                if (LogicDomain.IsGate(connected.Type) && parentGate == null)
                {
                    parentGate = _logicGates[connected];
                }
                else if (LogicDomain.IsWire(connected.Type))
                {
                    wire = _wireMeshes[connected];
                }
            }

            // If this is not connected to a gate, connect it like a normal logic gate
            if (parentGate == null)
            {
                connectWiresTo(bubble);
                return;
            }

            // Is this bubble on the output or the input?
            Sketch.EndPoint connectingEndpoint =
                parentGate.Shape.ClosestEndpointFrom(bubble.Shape);
            bool isInput = parentGate.ShouldBeInput(connectingEndpoint);

            if (isInput)
            {
                wire.ConnectDependent(bubble);
                parentGate.ConnectInput(bubble, 0);
            }
            else
            {
                wire.ConnectSource(bubble, 0);
                parentGate.ConnectOutput(bubble, 0);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Checks whether the sketch is valid, and returns a bool indicating this.
        /// Adds any errors it comes across to the _parseErrors list.
        ///
        /// Looks for:
        ///    * Basic consistency via sketch.CheckConsistency
        ///    * Gates connected to only wires
        ///    * Wires not connected to wires
        ///    * Text connected to at most one wire
        /// </summary>
        /// <param name="sketch">The sketch to check the validity of</param>
        /// <returns>A bool, which is true if the sketch is valid</returns>
        private bool CheckSketch(Sketch.Sketch sketch)
        {
            bool valid = true;

            // Check basic sketch consistency, will (rightly) throw an exception if it finds something wrong.
            // Eventually we should not need this, for the sketch should always pass this, but it's a useful check for now.
            sketch.CheckConsistency();

            foreach (Sketch.Shape shape in sketch.Shapes)
            {
                #region Gate Checks
                if (LogicDomain.IsGate(shape.Type))
                {
                    // Each gate should be connected to only wires
                    foreach (Sketch.Shape connected in shape.ConnectedShapes)
                    {
                        if (!LogicDomain.IsWire(connected.Type))
                        {
                            valid = false;
                            _parseErrors.Add(new ParseError("Gate " + shape.Name + " is connected to something that is not a wire, " + connected.Name + "of type " + connected.Type.Name,
                                                            "This gate is connected to something that is not a wire.  Draw wires between them or group them together.", shape));
                        }
                    }
                }
                #endregion

                #region Wire Checks
                else if (LogicDomain.IsWire(shape.Type))
                {
                    // Wires shouldn't be connected to other wires
                    foreach (Sketch.Shape connected in shape.ConnectedShapes)
                    {
                        if (shape != connected && LogicDomain.IsWire(connected.Type))
                        {
                            valid = false;
                            _parseErrors.Add(new ParseError("Wire " + shape.Name + " is connected to another wire, " + connected.Name,
                                                            "This wire is connected to another wire.  Try grouping these wires together.", shape));
                        }
                    }
                }
                #endregion

                #region Input/Output Checks
                else if (LogicDomain.IsText(shape.Type))
                {
                    // Text should only be connected to wires, if anything.
                    foreach (Sketch.Shape wire in shape.ConnectedShapes)
                    {
                        if (!LogicDomain.IsWire(wire.Type))
                        {
                            valid = false;
                            _parseErrors.Add(new ParseError("Text " + shape.Name + " should only be connected to a wire, but is connected to a " + wire.Type.Name + ".",
                                                            shape.Name + " should only be connected to a wire, but is connected to a " + wire.Type.Name + ".", shape));
                        }
                    }
                }
                #endregion
            }

            return(valid);
        }
Beispiel #6
0
        /// <summary>
        /// Determines whether or not a given shape is a circuit
        /// input, and creates and connects it accordingly.
        /// Will ignore any text that is not connected to anything.
        ///
        /// Assumptions:
        ///   * The names of wire-meshes correspond directly to
        ///     their associated shapes.
        ///   * Wire-meshes all have unique names.
        ///   * The given shape is not a label connected to two wires.
        /// </summary>
        /// <param name="shape">The shape to analyze</param>
        /// <returns>True if loading was successful, false
        /// if the given shape cannot be recognized as an input
        /// or output</returns>
        private void loadInputOrOutput(Sketch.Shape shape)
        {
            // Make sure we're actually dealing with something sensical.
            // Note: If there are no connected shapes, we don't make an input or output, it is just ignored in the circuit.
            if (shape.Type != LogicDomain.TEXT || shape.ConnectedShapes.Count == 0)
            {
                return;
            }

            // Retreive the wire connected to this label shape, while
            // also checking that the shape has the correct number and
            // kinds of connections.
            List <WireMesh> connectedWires = new List <WireMesh>();

            // Assume that we have an input until we are told otherwise.
            bool input = true;

            foreach (Sketch.Shape connectedShape in shape.ConnectedShapes)
            {
                // Is this a wire?
                if (!LogicDomain.IsWire(connectedShape.Type))
                {
                    continue;
                }

                // Get the connected wire
                WireMesh connected = _wireMeshes[connectedShape.Name];

                // Have we already seen this?
                if (connectedWires.Contains(connected))
                {
                    continue;
                }
                connectedWires.Add(connected);

                // If we're dealing with any wire that already has a source, this will not be an input
                if (connected.HasSource)
                {
                    input = false;
                }
            }

            if (input)
            {
                CircuitInput newInput = new CircuitInput(shape);
                foreach (WireMesh wire in connectedWires)
                {
                    newInput.Connect(wire);
                }
                _circuitInputs.Add(newInput.Name, newInput);
            }
            else
            {
                CircuitOutput newOutput = new CircuitOutput(shape);
                foreach (WireMesh wire in connectedWires)
                {
                    newOutput.Connect(wire);
                }
                _circuitOutputs.Add(newOutput.Name, newOutput);
            }
        }
Beispiel #7
0
        /// <summary>
        /// Recalculate the connectedShapes of every shape in a given list,
        /// and correctly update all related shapes.
        /// </summary>
        /// <param name="shapeList">the list of shapes to reconnect</param>
        /// <param name="featureSketch">the sketch the shapes belong to</param>
        public void recomputeConnectedShapes(IEnumerable <Sketch.Shape> shapeList, Sketch.Sketch sketch)
        {
            // Keep a unique list of shapes
            HashSet <Sketch.Shape> allRelevantShapes = new HashSet <Sketch.Shape>(shapeList);

            // Add connected shapes to the list that needs to change
            foreach (Sketch.Shape shape in shapeList)
            {
                foreach (Sketch.Shape connected in shape.ConnectedShapes)
                {
                    allRelevantShapes.Add(connected);
                }
            }

            // clear ALL connections first
            foreach (Sketch.Shape shape in allRelevantShapes)
            {
                shape.ClearConnections();
            }

            sketch.CheckConsistency();

            // connect every shape
            foreach (Sketch.Shape shape in allRelevantShapes)
            {
                connect(shape, sketch);
            }


            // Make sure connected wires are the same shape
            Tuple <Sketch.Shape, Sketch.Shape> pair = null;

            while ((pair = wiresToMerge(allRelevantShapes)) != null)
            {
                sketch.mergeShapes(pair.Item1, pair.Item2);
                allRelevantShapes.Remove(pair.Item2);
                sketch.connectShapes(pair.Item1, pair.Item1);;
            }

            sketch.CheckConsistency();

#if DEBUG
            foreach (Shape wire in sketch.Shapes)
            {
                if (!LogicDomain.IsWire(wire.Type))
                {
                    continue;
                }
                foreach (Shape shape in wire.ConnectedShapes)
                {
                    if (LogicDomain.IsWire(shape.Type) && shape != wire)
                    {
                        throw new Exception("Found two connected wires (" + wire + " and " + shape + ") that were not merged!");
                    }
                    bool found = false;
                    foreach (EndPoint endpoint in wire.Endpoints)
                    {
                        if (endpoint.ConnectedShape == shape)
                        {
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        throw new Exception("The wire " + wire + " is connected to " + shape + " as a connected shape, but not by an endpoint!");
                    }
                }
            }
#endif
        }
Beispiel #8
0
        /// <summary>
        /// Connects the given shape to the other shapes in the sketch.
        ///
        /// Postcondition:
        ///     If the shape is a wire, the following things are true:
        ///       - For every substroke in the wire, both endpoints are connected to the closest shape
        ///       - The shapes the endpoints are connected to are also in the list of connected shapes
        ///       - The shapes that the wire is  connected to also know they are connected to the wire
        ///     If the shape is a NOTBUBBLE
        ///       - It is connected to the two closest shapes??
        /// </summary>
        /// <param name="shape">The shape to check.</param>
        /// <param name="sketch">The sketch containing the shape.</param>
        public override void ConnectShape(Sketch.Shape shape, Sketch.Sketch sketch)
        {
            if (!sketch.ShapesL.Contains(shape))
            {
                throw new ArgumentException("The given shape " + shape + " is not in the given sketch!");
            }

            // Connect wires to adjacent shapes
            if (shape.Type == LogicDomain.WIRE)
            {
                foreach (Sketch.Substroke substroke in shape.Substrokes)
                {
                    // Find the shape closest to the start point of the wire
                    Shape shape2 = findClosest(true, substroke, sketch);
                    if (shape2 != null)
                    {
                        EndPoint start = substroke.Endpoints[0];
                        if (!start.IsConnected)
                        {
                            sketch.connectShapes(shape, shape2);
                            start.ConnectedShape = shape2;
                        }
                    }

                    // Find the shape closest to the end point of the wire
                    Shape shape3 = findClosest(false, substroke, sketch);
                    if (shape3 != null)
                    {
                        EndPoint end = substroke.Endpoints[1];
                        if (!end.IsConnected)
                        {
                            sketch.connectShapes(shape, shape3);
                            end.ConnectedShape = shape3;
                        }
                    }
                }
            }

            // Connect NotBubbles to its two closest shapes.
            // FIXME: This could potentially cause problems. For instance,
            // on the off chance that one of the closest shapes was a wire
            // whose connections were already figured out, this could leave
            // the wire in an inconsistent state.
            else if (shape.Type == LogicDomain.NOTBUBBLE)
            {
                List <Sketch.Shape> shapes = twoClosest(shape, sketch);

                foreach (Shape closeShape in shapes)
                {
                    if (closeShape == null)
                    {
                        continue;
                    }

                    // FIXME: For now, we're only connecting this notbubble to a wire if that wire's closest endpoint is free.
                    if (closeShape.Type == LogicDomain.WIRE)
                    {
                        EndPoint endpoint = shape.ClosestEndpointFrom(closeShape);
                        if (!endpoint.IsConnected)
                        {
                            closeShape.ConnectNearestEndpointTo(shape);
                        }
                    }
                    else
                    {
                        sketch.connectShapes(closeShape, shape);
                    }
                }
            }

#if DEBUG
            foreach (Shape wire in sketch.Shapes)
            {
                if (!LogicDomain.IsWire(wire.Type))
                {
                    continue;
                }
                foreach (Shape connected in wire.ConnectedShapes)
                {
                    bool found = false;

                    // If a wire is connected to something, then either the wire is
                    // connected by an endpoint to the other shape...
                    foreach (EndPoint endpoint in wire.Endpoints)
                    {
                        if (endpoint.ConnectedShape == connected)
                        {
                            found = true;
                            break;
                        }
                    }

                    // ...or the other shape is connected by an endpoint to the wire
                    foreach (EndPoint endpoint in connected.Endpoints)
                    {
                        if (endpoint.ConnectedShape == wire)
                        {
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        throw new Exception("The wire " + wire + " is connected to " + connected +
                                            " as a connected shape, but neither has an endpoint connection to the other!");
                    }
                }
            }
#endif
        }