public void TestStandardMerge() { Shape shape1 = Shapes.newValidShape(); Shape shape2 = Shapes.newValidShape(); Shape shape3 = Shapes.newValidShape(); Sketch.Sketch sketch = new Sketch.Sketch(); sketch.CheckConsistency(); sketch.AddShape(shape1); sketch.AddShape(shape2); sketch.AddShape(shape3); sketch.connectShapes(shape1, shape3); sketch.connectShapes(shape2, shape3); Assert.IsTrue(sketch.AreConnected(shape1, shape3), "Shape 1 is not connected to shape 3"); Assert.IsTrue(sketch.AreConnected(shape2, shape3), "Shape 2 is not connected to shape 3"); sketch.CheckConsistency(); Assert.IsTrue(sketch.containsShape(shape1), "Sketch does not contain shape 1"); Assert.IsTrue(sketch.containsShape(shape2), "Sketch does not contain shape 2"); sketch.mergeShapes(shape1, shape2); Assert.IsTrue(sketch.AreConnected(shape1, shape3), "Shape 1 is not connected to shape 3 (after merge)"); Assert.IsFalse(sketch.AreConnected(shape1, shape1), "Shape 1 is connected to itself (after merge)"); Assert.IsFalse(sketch.AreConnected(shape1, shape2), "Shape 1 is connected to shape 2 (after merge)"); Assert.IsTrue(sketch.containsShape(shape1), "Sketch does not contain shape 1 (after merge)"); Assert.IsFalse(sketch.containsShape(shape2), "Sketch contains shape 2 (after merge)"); }
/// <summary> /// Attempts to merge the designated not bubble with the designated shape. /// /// Only works if connected is a gate that can have a not bubble on the front of it. /// </summary> /// <param name="bubble">The not bubble in question.</param> /// <param name="connected">The connected shape to try to merge with.</param> /// <returns>Whether or not the shapes were able to merge.</returns> private bool tryToMerge(Shape bubble, Shape connected) { if (bubble.Type != LogicDomain.NOTBUBBLE) { Console.WriteLine("You thought " + bubble.Name + " was a NotBubble, but it's not!"); return(false); } if (connected.Type.Classification != LogicDomain.GATE_CLASS) { return(false); } ShapeType newType = new ShapeType(); if (connected.Type == LogicDomain.AND) { newType = LogicDomain.NAND; } else if (connected.Type == LogicDomain.OR) { newType = LogicDomain.NOR; } else if (connected.Type == LogicDomain.XOR) { newType = LogicDomain.XNOR; } if (newType != new ShapeType()) { _sketch.mergeShapes(connected, bubble); #if (DEBUG) Console.WriteLine("Adding a NotBubble changed a " + connected.Type + " to a " + newType); #endif connected.Type = newType; return(true); } return(false); }
/// <summary> /// Once strokes are grouped, turn the stroke pairs into shapes. /// </summary> /// <param name="pairs">The list of stroke pairs that should be merged into shapes.</param> /// <param name="sketch">The sketch the strokes exist in; where the shapes should be created.</param> private void makeShapes(List <Sketch.StrokePair> pairs, Sketch.Sketch sketch) { foreach (Sketch.StrokePair pair in pairs) { Sketch.Shape shape1 = pair.Item1.ParentShape; Sketch.Shape shape2 = pair.Item2.ParentShape; // If they've already been merged, forget it. if (shape1 == shape2) { continue; } // If either one is null, we have a problem! if (shape1 == null || shape2 == null) { throw new Exception("Cannot merge substrokes " + pair.Item1 + " and " + pair.Item2 + "; one or both are missing a parent shape"); } // Don't merge any user-specified shapes. if (shape1.AlreadyGrouped || shape2.AlreadyGrouped) { continue; } sketch.mergeShapes(shape1, shape2); } #if DEBUG Console.WriteLine("Your sketch has " + sketch.Shapes.Length + " distinct shapes."); int gates = 0; foreach (Sketch.Shape shape in sketch.Shapes) { if (shape.Classification == LogicDomain.GATE_CLASS) { gates++; } } Console.WriteLine(gates + " of those shapes are gates."); #endif }
/// <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 }