/// <summary> /// Compares two wires on the basis of the Y value of the endpoint that connects to this gate /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public int WireSort(WireMesh a, WireMesh b) { Sketch.EndPoint aEnd = Shape.ClosestEndpointFrom(a.Shape); Sketch.EndPoint bEnd = Shape.ClosestEndpointFrom(b.Shape); return(EndpointSort(aEnd, bEnd)); }
/// <summary> /// Sorts and connects all inputs /// </summary> /// <returns></returns> public void ConnectAllInputs() { foreach (Sketch.EndPoint endpoint in InputEndpoints) { WireMesh wire = EndpointsToWires[endpoint]; wire.ConnectDependent(this);//, _inputWires.IndexOf(wire)); } OrderInputs(); }
/// <summary> /// Figures out everything a given logic gate should be /// connected to, and connects them appropriately. /// /// Assumption: Every wire-mesh has a unique name. /// /// Note: this currently only deals with connections to wires. /// Hence, it does not make any connections for notbubbles yet. /// </summary> /// <param name="gate">The gate to connect</param> private void connectWiresTo(LogicGate gate) { // We keep track of what wire-meshes are inputs and outputs // so we can do sanity checks before actually connecting // them to the logic gate. List <string> inputWires = new List <string>(); List <string> outputWires = new List <string>(); int maxOutputs = LogicDomain.MaxOutputs(gate.Type); // Cycle through everything connected to the gate's associated // shape and categorize their connection type accordingly foreach (Sketch.Shape connectedShape in gate.Shape.ConnectedShapes) { if (!Domain.LogicDomain.IsWire(connectedShape.Type)) { throw new Exception("Gate " + gate + " was connected to non-wire shape " + connectedShape); } Sketch.EndPoint connectingEndpoint = gate.Shape.ClosestEndpointFrom(connectedShape); if (gate.ShouldBeInput(connectingEndpoint)) { inputWires.Add(connectedShape.Name); } else { outputWires.Add(connectedShape.Name); } } // If it looks like we mixed up the output and input wires, // swap them so they're more correct (this can happen if the // gate's orientation was recognized in the wrong direction) if ((outputWires.Count > maxOutputs) && (inputWires.Count <= maxOutputs)) { swap(ref outputWires, ref inputWires); } // Make the connections. foreach (string wireName in inputWires) { WireMesh inputWire = _wireMeshes[wireName]; gate.ConnectInput(inputWire); } foreach (string wireName in outputWires) { WireMesh outputWire = _wireMeshes[wireName]; gate.ConnectOutput(outputWire); } gate.ConnectAllInputs(); gate.ConnectAllOutputs(); }
/// <summary> /// Connects a wire-mesh as the output to the invoking logic gate. /// </summary> /// <param name="wire">The wire-mesh to connect</param> public void ConnectOutput(WireMesh wire) { // If we're already connected to this wire, we're done! if (_outputWires.Contains(wire)) { return; } _outputWires.Add(wire); return; }
/// <summary> /// Figures out everything a given logic gate should be /// connected to, and connects them appropriately. /// /// Assumption: Every wire-mesh has a unique name. /// /// Note: this currently only deals with connections to wires. /// Hence, it does not make any connections for notbubbles yet. /// </summary> /// <param name="gate">The gate to connect</param> private void connectWiresTo(LogicGate gate) { // We keep track of what wire-meshes are inputs and outputs // so we can do sanity checks before actually connecting // them to the logic gate. List <Shape> inputWires = new List <Shape>(); List <Shape> outputWires = new List <Shape>(); int maxOutputs = _domain.NumberOutputs(gate.Type).Max; // Cycle through everything connected to the gate's associated // shape and categorize their connection type accordingly foreach (Sketch.Shape connectedShape in gate.Shape.ConnectedShapes) { // We'll take care of the not bubbles when they come up seprately if (connectedShape.Type == LogicDomain.NOTBUBBLE) { continue; } // If it's not a wire or a not bubble, something is wrong else if (!Domain.LogicDomain.IsWire(connectedShape.Type)) { throw new Exception("Gate " + gate + " was connected to non-wire, non-notbubble shape " + connectedShape); } Sketch.EndPoint connectingEndpoint = gate.Shape.ClosestEndpointFrom(connectedShape); if (gate.ShouldBeInput(connectingEndpoint)) { inputWires.Add(connectedShape); } else { outputWires.Add(connectedShape); } } // Make the connections. foreach (Shape wire in inputWires) { WireMesh inputWire = _wireMeshes[wire]; gate.ConnectInput(inputWire); } foreach (Shape wire in outputWires) { WireMesh outputWire = _wireMeshes[wire]; gate.ConnectOutput(outputWire); } gate.ConnectAllInputs(); gate.ConnectAllOutputs(); }
/// <summary> /// Connects a wire-mesh to the invoking circuit input, making /// the input the input/source of the wire. /// </summary> /// <param name="wire">The wire to connect to</param> public void Connect(WireMesh wire) { // If we already connected this wire, we're done! if (_outputWires.Contains(wire)) { return; } _outputWires.Add(wire); // Make sure the wire has the same connection wire.ConnectSource(this, 0); }
/// <summary> /// Compares two wires on the basis of the Y value of the endpoint that connects to this gate /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public int WireSort(WireMesh a, WireMesh b) { Sketch.EndPoint aEnd = Shape.ClosestEndpointFrom(a.Shape); Sketch.EndPoint bEnd = Shape.ClosestEndpointFrom(b.Shape); if (aEnd.Y < bEnd.Y) { return(-1); } else if (aEnd.Y > bEnd.Y) { return(1); } return(0); }
/// <summary> /// Connects a wire-mesh to the invoking circuit output, making /// the circuit output's value dependent on this wire. /// </summary> /// <param name="wire">The wire to connect</param> public void Connect(WireMesh wire) { // If we already connected to this wire, we're done! if (_outputWires.Contains(wire) || _inputWires.ContainsKey(wire)) { return; } // If this wire doesn't come from somewhere, it comes from here. Otherwise, it gives us value. if (!wire.HasSource) { _outputWires.Add(wire); wire.ConnectSource(this, 0); } else { _inputWires[wire] = wire.ConnectedEndpoints(this); wire.ConnectDependent(this); } }
/// <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); } }
/// <summary> /// Sorts inputs by where they are on screen, constructs the input dictionary /// </summary> public void OrderInputs() { // Get all the endpoints List <Sketch.EndPoint> connectedEndpoints = InputEndpoints; Dictionary <Sketch.EndPoint, CircuitComponent> endpointsToNotBubbles = new Dictionary <Sketch.EndPoint, CircuitComponent>(); // Take care of any not bubbles foreach (CircuitComponent connected in _inputComponents.Keys) { if (Domain.LogicDomain.IsGate(connected.Type) && connected.Shape.ConnectedShapes.Contains(Shape) && connected.InputEndpoints.Count > 0) { connectedEndpoints.Add(connected.InputEndpoints[0]); endpointsToNotBubbles[connected.InputEndpoints[0]] = connected; } } // Sort all these endpoints connectedEndpoints.Sort(EndpointSort); // Make the input dictionary _inputDictionary.Clear(); for (int index = 0; index < connectedEndpoints.Count; index++) { if (EndpointsToWires.ContainsKey(connectedEndpoints[index])) { WireMesh wire = EndpointsToWires[connectedEndpoints[index]]; if (wire.HasSource) { _inputDictionary[index] = new Tuple <CircuitComponent, int>(wire.Source, wire.SourceIndex); } } else { CircuitComponent notBubble = endpointsToNotBubbles[connectedEndpoints[index]]; _inputDictionary[index] = new Tuple <CircuitComponent, int>(notBubble, 0); } } }
/// <summary> /// Creates a circuit component for every Wire or Gate shape in /// a given sketch to store in the invoking circuit parser. /// Note that it does not add labels (circuit inputs/outputs) /// or anything else that's not a wire or gate. /// /// Assumption: every shape in the sketch has a unique name. /// /// Note: we can remove this assumption by using the shape ID /// (GUIDs) as keys in CircuitParser's dictionaries. We use /// the shape names primarily because it helps with debugging, /// and that circuit elements are differentiated by their names /// later along the line so names should be unique anyway. /// </summary> /// <param name="sketch"></param> private void loadWiresAndGates(Sketch.Sketch sketch) { foreach (Sketch.Shape shape in sketch.Shapes) { if (Domain.LogicDomain.IsWire(shape.Type)) { WireMesh newWire = new WireMesh(shape); _wireMeshes.Add(newWire.Name, newWire); if (debug) { Console.WriteLine("Found wire: " + newWire.Name); } } else if (Domain.LogicDomain.IsGate(shape.Type)) { LogicGate newGate = new LogicGate(shape); _logicGates.Add(newGate.Name, newGate); if (debug) { Console.WriteLine("Found gate: " + newGate.Name); } } } }
/// <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); } }
/// <summary> /// Connects a wire-mesh as an input to the invoking logic gate. /// </summary> /// <param name="wire">The wire-mesh to connect</param> public void ConnectInput(WireMesh wire) { List <Sketch.EndPoint> connectedEndpoints = wire.ConnectedEndpoints(this); _inputWires[wire] = connectedEndpoints; }