/// <summary> /// Populates the stroke objects in an Ink Overlay object using the /// substrokes in a sketch object /// </summary> /// <param name="sketch">Sketch containing substrokes to convert</param> private void FillInkOverlay(Sketch.Sketch sketch, InkOverlay overlayInk, Panel inkPanel, float paddingOffset, Dictionary <Guid, string> strokeClassifications) { overlayInk.Ink.DeleteStrokes(); foreach (Substroke s in sketch.Substrokes) { overlayInk.Ink.CreateStroke(s.PointsAsSysPoints); Color c = Color.Black; if (this.strokeColor.ContainsKey(s)) { c = this.strokeColor[s]; } overlayInk.Ink.Strokes[overlayInk.Ink.Strokes.Count - 1].DrawingAttributes.Color = c; } // Move center the ink's origin to the top-left corner Rectangle bb = overlayInk.Ink.GetBoundingBox(); ScaleAndMoveInk(overlayInk, inkPanel, paddingOffset); UpdateColors(overlayInk, inkPanel); }
/// <summary> /// Initializes data structure members for holding /// the sketch and associated shape data. /// </summary> private void init() { this.sketch = new Sketch.Sketch(); this.shapeToAttrs = new Dictionary <Guid, XmlStructs.XmlShapeAttrs>(); this.shapeToShapeIDs = new Dictionary <Guid, List <Guid> >(); this.shapeToStrokeIDs = new Dictionary <Guid, List <Guid> >(); this.shapeToSubstrokeIDs = new Dictionary <Guid, List <Guid> >(); this.shapeToNeighborIDs = new Dictionary <Guid, List <Guid> >(); this.strokeToAttrs = new Dictionary <Guid, XmlStructs.XmlShapeAttrs>(); this.strokeToSubstrokeIDs = new Dictionary <Guid, List <Guid> >(); this.substrokeToAttrs = new Dictionary <Guid, XmlStructs.XmlShapeAttrs>(); this.substrokeToPointIDs = new Dictionary <Guid, List <Guid> >(); this.pointsHT = new Dictionary <Guid, Point>(); this.inputs = new List <string>(); this.outputs = new List <string>(); this.behavior = new Dictionary <int[], int[]>(); }
/// <summary> /// Get a set of all non-wire shapes whose contexts would be improved if they were connected to another wire. /// </summary> /// <param name="sketch"></param> /// <param name="closestContexts"></param> /// <returns></returns> private List <Shape> findNonWiresMissingConnections(Sketch.Sketch sketch, Dictionary <Shape, Tuple <double, ConnectionContext> > closestContexts) { List <Shape> nonWiresMissingWireConnections = new List <Shape>(); foreach (Shape shape in sketch.Shapes) { if (shape.Type != LogicDomain.WIRE) { Tuple <double, ConnectionContext> currentContext = closestContexts[shape]; Tuple <double, ConnectionContext> potentialContext = _domain.ClosestContextIfConnectedToType(shape, LogicDomain.WIRE_CLASS); // If we would be better off connecting this to a wire, let's mark it as such // Also, if we *could* make this connection without hurting things, let's do it // (if only to fix the missing wire endpoint connection) if (potentialContext.Item1 >= currentContext.Item1) { nonWiresMissingWireConnections.Add(shape); } } } return(nonWiresMissingWireConnections); }
/// <summary> /// Workpath method /// </summary> /// <param name="projFile">String containing full filepath of Xilinx .ise /// project file</param> /// <param name="filename">String containing sketch xml filename</param> /// <param name="sktch">Sketch.Sketch object</param> /// <param name="superWire">List of Superwire objects of the recognized /// circuit</param> /// <param name="tv">List of Pin objects containing the inputs and outputs /// recognized by the truth table recognizer</param> private bool path(String projFile, String filename, Sketch.Sketch sktch, List <List <Pin> > tv, CircuitRec.CircuitRec circuit) { //In the off chance that either the passed in filename or project file //is null, simulation can not proceed (possibly unnecessary) if (projFile == null || filename == null) { return(false); } //save the sketch as an xml file //XMLWrite(filename, sktch); //if rectify returns null, the truth table and circuitrec results could //not be rectified, so simulation can't proceed List <Mesh> superWire = new List <Mesh>(); superWire.AddRange(circuit.Meshes); if (inOutRectify(tv[0], superWire, filename) == null) { return(false); } tv.RemoveAt(0); VerilogWrite vw = new VerilogWrite(circuit, filename); pins2testVectors(tv, filename); //Execute Xilinx and Modelsim components of workflow XilinxRun(filename, projFile); simulate(filename, projFile); //if it gets to the end of the method, then simulation made it completely //through the workpath code return(true); }
/// <summary> /// Sends the sketch to the networked Wizard Labeler. /// </summary> /// <param name="sketch">The sketch to send</param> /// <param name="selectedStrokes">Selection of strokes to recognize (ignored for now)</param> /// <param name="userTriggered">True iff the user triggered recognition</param> void Recognizer.recognize(Sketch.Sketch sketch, Sketch.Stroke[] selectedStrokes, bool userTriggered) { // For fast sketchers, XML (un)marshalling causes a bottleneck. // Here we limit the frequency with which the Wizard is updated // in order to avoid crashes due to this bottleneck. if (!userTriggered && (DateTime.Now.Ticks - lastSketchSent.Ticks) <= WizardMaxUpdateThreshold) { Console.WriteLine("Fast sketcher! Skipping Wizard Labeler Update. Duration: " + (DateTime.Now.Ticks - lastSketchSent.Ticks)); return; } Console.WriteLine("Firing send. Duration: " + (DateTime.Now.Ticks - lastSketchSent.Ticks)); // Create XML from the sketch MakeXML makeXml = new MakeXML(sketch); // If the user triggered recognition, then // internally remember this event so that // the recognizer will fire a recognition // event as soon as a result is received. this.waitingOnWizard = userTriggered; // Give XML to the SocketClient for transmittal string xmlStr = makeXml.getXMLstr(); DefaultNamespace.SocketClient.SocketClientSendXml sendDelegate = new DefaultNamespace.SocketClient.SocketClientSendXml(socketClient.SendXml); sendDelegate.BeginInvoke(xmlStr, userTriggered, null, null); //TextWriter errorWriter = new StreamWriter("errorSketch.xml"); //errorWriter.Write(xmlStr); // Record when sketch was sent lastSketchSent = DateTime.Now; }
/// <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(shape, newWire); if (debug) { Console.WriteLine("Found wire: " + newWire.Name); } } else if (Domain.LogicDomain.IsGate(shape.Type)) { LogicGate newGate = new LogicGate(shape); _logicGates.Add(shape, newGate); if (debug) { Console.WriteLine("Found gate: " + newGate.Name); } } } }
/// <summary> /// processFile: performs the conversion of types. /// </summary> /// <param name="args">Name of the file to be converted</param> static void processFile(string filename) { string outputFilename = filename.Remove(filename.Length - Program.OLD_EXTENSION.Length + 1) + Program.NEW_EXTENSION; try { Sketch.Sketch sketch = (new ReadXML(filename)).Sketch; foreach (Sketch.Shape shape in sketch.Shapes) { String type = shape.XmlAttrs.Type.ToString(); if (type.Equals("AND") || type.Equals("OR") || type.Equals("NOT") || type.Equals("NAND") || type.Equals("NOR") || type.Equals("XOR") || type.Equals("XNOR")) { shape.XmlAttrs.Type = "Gate"; //} else if (!type.Equals("Wire")) // we have "Other" or "Label" and we want to delete it. //{ // sketch.RemoveShape(shape); //} } else if (type.Equals("Other")) { sketch.RemoveShape(shape); } } (new MakeXML(sketch)).WriteXML(outputFilename); } catch (Exception e) { Console.WriteLine("Exception was generated during conversion: {0}", e); return; } }
/// <summary> /// When the user manually triggers recognition, label everything /// in the sketch as a wire, and label a fixed percentage of a /// random selection of substrokes as erroneous. /// </summary> public override RecognitionResult Recognize(RecognitionArgs args) { RecognitionResult result = new RecognitionResult(); // Only operate on user triggered recognition events if (!args.UserTriggered) { return(result); } if (args.Sketch == null) { return(result); } Sketch.Sketch sketch = args.Sketch; // Label the substrokes foreach (Substroke sub in sketch.Substrokes) { if (randObj.NextDouble() < ErrorRate) { sketch.AddLabel(sub, ErrorLabel, 1.0); } else { sketch.AddLabel(sub, WireLabel, 1.0); } } // Create result result.UserTriggered = args.UserTriggered; result.Sketch = sketch; return(result); }
public void process(FeatureSketch featureSketch) { _producer.Start(featureSketch); Sketch.Sketch sketch = featureSketch.Sketch; SketchModification actionToTake; for (int i = 0; i < MAX_ITERATIONS; i++) { List <SketchModification> modifications = _producer.SketchModifications(featureSketch); actionToTake = _searchMethod.chooseAction(modifications, sketch); if (actionToTake == null) { break; } if (debug) { Console.WriteLine("Performing action: " + actionToTake); } actionToTake.perform(); } }
/// <summary> /// Constructor /// </summary> /// <param name="sketch"></param> public MakeJnt(Sketch.Sketch sketch) { ink = new Ink(); Sketch.Substroke[] substrokes = sketch.Substrokes; int slength = substrokes.Length; int plength; int i; int k; for (i = 0; i < slength; ++i) { Sketch.Point[] sketchPts = substrokes[i].Points; System.Drawing.Point[] simplePts = new System.Drawing.Point[sketchPts.Length]; plength = simplePts.Length; for (k = 0; k < plength; k++) { simplePts[k] = new System.Drawing.Point((int)sketchPts[k].X, (int)sketchPts[k].Y); } ink.CreateStroke(simplePts); } }
/* some extra constructors just in case */ public NeighborhoodMap(Sketch.Sketch sketch, double radius) : this(sketch, radius, false, 0) { }
/// <summary> /// Add "strokes" connecting the middle of substrokes adjacent in the graph. /// ID labels absed on /// </summary> /// <param name="sketch">sketch to modify</param> /// <param name="graph">neighborhood graph</param> private static void AddDebuggingLines2(ref Sketch.Sketch sketch, NeighborhoodMap graph) { string[] labels = { "AND", "OR", "NOT", "NAND", "NOR", "XOR", "Wire", "BUBBLE", "Label" }; List <List <Substroke> > components = graph.connectedComponents(); #region midpoints Dictionary <Substroke, Sketch.Point> midpoints = new Dictionary <Substroke, Sketch.Point>(); foreach (Substroke s in sketch.Substrokes) { midpoints.Add(s, s.PointsL[s.PointsL.Count / 2]); } #endregion double bbminx, bbmaxx, bbminy, bbmaxy; double bbarea = area(graph.Substrokes, out bbminx, out bbmaxx, out bbminy, out bbmaxy); double THRESH = Math.Min(bbmaxx - bbminx, bbmaxy - bbminy) / 5; foreach (List <Substroke> group in components) { Shape xyz = new Shape(group, new XmlStructs.XmlShapeAttrs(true)); xyz.XmlAttrs.Name = "Shape"; xyz.XmlAttrs.Time = 1; double minx, maxx, miny, maxy; double a = area(group, out minx, out maxx, out miny, out maxy); // check if it is an outer group and relatively small if ((minx - THRESH <= bbminx || maxx + THRESH >= bbmaxx || miny - THRESH <= bbminy || maxy + THRESH >= bbmaxy) && a <= bbarea / 40.0) { xyz.XmlAttrs.Type = "Label"; Console.Write("label!"); } else { xyz.XmlAttrs.Type = "Wire"; } sketch.AddShape(xyz); } #region old /* * foreach (Substroke s in graph.Substrokes) * { * * foreach (Neighbor n in graph[s]) * { * * Substroke sub = new Substroke(new Sketch.Point[] { midpoints[s], midpoints[n.neighbor] }, * new XmlStructs.XmlShapeAttrs(true)); * sub.XmlAttrs.Time = 0; * sub.XmlAttrs.Name = "substroke"; * sub.XmlAttrs.Type = "substroke"; * Stroke str = new Stroke(sub); * str.XmlAttrs.Time = 0; * str.XmlAttrs.Name = "stroke"; * str.XmlAttrs.Type = "stroke"; * Shape xor = new Shape(new List<Substroke>(new Substroke[] { sub }), * new XmlStructs.XmlShapeAttrs(true)); * xor.XmlAttrs.Type = thislabel; * xor.XmlAttrs.Name = "Shape"; * xor.XmlAttrs.Time = 0; * sketch.AddStroke(str); * sketch.AddShape(xor); * } * } * */ #endregion }
public NeighborhoodMap(Sketch.Sketch sketch, double radius, bool directed) : this(sketch, radius, directed, 0) { }
static void Main(string[] args) { if (args.Length == 0) { Console.WriteLine("BatchDRSConverter: Convert DRS formatted files to MIT XML formatted files"); Console.WriteLine("usage: BatchDRSConverter.exe [-d input_directory] [-o output_directory] [files]"); Console.WriteLine("if an input directory is given, extra files on the command line are ignored"); Environment.Exit(1); } string indir = "", outdir = ""; for (int i = 0; i < args.Length; i++) { if (args[i] == "-d") { indir = args[++i]; } else if (args[i] == "-o") { outdir = args[++i]; } } List <string> files = new List <string>(); if (indir == "") { for (int i = 0; i < args.Length; i++) { if (args[i] == "-o") { i++; } else { files.Add(args[i]); } } } else { if (!Directory.Exists(indir)) { Console.WriteLine("Input directory '{0}' does not exist. Exiting.", indir); Environment.Exit(1); } files.AddRange(Directory.GetFiles(indir, ".drs")); files.AddRange(Directory.GetFiles(indir, ".DRS")); } foreach (string file in files) { if (!File.Exists(file)) { Console.WriteLine("File '{0}' does not exist. Continuing.", file); } Sketch.Sketch sketch = ReadDRS.load(file); MakeXML mxml = new MakeXML(sketch); string outfile = ""; if (outdir == "") { outfile = file.Substring(0, file.LastIndexOf('.')) + ".xml"; } else { outfile = outdir + file.Substring(file.LastIndexOf(Path.DirectorySeparatorChar), file.LastIndexOf('.') - file.LastIndexOf(Path.DirectorySeparatorChar)) + ".xml"; } mxml.WriteXML(outfile); } }
public SketchModification chooseAction(List <SketchModification> availableActions, Sketch.Sketch sketch) { SketchModification result = null; double max = 0; foreach (SketchModification action in availableActions) { double change = action.benefit(); if (change > max) { result = action; max = change; } } return(result); }
/// <summary> /// Inheritors classes supply the feedback mechanism's visual effect. /// </summary> public abstract void FireFeedbackMechanism(Sketch.Sketch sketch, InkPicture inkPicture, Hashtable ink2sketchIdTable, FeedbackContext context);
/// <summary> /// Constructor for CreateSymbol. /// </summary> /// <param name="sketch">The current sketch.</param> public CreateSymbol(Sketch.Sketch sketch) { this.sketch = sketch; }
public NeighborhoodMap(Sketch.Sketch sketch, double radius, int context) : this(sketch, radius, false, context) { }
/// <summary> /// Constructor, creates an empty ReadJnt instance that /// can function as an converter for ink to sketch data. /// <see cref="ReadJnt.InkStroke2SketchStroke()"/> /// </summary> public ReadJnt() { sketch = null; }
public List <SketchModification> SketchModifications(Featurefy.FeatureSketch featureSketch) { Sketch.Sketch sketch = featureSketch.Sketch; if (debug) { Console.WriteLine("Sketch Modifications:"); } // Used to assemble the list of results List <SketchModification> results = new List <SketchModification>(); // Precompute closest contexts for each shape Dictionary <Shape, Tuple <double, ConnectionContext> > closestContexts = new Dictionary <Shape, Tuple <double, ConnectionContext> >(); foreach (Shape shape in sketch.Shapes) { closestContexts.Add(shape, _domain.ClosestContext(shape)); } // ========================================================================================================== /* * Operation zero: running the connector is ALWAYS an option. */ //results.Add(new SketchModification(sketch, new RunConnectorOperation(featureSketch, _connector), computeEnergy)); // ========================================================================================================== /* * First things first: missing connections * This takes care of obvious connector problems. If there is a wire with a dangling endpoint and a * shape that would be better off connected to a wire, we make that connection. The benefit is: * benefit = 1 / distance * where "distance" is the minimum distance from the dangling endpoint to the shape. This will favor * close connections over distant ones. */ List <EndPoint> wiresMissingConnections = findWireEndpointsMissingConnections(sketch); List <Shape> nonWiresMissingWireConnections = findNonWiresMissingConnections(sketch, closestContexts); foreach (EndPoint wireEndpoint in wiresMissingConnections) { foreach (Shape shape in nonWiresMissingWireConnections) { Shape wire = wireEndpoint.ParentShape; if (debug) { Console.WriteLine("ACTION (connect wire endpoint): " + sketch + ", " + wire + ", " + wireEndpoint + ", " + shape); } var op = new ConnectEndpointOperation(sketch, wireEndpoint, shape); var modification = new SketchModification(featureSketch, op, computeEnergy); results.Add(modification); } } // ========================================================================================================== /* * Second: relabeling * Now we go through every shape and see if its context would be better matched as a different shape. * If so, we can change the shape. The benefit is the % improvement in context score plus the % * improvement in recognition quality. */ foreach (Shape shape in sketch.Shapes) { if (shape.AlreadyLabeled) { continue; } Tuple <double, ConnectionContext> currentContext = closestContexts[shape]; List <ShapeType> allTypes = LogicDomain.Types; foreach (ShapeType otherType in AlternateTypes(shape.Type)) { if (debug) { Console.WriteLine("ACTION (relabel shape): " + shape + ", " + otherType); } var op = new RelabelShapeOperation(sketch, shape, RecognizeAsType(shape, otherType, featureSketch)); var modification = new SketchModification(featureSketch, op, computeEnergy); results.Add(modification); } } // ========================================================================================================== /* * Third: stroke steal * This works as follows: * * For every shape, get the set of closeSubstrokes (within a certain threshold). * For every substroke in closeSubstrokes * generate a steal modification (substroke --> shape) * * The steal modifications should have their benefit based on * (1) connection contexts * (2) recognition quality */ foreach (Shape thief in sketch.Shapes) { if (thief.AlreadyLabeled) { continue; } List <Substroke> closeSubstrokes = findSubstrokesCloseTo(thief, sketch, STROKE_STEAL_THRESHOLD); foreach (Substroke gem in closeSubstrokes) // thiefs steal gems { Shape victim = gem.ParentShape; // thiefs steal from victims if (victim.AlreadyLabeled) { continue; } // find the thief's new type var newThiefSubstrokes = new List <Substroke>(thief.SubstrokesL); newThiefSubstrokes.Add(gem); RecognitionResult newThiefRecognition = Identify(newThiefSubstrokes, featureSketch); if (debug) { Console.WriteLine("ACTION (steal stroke): " + thief + ", " + victim + ", " + gem); } var stealOp = new StrokeStealOperation(sketch, thief, gem); var relabelThiefOp = new RelabelShapeOperation(sketch, thief, newThiefRecognition); var runConnectorOp = new RunConnectorOperation(featureSketch, _connector); ISketchOperation op; // if the victim will still be around after the steal if (victim.Substrokes.Length > 1) { var newVictimSubstrokes = new List <Substroke>(victim.SubstrokesL); newVictimSubstrokes.Remove(gem); RecognitionResult newVictimRecognition = Identify(newVictimSubstrokes, featureSketch); var relabelVictimOp = new RelabelShapeOperation(sketch, victim, newVictimRecognition); op = new CompoundSketchOperation(stealOp, relabelThiefOp, relabelVictimOp, runConnectorOp); } else { op = new CompoundSketchOperation(stealOp, relabelThiefOp, runConnectorOp); } var modification = new SketchModification(featureSketch, op, computeEnergy); results.Add(modification); } } if (debug && results.Count == 0) { Console.WriteLine("(none)"); } // Keep only the ones greater than the cutoff results = results.FindAll(r => { return(r.benefit() > BENEFIT_CUTOFF); }); return(results); }
public ISketchModification chooseAction(List <ISketchModification> availableActions, ContextDomain.ContextDomain domain, Sketch.Sketch sketch) { ISketchModification result = null; double max = 0; foreach (ISketchModification action in availableActions) { double change = action.benefit(); if (change > max) { result = action; max = change; } } return(result); }
/// <summary> /// Set Ink stroke text labels based upon domain /// </summary> public override void FireFeedbackMechanism(Sketch.Sketch sketch, InkPicture inkPicture, Hashtable ink2sketchIdTable, FeedbackContext context) { // // Preprocessing // // Remove all current textboxes from the inkPicture // and clear the table of textboxes; start out fresh foreach (Label currentLabel in textboxList) { inkPicture.Controls.Remove(currentLabel); } textboxList.Clear(); // Build hashtable of sketch substroke Ids to ink strokes Hashtable substroke2InkTable = new Hashtable(); System.Guid currentGuid; foreach (Microsoft.Ink.Stroke iStroke in inkPicture.Ink.Strokes) { // If this ink stroke does not have a // corresponding sketch stroke, skip it if (!ink2sketchIdTable.Contains(iStroke.Id)) { continue; } currentGuid = (System.Guid)ink2sketchIdTable[iStroke.Id]; substroke2InkTable.Add(currentGuid, iStroke); } // // Iterate through shapes // Graphics g = inkPicture.CreateGraphics(); foreach (Sketch.Shape shape in sketch.Shapes) { // Get label of this shape string label = shape.Substrokes[0].GetFirstLabel(); // // Color wires and don't label them // if (label == "Wire") { foreach (Sketch.Substroke substroke in shape.Substrokes) { if (!substroke2InkTable.Contains(substroke.XmlAttrs.Id)) { // If, for some reason, there is no ink stroke // that corresponds to this substroke, skip it continue; } Microsoft.Ink.Stroke iStroke = (Microsoft.Ink.Stroke)substroke2InkTable[substroke.XmlAttrs.Id]; iStroke.DrawingAttributes.Color = UIConstants.TextFeedbackMechanismWireColor; } } // // Draw boxes over input/output labels // else if (label == "Label") { // For efficiency's sake, we color the strokes while calculating the bounding box. Rectangle boundingBox = calculateBoundingBox(shape, substroke2InkTable, true); // Devise the (x,y) location of the text label on the screen System.Drawing.Point upperLeft = new System.Drawing.Point(boundingBox.X, boundingBox.Y); System.Drawing.Point lowerRight = new System.Drawing.Point(boundingBox.Right, boundingBox.Bottom); inkPicture.Renderer.InkSpaceToPixel(g, ref upperLeft); inkPicture.Renderer.InkSpaceToPixel(g, ref lowerRight); upperLeft.X -= 10; upperLeft.Y -= 10; lowerRight.X += 10; lowerRight.Y += 10; int bwidth = lowerRight.X - upperLeft.X; int bheight = lowerRight.Y - upperLeft.Y; // Create bounding box for label // HACK!! TODO: draw a transparent label // instead of four labels to make // a box around the symbol Label topLabel = new Label(); Label bottomLabel = new Label(); Label leftLabel = new Label(); Label rightLabel = new Label(); topLabel.UseMnemonic = false; bottomLabel.UseMnemonic = false; leftLabel.UseMnemonic = false; rightLabel.UseMnemonic = false; topLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; bottomLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; leftLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; rightLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; // Set label positions topLabel.Location = upperLeft; topLabel.Height = 1; topLabel.Width = bwidth; bottomLabel.Location = new System.Drawing.Point(upperLeft.X, upperLeft.Y + bheight); bottomLabel.Height = 1; bottomLabel.Width = bwidth; leftLabel.Location = new System.Drawing.Point(upperLeft.X, upperLeft.Y); leftLabel.Height = bheight; leftLabel.Width = 1; rightLabel.Location = new System.Drawing.Point(upperLeft.X + bwidth, upperLeft.Y); rightLabel.Height = bheight; rightLabel.Width = 1; topLabel.Enabled = true; bottomLabel.Enabled = true; leftLabel.Enabled = true; rightLabel.Enabled = true; inkPicture.Controls.Add(topLabel); inkPicture.Controls.Add(bottomLabel); inkPicture.Controls.Add(leftLabel); inkPicture.Controls.Add(rightLabel); textboxList.Add(topLabel); textboxList.Add(bottomLabel); textboxList.Add(leftLabel); textboxList.Add(rightLabel); } // // Draw labels for other symbols // else { // For efficiency's sake, we color the strokes while calculating the bounding box. Rectangle boundingBox = calculateBoundingBox(shape, substroke2InkTable, true); // Devise the (x,y) location of the text label on the screen System.Drawing.Point center = new System.Drawing.Point(boundingBox.Width / 2 + boundingBox.Left, boundingBox.Height / 2 + boundingBox.Top); System.Drawing.Point upperLeft = new System.Drawing.Point(boundingBox.X, boundingBox.Y); System.Drawing.Point lowerRight = new System.Drawing.Point(boundingBox.Right, boundingBox.Bottom); inkPicture.Renderer.InkSpaceToPixel(g, ref center); inkPicture.Renderer.InkSpaceToPixel(g, ref upperLeft); inkPicture.Renderer.InkSpaceToPixel(g, ref lowerRight); center.X += inkPicture.Bounds.X; center.Y += inkPicture.Bounds.Y; // Create textbox for label Label textLabel = new Label(); textLabel.UseMnemonic = false; textLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; textLabel.Text = label; textLabel.TextAlign = ContentAlignment.MiddleCenter; textLabel.AutoSize = true; // Position label so that it is either on top of the symbol, // or, if the symbol is very small, along side the symbol int bwidth = lowerRight.X - upperLeft.X; int bheight = lowerRight.Y - upperLeft.Y; if (textLabel.Width < bwidth && textLabel.Height < bheight) { center.X -= textLabel.Width / 2; center.Y -= textLabel.Height / 2; } else { // If taller than is wide, place label to the right; // else place label just above symbol if (boundingBox.Height > boundingBox.Width) { center.Y -= textLabel.Height / 2; center.X += bwidth / 2; } else { center.Y += bheight / 2; center.X -= textLabel.Width / 2; } } textLabel.Location = center; textLabel.Enabled = true; inkPicture.Controls.Add(textLabel); textboxList.Add(textLabel); } } }
/// <summary> /// Set Ink stroke colors based upon domain /// </summary> public override void FireFeedbackMechanism(Sketch.Sketch sketch, InkPicture inkPicture, Hashtable ink2sketchIdTable, FeedbackContext context) { // Only fire feedback on recogition events if (context != FeedbackContext.OnRecognitionResult) { return; } // Disable the Ink Picture if it is already enabled bool toggleInkPic = inkPicture.Enabled; if (toggleInkPic) { inkPicture.Enabled = false; } // Set Ink stroke colors foreach (Microsoft.Ink.Stroke istroke in inkPicture.Ink.Strokes) { // If this ink stroke does not have a // corresponding sketch stroke, skip it if (!ink2sketchIdTable.Contains(istroke.Id)) { continue; } // Get the label of the corresponding substroke Guid substrokeGuid = (Guid)ink2sketchIdTable[istroke.Id]; Substroke substr = sketch.GetSubstroke(substrokeGuid); if (substr != null) { string label = substr.GetFirstLabel(); // Now color the stroke istroke.DrawingAttributes.Color = domain.getColor(label); // Store the label if (this.ink2sketchLabelTable.Contains(istroke.Id)) { this.ink2sketchLabelTable[istroke.Id] = label; } else { this.ink2sketchLabelTable.Add(istroke.Id, label); } } else { // We should report an error here because // there should be a substroke // in the sketch if it's referenced in the // hashtable continue; } } // Re-enable the ink picture if it was enabled. if (toggleInkPic) { inkPicture.Enabled = true; } }
public RelabelShapeOperation(Sketch.Sketch sketch, Shape shape, RecognitionResult recognition) : base(sketch) { _shape = shape; _recognition = recognition; }
/// <summary> /// Compute the energy function that we are trying to maximize. /// </summary> /// <param name="sketch"></param> /// <returns>an unbounded double representing the energy of the sketch</returns> private double computeEnergy(FeatureSketch featureSketch) { Sketch.Sketch sketch = featureSketch.Sketch; featureSketch.hasConsistentSubstrokes(); sketch.CheckConsistency(); double energy = 0; var shapes = sketch.ShapesL; int numShapes = shapes.Count; int numGates = shapes.FindAll(s => LogicDomain.IsGate(s.Type)).Count; foreach (Shape shape in shapes) { // Add energy for every connection #if false // This is a bad idea. It favors interpretations with more connections, which basically means // that everything should alternate wire-text-wire-text-wire-... foreach (Shape connected in shape.ConnectedShapes) { if (connected == shape) { continue; } if (connected.Type != LogicDomain.WIRE) { continue; } double connectionDistance = double.PositiveInfinity; foreach (EndPoint endpoint in connected.Endpoints) { connectionDistance = Math.Min(shape.minDistanceTo(endpoint.X, endpoint.Y), connectionDistance); } connectionDistance = Math.Max(connectionDistance, 0.001); // avoid problems when connection distance is close to zero energy += 1 + 1 / connectionDistance; } #endif // Add the context match score energy += (double)_domain.ClosestContext(shape).Item1 / numShapes; // Get recognition results RecognitionResult result = RecognizeAsType(shape, shape.Type, featureSketch); double confidence = result.Confidence; // Add the recognition score energy += confidence / numShapes; #if false // Gate orientation also contributes if (LogicDomain.IsGate(shape.Type)) { // Determine the recognizer's and the connector's orientation values, // in the range [0, 2Pi] double orientation = result.Orientation; double otherOrientation = _domain.OrientShape(shape, sketch); // Orientation might be off by PI... double dist1 = Math.Abs(otherOrientation - orientation); double dist2 = Math.Abs(otherOrientation - Math.PI - orientation); double dist = Math.Min(dist1, dist2); // Add orientation score double twoPI = 2 * Math.PI; energy += (1 - (dist / twoPI)) / numGates; } #endif } return(energy); }
/// <summary> /// Generate the neighborhood graph. /// </summary> /// <param name="sketch">the sketch to generate the graph for</param> /// <param name="radius">the allowable distance one stroke to another</param> /// <param name="directed">if the graph should be directed</param> /// <param name="context">how many points of context should be used for direction</param> /// <returns>a populated NeighborhoodMap</returns> private void generateNeighborhood (Sketch.Sketch sketch, double radius, bool directed, int context) { long maxX = 0; // points indexed by Y*maxX+X Dictionary <long, List <Substroke> > intPoints = new Dictionary <long, List <Substroke> >(); map = new Dictionary <Substroke, NeighborList>(); points = new List <LinkedPoint>(); /* * First we find the maximum X value, which we use to index into * the points dictionary. */ foreach (Substroke s in sketch.Substrokes) { for (int i = 0; i < s.PointsL.Count; i++) { Sketch.Point p = s.PointsL[i]; if (p.X > maxX) { maxX = (long)p.X; } points.Add(new LinkedPoint(s, i)); } } maxX += 1; /* * Store the location of each point currently in the sketch */ foreach (Substroke s in sketch.Substrokes) { foreach (Sketch.Point p in s.PointsL) { long key = (long)p.Y * maxX; key += (long)p.X; if (!intPoints.ContainsKey(key)) { intPoints.Add(key, new List <Substroke>()); } intPoints[key].Add(s); } } /* * For each substroke, check if any of its points are close to * any other points from the sketch. */ foreach (Substroke s in sketch.Substrokes) { map.Add(s, new NeighborList()); for (int index = 0; index < s.PointsL.Count; index++) { if (index > 10 && index < s.PointsL.Count - 10) { continue; } if ((index == 0 || index == s.PointsL.Count - 1) && directed) { continue; } Sketch.Point p = s.PointsL[index]; if (directed && curvature(s, index, 1) - curvature(s, index, 20) > 1) { continue; } for (int i = 0; i < (int)radius; i++) { for (int j = 0; j < (int)radius && Math.Sqrt(i * i + j * j) < radius; j++) { if (i == 0 & j == 0) { continue; } /* * if p is the origin, we need to check the point translated by |i| * in the X-direction and |j| in the Y-direction in each of the 4 * quadrants. */ long key1 = (long)(p.Y + j) * maxX + (long)(p.X + i); long key2 = (long)(p.Y + j) * maxX + (long)(p.X - i); long key3 = (long)(p.Y - j) * maxX + (long)(p.X + i); long key4 = (long)(p.Y - j) * maxX + (long)(p.X - i); if (intPoints.ContainsKey(key1)) { if (!directed || checkDirection(s, index, context, i, j)) { foreach (Substroke test in intPoints[key1]) { if (test != s) { map[s].addPoint(test, new System.Drawing.Point((int)(p.X + i), (int)(p.Y + j)), new System.Drawing.Point((int)(p.X), (int)(p.Y))); } } } } if (intPoints.ContainsKey(key2)) { if (!directed || checkDirection(s, index, context, -i, j)) { foreach (Substroke test in intPoints[key2]) { if (test != s) { map[s].addPoint(test, new System.Drawing.Point((int)(p.X - i), (int)(p.Y + j)), new System.Drawing.Point((int)(p.X), (int)(p.Y))); } } } } if (intPoints.ContainsKey(key3)) { if (!directed || checkDirection(s, index, context, i, -j)) { foreach (Substroke test in intPoints[key3]) { if (test != s) { map[s].addPoint(test, new System.Drawing.Point((int)(p.X + i), (int)(p.Y - j)), new System.Drawing.Point((int)(p.X), (int)(p.Y))); } } } } if (intPoints.ContainsKey(key4)) { if (!directed || checkDirection(s, index, context, -i, -j)) { foreach (Substroke test in intPoints[key4]) { if (test != s) { map[s].addPoint(test, new System.Drawing.Point((int)(p.X - i), (int)(p.Y - j)), new System.Drawing.Point((int)(p.X), (int)(p.Y))); } } } } } } } } /* * Once we have constructed the Neighbor objects above, * the avg Point has the sum of all the points' X- and Y-values. * Now that we know the total, we can divide to find the true average. */ foreach (Substroke s in map.Keys) { for (int j = 0; j < map[s].Count; j++) { map[s][j].src.X /= map[s][j].num; map[s][j].src.Y /= map[s][j].num; map[s][j].dest.X /= map[s][j].num; map[s][j].dest.Y /= map[s][j].num; } } }
static void Main() { string[] files = { "AND", "OR", "XOR", "NAND", "NOR", "NOT", "EQ1", "EQ2", "COPY1", "COPY2" }; string sHeader = "SketchID,UserID,ShapeID,StrokeID,ShapeName,ShapeTime," + "StrokeTime,IsConsecutive,AveragePressure,Width,Height,AvgCurvature," + "MaxCurvature,MinCurvature,NumPoints,MinDist,StrokesPerShape,StartTime,EndTime"; string tHeader = "SketchID, StrokeID, X, Y, Time"; GateStats stats = new GateStats(files, sHeader); StreamWriter sSw; StreamWriter tSw; string[] hmc = Directory.GetFiles("c:\\sketch\\Data\\Gate Study Data\\LabeledSketches\\TabletPC\\HMC", "*.xml", SearchOption.AllDirectories); string[] ucr = Directory.GetFiles("c:\\sketch\\Data\\Gate Study Data\\LabeledSketches\\TabletPC\\UCR", "*.xml", SearchOption.AllDirectories); List <MySketch> sketches = new List <MySketch>(); // read HMC for (int i = 1; i <= 12; i++) { foreach (string file in hmc) { // only care about and/or/not //if (file.Contains("NAND") || file.Contains("NOR") || file.Contains("XOR")) continue; if (file.Contains(string.Format("\\{0}_", i))) // iso,copy { string act = file.Contains("COPY") ? "copy" : "iso"; sketches.Add(new MySketch(new ReadXML(file).Sketch, i, act)); } else if (file.Contains(string.Format("_{0}_", i))) // synth { sketches.Add(new MySketch(new ReadXML(file).Sketch, i, "synth")); } } } // read UCR for (int i = 1; i <= 12; i++) { foreach (string file in ucr) { // only care about and/or/not //if (file.Contains("NAND") || file.Contains("NOR") || file.Contains("XOR")) continue; if (file.Contains(string.Format("\\{0}_", i))) // iso,copy { string act = file.Contains("COPY") ? "copy" : "iso"; sketches.Add(new MySketch(new ReadXML(file).Sketch, i + 12, act)); } else if (file.Contains(string.Format("_{0}_", i))) // synth { sketches.Add(new MySketch(new ReadXML(file).Sketch, i + 12, "synth")); } } } sketches.Sort(delegate(MySketch a, MySketch b) { return(a.Author.CompareTo(b.Author)); }); int curruser = 0; string curuserstr = (curruser > 12) ? "HMC" + curruser : "******" + (curruser - 12); sSw = new StreamWriter("GateStats" + curuserstr + ".csv"); tSw = new StreamWriter("GateTimes" + curuserstr + ".csv"); Console.WriteLine("Writing user " + curuserstr + "..."); sSw.WriteLine(sHeader); tSw.WriteLine(tHeader); foreach (MySketch mysketch in sketches) { if (mysketch.Author != curruser) { sSw.Close(); tSw.Close(); curruser = mysketch.Author; curuserstr = (curruser > 12) ? "HMC" + curruser : "******" + (curruser - 12); sSw = new StreamWriter("GateStats" + curuserstr + ".csv"); tSw = new StreamWriter("GateTimes" + curuserstr + ".csv"); Console.WriteLine("Writing user " + curuserstr + "..."); } Sketch.Sketch sketch = mysketch.Sketch; for (int j = 0; j < sketch.Substrokes.Length; j++) { Substroke sub = sketch.Substrokes[j]; for (int i = 0; i < sub.Points.Length; i++) { string time = sketch.XmlAttrs.Id + "," + sub.XmlAttrs.Id + "," + sub.Points[i].X + "," + sub.Points[i].Y + "," + sub.Points[i].Time; tSw.WriteLine(time); } for (int i = 0; i < sub.ParentShapes.Count; i++) { string line = sketch.XmlAttrs.Id + "," + curuserstr + "," + sub.ParentShapes[i].XmlAttrs.Id + "," + sub.XmlAttrs.Id + "," + sub.ParentShapes[i].XmlAttrs.Type + "," + stats.findShapeTime(sub.ParentShapes[i]) + "," + stats.findSubStrokeTime(sub) + "," + stats.isConsecutive(sketch, sub.ParentShapes[i]) + "," + stats.findAvgPressure(sub) + "," + stats.getWidth(sub.ParentShapes[i]) + "," + stats.getHeight(sub.ParentShapes[i]) + "," + stats.getAvgCurvature(sub) + "," + stats.getMaxCurvature(sub) + "," + stats.getMinCurvature(sub) + "," + stats.getNumPoints(sub) + ","; if (sub.ParentShapes[i].XmlAttrs.Type == "Wire") { line = line + stats.minDistWireToGates(stats.findGatesInSketch(sketch), sub.ParentShapes[i]); } else if (sub.ParentShapes[i].XmlAttrs.Type == "Label") { line += stats.minDistLabelToWires(stats.findWiresInSketch(sketch), sub.ParentShapes[i]); } else { line += stats.minDistGateToWires(stats.findWiresInSketch(sketch), sub.ParentShapes[i]); } line += "," + stats.numStrokesPerShape(sub.ParentShapes[i]) + "," + stats.getStartTime(sub) + "," + stats.getEndTime(sub); sSw.WriteLine(line); } } } sSw.Close(); tSw.Close(); }
/// <summary> /// Create training data for a shape with its cropped context. /// </summary> /// <param name="neighborhood">The neighborhood mapping of substrokes to neighboring substrokes of the sketch.</param> /// <param name="filename">Filename of the current sketch.</param> /// <param name="start">Number of the file.</param> /// <param name="userID">User ID (usually four numbers in the filename)</param> private void croppedContextForShape(Neighborhood neighborhood, string filename, string start, string userID) { Sketch.Sketch croppedContextSketch = new Sketch.Sketch(this.sketch); string path = Path.GetFullPath(filename); string dir = Path.GetDirectoryName(path); // Go through every shape that is not context and write training data for each shape individually foreach (Shape shape in this.sketch.Shapes) { if (shape.XmlAttrs.Type != "context") { // Get all of the neighbors of the shape List <Substroke> neighbors = new List <Substroke>(); foreach (Substroke sub in shape.Substrokes) { foreach (Substroke neighbor in neighborhood.Graph[sub.XmlAttrs.Id.Value]) { if (!neighbors.Contains(neighbor)) { neighbors.Add(neighbor); } } } // Create new directory for the shape type if it does not exist string newDirectory = dir + "\\" + shape.XmlAttrs.Type; if (!Directory.Exists(newDirectory)) { Directory.CreateDirectory(newDirectory); } // Create new directory for the userID if it does not exist string userDirectory = newDirectory + "\\" + userID; if (!Directory.Exists(userDirectory)) { Directory.CreateDirectory(userDirectory); } // Create the windowed image of the shape and its context WindowedImage image = new WindowedImage(32, 32); image.CreateImage(shape.SubstrokesL, neighbors, CropMethod.DISTANCE); // Write the training file write(image.Cropped.SubStrokes, userDirectory + "\\" + shape.XmlAttrs.Type + "." + start + ".con.xml"); //image.DI.writeToBitmap(userDirectory + "\\" + start + "." + shape.XmlAttrs.Type, "con.bmp"); //image.DI.writeToFile(userDirectory + "\\" + start + "." + shape.XmlAttrs.Type + ".con.imat"); //image.writeToBitmap(userDirectory + "\\" + start + "." + shape.XmlAttrs.Type + ".con.bmp"); //image.writeToFile(userDirectory + "\\" + start + "." + shape.XmlAttrs.Type + ".con.imat").Close(); // Create the windowed image of the shape without context image = new WindowedImage(32, 32); image.CreateImage(shape.SubstrokesL, shape.SubstrokesL, CropMethod.DISTANCE); // Write the training file write(image.Cropped.SubStrokes, userDirectory + "\\" + shape.XmlAttrs.Type + "." + start + ".non.xml"); //image.DI.writeToBitmap(userDirectory + "\\" + start + "." + shape.XmlAttrs.Type, "non.bmp"); //image.DI.writeToFile(userDirectory + "\\" + start + "." + shape.XmlAttrs.Type + ".non.imat"); //image.writeToBitmap(userDirectory + "\\" + start + "." + shape.XmlAttrs.Type + ".non.bmp"); //image.writeToFile(userDirectory + "\\" + start + "." + shape.XmlAttrs.Type + ".non.imat").Close(); } } }
/// <summary> /// Does all the setup, creates a Designation class from a list of gates, and calls Designation.train(); /// </summary> /// <param name="dirs"></param> /// <param name="testSymbols"></param> /// <returns></returns> private static List <Designation> doTraining(List <string> dirs, out List <Sketch.Sketch> testSymbols) { string symbolType; List <Designation> designations = new List <Designation>(); testSymbols = new List <Sketch.Sketch>(dirs.Count); //For partial gate recog // List<Sketch.Sketch> nandGates = Congeal.Util.getSketches(m_NandDir, m_xmlPattern); foreach (string dir in dirs) { List <Sketch.Sketch> sketches = Congeal.Util.getSketches(dir, m_xmlPattern); //The 3rd sketch gets pulled out later as a testing sketch. List <Sketch.Sketch> two = new List <Sketch.Sketch>(); for (int i = 0; i < 7; i++) { two.Add(sketches[i]); } //sketches = two; //sketches.AddRange(nandGates); // List<Sketch.Sketch> sketches = Congeal.Util.getSketches(dir, "*.jnt"); //List<Bitmap> bitmaps = Util.getBitmaps(dir, m_bmPattern); //Get the name of the folder containing that set of training data //Which will usually serve as a decent name for the designation. symbolType = dir.Substring(dir.LastIndexOf('\\') + 1); //DEBUG // write input bitmaps to file List <Bitmap> bitmaps = Util.sketchToBitmap(64, 64, sketches); for (int i = 0; i < bitmaps.Count; i++) { Bitmap bm = new Bitmap(bitmaps[i], 128, 128); ImageTransform it = new ImageTransform(bm); it.writeImage(String.Format("inputs\\input_{0}{1}.bmp", symbolType, i)); } if (sketches != null && sketches.Count > 0) { //Pull out the last sketch for testing Sketch.Sketch s = sketches[sketches.Count - 1]; testSymbols.Add(s); sketches.RemoveAt(sketches.Count - 1); Designation d = new Congeal.Designation(width, height, sketches, symbolType); System.Console.WriteLine("training: " + symbolType); d.train(); designations.Add(d); } } return(designations); }
/// <summary> /// Console application entry point to write all of the training data. /// </summary> /// <param name="args">The arguments provided by the user at the console.</param> public static void Main(string[] args) { List <string> argArray = new List <string>(args); int numArgs = argArray.Count; string[] files; string pattern = "*.xml"; if (argArray.Contains("-p")) { int i = argArray.IndexOf("-p"); if (i + 1 >= argArray.Count) // Are we in range? { Console.Error.WriteLine("No pattern specified."); return; } else if (argArray[i + 1].StartsWith("-") || !argArray[i + 1].EndsWith(".xml")) { Console.Error.WriteLine("invalid pattern specified."); return; } else { pattern = argArray[i + 1]; } } // Show how to run the program if there are no arguments provided if (numArgs == 0) { Console.WriteLine("*****************************************************************"); Console.WriteLine("*** CreateSymbol.exe"); Console.WriteLine("*** by Sara Sheehan and Matthew Weiner"); Console.WriteLine("*** Harvey Mudd College, Claremont, CA 91711."); Console.WriteLine("*** Sketchers 2007"); Console.WriteLine("***"); Console.WriteLine("*** Usage: CreateSymbol.exe (-c | -d directory | -r)"); Console.WriteLine("*** Usage: CreateSymbol.exe input1.xml [input2.xml ...]"); Console.WriteLine("***"); Console.WriteLine("*** -c: convert all files in current directory"); Console.WriteLine("*** -d directory: convert all files in the specified directory"); Console.WriteLine("*** -r directory: recursively convert files from the specified directory"); Console.ReadLine(); return; } else if (argArray.Contains("-c")) // Convert everything in this directory { files = Directory.GetFiles(Directory.GetCurrentDirectory()); } else if (argArray.Contains("-d")) // Convert everything in specified directory { int index = argArray.IndexOf("-d"); if (index + 1 >= argArray.Count) // Are we in range? { Console.Error.WriteLine("No directory specified."); return; } else if (!Directory.Exists(argArray[index + 1])) // Does dir exist? { Console.Error.WriteLine("Directory doesn't exist."); return; } else { files = Directory.GetFiles(argArray[index + 1], "*.xml", SearchOption.TopDirectoryOnly); } } else if (argArray.Contains("-r")) //Recursive from current dir { int index = argArray.IndexOf("-r"); if (index + 1 >= argArray.Count) //Are we in range? { Console.Error.WriteLine("No directory specified."); return; } else if (!Directory.Exists(argArray[index + 1])) // Does dir exist? { Console.Error.WriteLine("Directory doesn't exist."); return; } else { files = Directory.GetFiles(argArray[index + 1], pattern, SearchOption.AllDirectories); } } else //Convert only the specified files { files = args; } foreach (string input in files) { //We know it ends with .xml from above, or if the user specified it, we should try to use it //if (Path.GetExtension(input) == ".xml") { // Get information about the filename/path string filename = Path.GetFileName(input); string[] split = filename.Split(new char[] { '.' }); string path = Path.GetFullPath(filename); string [] inputSplit = input.Split(new char[] { '\\' }); // Status printouts Console.WriteLine(filename); Console.WriteLine(input); Console.WriteLine(path); string newDirectory = ""; for (int i = 0; i < inputSplit.Length - 2; i++) { newDirectory += inputSplit[i] + "\\"; } // Run the training data creation on the current file if it is labeled if (split[1] == "labeled") { // Load the sketch Sketch.Sketch sketch = (new ReadXML(input)).Sketch; // Create a new sketch to manipulate Sketch.Sketch noContextSketch = new Sketch.Sketch(); // Make a new CreateSymbol object CreateSymbol createSymbol = new CreateSymbol(sketch); // Create a neighborhood for this sketch Neighborhood neighborhood = new Neighborhood(sketch); neighborhood.createGraph(ClosenessMeasure.EUCLIDIAN); // Run the training data creation functions createSymbol.noContext(input, split[0]); createSymbol.croppedContextForShape(neighborhood, newDirectory, split[0], inputSplit[inputSplit.Length - 2]); createSymbol.croppedContextForSymbol(neighborhood, input, split[0]); } } } }