// the main listener function protected void TcpServerWorkerListening(object sender, DoWorkEventArgs e) { //---listen at the specified IP and port no.--- const int portNo = 614; IPAddress serverIp = IPAddress.Parse("127.0.0.1"); if (_server == null) { _server = new TcpListener(serverIp, portNo); } try { _server.Start(); RhinoApp.WriteLine("VS Code Listener Started..."); } catch (Exception err) { RhinoApp.WriteLine(err.ToString()); } while (true) { // incoming client connected TcpClient client; try { client = _server.AcceptTcpClient(); } catch (Exception serverException) { return; } // get the incoming data through a network stream NetworkStream nwStream = client.GetStream(); byte[] buffer = new byte[client.ReceiveBufferSize]; // read incoming stream int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize); // convert the data received into a string StringBuilder msg = new StringBuilder(); // parse the buffer into msg foreach (var b in buffer) { if (b.Equals(00)) { break; } msg.Append(Convert.ToChar(b).ToString()); } // parse the received message into C# Object string msgString = msg.ToString(); msgString = Regex.Split(msgString, "}")[0] + "}"; MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(msgString)); DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(msgObject)); msgObject msgObj; try { msgObj = ser.ReadObject(ms) as msgObject; } catch (Exception ex) { RhinoApp.WriteLine("Received invalid data, please try again."); return; } ms.Close(); // invoke the main task in the main thread Application.Current.Dispatcher.Invoke(() => { // create python script runner PythonScript myScript = PythonScript.Create(); // redirect output to _output field myScript.Output = PrintToVSCode; FeedbackSender feedbackSender = new FeedbackSender(nwStream); GotCodeFeekBack += feedbackSender.OnGotCodeFeedBack; // if flagged reset, then reset the script engine. if (msgObj.reset) { ResetScriptEngine.ResetEngine(); } // if it is not a temp folder, add the folder to python library path if (!msgObj.temp) { string pythonFilePath = Path.GetDirectoryName(msgObj.filename); string code = string.Format("import sys\nimport os\nif \"{0}\" not in sys.path: sys.path.append(\"{0}\")", pythonFilePath); try { myScript.ExecuteScript(code); } catch (Exception exception) { PrintToVSCode(exception.Message); } } // determines if run actual script if (msgObj.run) { uint sn = _idoc.BeginUndoRecord("VS Code execution"); var sn_start = RhinoObject.NextRuntimeSerialNumber; try { if (msgObj.minimize) { Utils.MinimizeVSCodeWindow(); } myScript.ExecuteFile(msgObj.filename); } catch (Exception ex) { // get the exception message var error = myScript.GetStackTraceFromException(ex); string message = ex.Message + "\n" + error; // send exception msg back to VS Code PrintToVSCode(message); } finally { CloseConnection(nwStream); _idoc.EndUndoRecord(sn); if (msgObj.minimize) { Utils.RestoreVSCodeWindow(); } // fix the rs.Prompt bug RhinoApp.SetCommandPrompt("Command"); // select created objects var sn_end = RhinoObject.NextRuntimeSerialNumber; if (sn_end > sn_start) { for (var i = sn_start; i < sn_end; i++) { var obj = _idoc.Objects.Find(i); if (null != obj) { obj.Select(true); } } } // enable the view _idoc.Views.RedrawEnabled = true; } } else { CloseConnection(nwStream); } }); } }
protected override Result RunCommand(RhinoDoc doc, RunMode mode) { var pack_algorithm = PackingAlgorithm.Fast; Point3d base_point = new Point3d(); var option_count = new OptionInteger(100, true, 2); var option_min_radius = new OptionDouble(0.1, true, 0.001); var option_max_radius = new OptionDouble(1.0, true, 0.001); var option_iterations = new OptionInteger(10000, false, 100); bool done_looping = false; while (!done_looping) { var gp = new GetPoint(); gp.SetCommandPrompt("Center of fitting solution"); gp.AddOptionInteger("Count", ref option_count); gp.AddOptionDouble("MinRadius", ref option_min_radius); gp.AddOptionDouble("MaxRadius", ref option_max_radius); gp.AddOptionInteger("IterationLimit", ref option_iterations); int index_option_packing = gp.AddOption("Packing", pack_algorithm.ToString()); gp.AcceptNumber(true, true); switch (gp.Get()) { case GetResult.Point: base_point = gp.Point(); done_looping = true; break; case GetResult.Option: if (index_option_packing == gp.OptionIndex()) { var get_algorithm = new GetOption(); get_algorithm.SetCommandPrompt("Packing"); get_algorithm.SetDefaultString(pack_algorithm.ToString()); var opts = new string[] { "Fast", "Double", "Random", "Simple" }; int current_index = 0; switch (pack_algorithm) { case PackingAlgorithm.Fast: current_index = 0; break; case PackingAlgorithm.Double: current_index = 1; break; case PackingAlgorithm.Random: current_index = 2; break; case PackingAlgorithm.Simple: current_index = 3; break; } int index_list = get_algorithm.AddOptionList("algorithm", opts, current_index); get_algorithm.AddOption("Help"); while (get_algorithm.Get() == GetResult.Option) { if (index_list == get_algorithm.OptionIndex()) { int index = get_algorithm.Option().CurrentListOptionIndex; if (0 == index) { pack_algorithm = PackingAlgorithm.Fast; } if (1 == index) { pack_algorithm = PackingAlgorithm.Double; } if (2 == index) { pack_algorithm = PackingAlgorithm.Simple; } if (3 == index) { pack_algorithm = PackingAlgorithm.Random; } break; } // if we get here, the user selected help const string help = @"Fast: fast packing prevents collisions by moving one circle away from all its intersectors. After every collision iteration, all circles are moved towards the centre of the packing to reduce the amount of wasted space. Collision detection proceeds from the center outwards. Double: similar to Fast, except that both circles are moved in case of a collision. Random: similar to Fast, except that collision detection is randomized rather than sorted. Simple: similar to Fast, but without a contraction pass after every collision iteration."; Rhino.UI.Dialogs.ShowMessageBox(help, "Packing algorithm description", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information); } } break; default: return(Result.Cancel); } } int count = option_count.CurrentValue; double min_radius = option_min_radius.CurrentValue; double max_radius = option_max_radius.CurrentValue; int iterations = option_iterations.CurrentValue; // TODO: try setting up a background worker thread and // communicate with the GetString through messages //GetString gs = new GetString(); //gs.SetCommandPrompt("Press escape to cancel"); using (var all_circles = new PackCircles(base_point, count, min_radius, max_radius)) { double damping = 0.1; for (int i = 1; i <= iterations; i++) { RhinoApp.SetCommandPrompt(string.Format("Performing circle packing iteration {0}... (Press Shift+Ctrl to abort)", i)); if (System.Windows.Forms.Control.ModifierKeys == (System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift)) { RhinoApp.WriteLine("Circle fitting process aborted at iteration {0}...", i); break; } if (!all_circles.Pack(pack_algorithm, damping, doc.ModelAbsoluteTolerance)) { RhinoApp.WriteLine("Circle fitting process completed at iteration {0}...", i); break; } damping *= 0.98; doc.Views.Redraw(); RhinoApp.Wait(); } all_circles.Add(doc); } doc.Views.Redraw(); return(Result.Success); }