/// <summary> /// RunCommand /// </summary> protected override Result RunCommand(RhinoDoc doc, RunMode mode) { Tolerance = doc.ModelAbsoluteTolerance; // Get persistent settings var settings = Settings; var radius = settings.GetDouble("Radius", RADIUS); var cut_type = settings.GetEnumValue("CutType", CUTTYPE); // Select closed,planar curve var go = new GetClosedPlanarPolyline(Tolerance); go.SetCommandPrompt("Select closed, planar polyline"); go.Get(); if (go.CommandResult() != Result.Success) { return(go.CommandResult()); } // Get curve var obj_ref = go.Object(0); var curve = obj_ref.Curve(); if (null == curve || !curve.IsClosed || !curve.IsPlanar()) { return(Result.Failure); } // Get polyline Polyline polyline; if (!curve.TryGetPolyline(out polyline)) { return(Result.Failure); } // Since first and last point are the same, remove the last point. polyline.RemoveAt(polyline.Count - 1); // Get curve plane Plane plane; if (!curve.TryGetPlane(out plane, Tolerance)) { return(Result.Failure); } // Get corner point indices var indices = FindInnerCornerPoints(curve, polyline, plane); if (0 == indices.Length) { RhinoApp.WriteLine("No inner corners found."); return(Result.Nothing); } // Show preview conduit var conduit = new SampleCsOverCutConduit { Circles = CalculateCuttingCircles(curve, polyline, indices, plane, radius, cut_type), Enabled = true }; doc.Views.Redraw(); Result rc; // Choose overcut options var gp = new GetOption(); gp.SetCommandPrompt("Choose overcut option"); gp.AcceptNothing(true); for (;;) { gp.ClearCommandOptions(); var cut_type_index = gp.AddOptionEnumList("CutType", cut_type); var radius_option = new OptionDouble(radius, true, Tolerance); var radius_index = gp.AddOptionDouble("Radius", ref radius_option); var res = gp.Get(); if (res == GetResult.Option) { var option = gp.Option(); if (null != option) { if (option.Index == cut_type_index) { var list = Enum.GetValues(typeof(CutType)).Cast <CutType>().ToList(); cut_type = list[option.CurrentListOptionIndex]; } else if (option.Index == radius_index) { radius = radius_option.CurrentValue; } conduit.Circles = CalculateCuttingCircles(curve, polyline, indices, plane, radius, cut_type); doc.Views.Redraw(); } continue; } if (res == GetResult.Nothing) { rc = Result.Success; break; } rc = Result.Cancel; break; } conduit.Enabled = false; if (rc == Result.Success) { // Try differencing circles from curve var success = true; var new_curve = curve; for (var i = 0; i < conduit.Circles.Count && success; i++) { var new_curves = Curve.CreateBooleanDifference(new_curve, new ArcCurve(conduit.Circles[i]), doc.ModelAbsoluteTolerance); if (1 == new_curves.Length && null != new_curves[0]) { new_curve = new_curves[0]; } else { success = false; } } // Add geometry to document if (success && null != new_curve) { doc.Objects.Replace(obj_ref, new_curve); } else { for (var i = 0; i < conduit.Circles.Count; i++) { doc.Objects.AddCircle(conduit.Circles[i]); } } // Set persistent settings settings.SetDouble("Radius", radius); settings.SetEnumValue("CutType", cut_type); } doc.Views.Redraw(); return(rc); }
protected override Result RunCommand(RhinoDoc doc, RunMode mode) { Rhino.Input.Custom.GetOption go = new GetOption(); go.SetCommandPrompt("Set Faro scan settings"); Rhino.Input.Custom.GetString gs = new GetString(); gs.SetCommandPrompt("Set Faro IP address."); gs.SetDefaultString("127.0.0.1"); gs.AddOption("Scanner IP"); gs.Get(); string val = gs.StringResult(); Rhino.RhinoApp.WriteLine("IP: " + val); // set up the options Rhino.Input.Custom.OptionInteger intOption = new Rhino.Input.Custom.OptionInteger(1, 1, 99); Rhino.Input.Custom.OptionDouble dblOption = new Rhino.Input.Custom.OptionDouble(2.2, 0, 99.9); Rhino.Input.Custom.OptionToggle boolOption = new Rhino.Input.Custom.OptionToggle(true, "Off", "On"); string[] resolutionValues = new string[] { "Full", "Half", "Quarter", "Eighth", "Sixsteenth" }; string[] measurementValues = new string[] { "Low", "Medium", "High" }; string[] noiseValues = new string[] { "Low", "Medium", "High" }; go.AddOptionInteger("Integer", ref intOption); go.AddOptionDouble("Double", ref dblOption); go.AddOptionToggle("Boolean", ref boolOption); int resolutionIndex = 2; int measurementIndex = 1; int noiseIndex = 1; int resolutionList = go.AddOptionList("Resolution", resolutionValues, resolutionIndex); int measurementList = go.AddOptionList("MeasurementRate", measurementValues, measurementIndex); int noiseList = go.AddOptionList("NoiseCompression", noiseValues, noiseIndex); while (true) { // perform the get operation. This will prompt the user to input a point, but also // allow for command line options defined above Rhino.Input.GetResult get_rc = go.Get(); Rhino.RhinoApp.WriteLine(get_rc.ToString()); if (go.CommandResult() != Rhino.Commands.Result.Success) { return(go.CommandResult()); } if (get_rc == Rhino.Input.GetResult.Nothing) { //doc.Objects.AddPoint(go.Point()); doc.Views.Redraw(); Rhino.RhinoApp.WriteLine("Command line option values are"); Rhino.RhinoApp.WriteLine(" Integer = {0}", intOption.CurrentValue); Rhino.RhinoApp.WriteLine(" Double = {0}", dblOption.CurrentValue); Rhino.RhinoApp.WriteLine(" Boolean = {0}", boolOption.CurrentValue); Rhino.RhinoApp.WriteLine(" Measurement rate = {0}", measurementValues[measurementIndex]); Rhino.RhinoApp.WriteLine(" Resolution = {0}", resolutionValues[resolutionIndex]); } else if (get_rc == Rhino.Input.GetResult.Option) { if (go.OptionIndex() == resolutionList) { resolutionIndex = go.Option().CurrentListOptionIndex; } else if (go.OptionIndex() == measurementList) { measurementIndex = go.Option().CurrentListOptionIndex; } continue; } break; } return(Rhino.Commands.Result.Success); }
protected override Result RunCommand(RhinoDoc doc, RunMode mode) { int counter = 0; GetObject go = new GetObject(); go.SetCommandPrompt("Select curves to offset."); go.GeometryFilter = Rhino.DocObjects.ObjectType.Curve; go.GroupSelect = true; go.SubObjectSelect = true; go.DeselectAllBeforePostSelect = true; go.OneByOnePostSelect = false; go.GetMultiple(1, 0); GetOption gop = new GetOption(); var dist = new Rhino.Input.Custom.OptionDouble(distVal); gop.SetCommandPrompt("Set values. Press enter when done."); gop.AddOptionDouble("Distance", ref dist); int optList = gop.AddOptionList("CornerStyle", corners, cornerIndex); gop.AcceptNothing(true); while (true) { if (gop.Get() == GetResult.Nothing) { break; } else if (gop.OptionIndex() == optList) { cornerIndex = gop.Option().CurrentListOptionIndex; } else { distVal = dist.CurrentValue; } } for (int i = 0; i < go.ObjectCount; i++) { Rhino.DocObjects.ObjRef objref = go.Object(i); var curve = objref.Curve(); if (curve == null) { return(Result.Nothing); } Plane plane; if (!curve.TryGetPlane(out plane)) { curve.DivideByCount(3, true, out Point3d[] curvePoints); plane = new Plane(curvePoints[0], curvePoints[1], curvePoints[2]); } try { var curves = curve.Offset(plane, distVal, doc.ModelAbsoluteTolerance, cornerStyle[cornerIndex]); foreach (var offsetcurve in curves) { doc.Objects.AddCurve(offsetcurve); } } catch { counter++; } } if (counter > 0) { RhinoApp.WriteLine(counter + " out of " + go.ObjectCount + " offset values were out of scope!"); } doc.Views.Redraw(); // --- return(Result.Success); }
protected override Result RunCommand(RhinoDoc doc, RunMode mode) { double tolerance = doc.ModelAbsoluteTolerance; List <Curve> curves = new List <Curve>(); //Select surface GetObject gs = new Rhino.Input.Custom.GetObject(); gs.SetCommandPrompt("Surface to orient on"); gs.GeometryFilter = Rhino.DocObjects.ObjectType.Surface; gs.SubObjectSelect = true; gs.DeselectAllBeforePostSelect = true; gs.OneByOnePostSelect = true; gs.Get(); if (gs.CommandResult() != Result.Success) { return(gs.CommandResult()); } Rhino.DocObjects.ObjRef objref_Surface = gs.Object(0); Rhino.DocObjects.RhinoObject obj = objref_Surface.Object(); if (obj == null) { return(Result.Failure); } surface = objref_Surface.Surface(); if (surface == null) { return(Result.Failure); } obj.Select(false); //Select Line(s) GetObject gl = new GetObject(); gl.SetCommandPrompt("Select one or two line(s)"); gl.GeometryFilter = Rhino.DocObjects.ObjectType.Curve; gl.DeselectAllBeforePostSelect = true; gl.OneByOnePostSelect = true; gl.GetMultiple(1, 0); for (int i = 0; i < gl.ObjectCount; i++) { Rhino.DocObjects.ObjRef objref_Line = gl.Object(i); curve = objref_Line.Curve(); Curve curveRe = curve.Rebuild(60, 3, true); curves.Add(curveRe); } List <Guid> cir_guid_list = new List <Guid>(); if (curves.Count > 1) { Curve curve2 = curves[0]; Curve curve3 = curves[1]; if (curve2.IsClosed || curve3.IsClosed) { Rhino.UI.Dialogs.ShowMessage("Please only select open curves for two line pave.", "Warning!"); return(Result.Failure); } while (true) { cir_guid_list = new List <Guid>(); var tweenCurves = Curve.CreateTweenCurvesWithSampling(curve2, curve3, 1, 30, tolerance); Curve tCurve = tweenCurves[0]; //3 point circle Point3d po1 = curve2.PointAtStart; Point3d po2 = curve3.PointAtStart; LineCurve line1 = new LineCurve(po1, po2); double[] param = line1.DivideByCount(2, false); double param1 = param[0]; double param2 = param[0]; double param3 = param[0]; Curve curve1 = line1; while (true) { Circle outCircle = Circle.TryFitCircleTTT(curve1, curve2, curve3, param1, param2, param3); //circle normal to surface Point3d outCircleCenter = outCircle.Center; double outCircleRadius = outCircle.Radius; double u, v; surface.ClosestPoint(outCircleCenter, out u, out v); var direction = surface.NormalAt(u, v); Point3d surfCenter = surface.PointAt(u, v); Plane pl1 = new Plane(surfCenter, direction); Circle circle = new Circle(pl1, surfCenter, outCircleRadius - offSetStone); Circle circleDist = new Circle(pl1, surfCenter, outCircleRadius + stoneDist); Guid cir_guid = doc.Objects.AddCircle(circle); cir_guid_list.Add(cir_guid); //Cut tween curve at latest circle center Point3d pointOnCurve; Point3d pointOnCircle; Curve circleDistCurve = circleDist.ToNurbsCurve(); tCurve.Domain = new Interval(0, tCurve.GetLength()); Curve[] splitCurves = tCurve.Split(outCircleRadius); if (splitCurves is null) { break; } tCurve = splitCurves[splitCurves.Length - 1]; tCurve.ClosestPoints(circleDistCurve, out pointOnCurve, out pointOnCircle); //Cut tween curve at latest circle border double curveSplitParam; tCurve.Domain = new Interval(0, tCurve.GetLength()); tCurve.ClosestPoint(pointOnCurve, out curveSplitParam); splitCurves = tCurve.Split(curveSplitParam); if (splitCurves is null) { break; } tCurve = splitCurves[splitCurves.Length - 1]; //New parameter at curve1 double circleParam; circleDistCurve.ClosestPoint(pointOnCircle, out circleParam); param1 = circleParam; curve1 = circleDistCurve; //New parameter at curves[0] double paramCurve0New; curve2.ClosestPoint(pointOnCircle, out paramCurve0New); Point3d pointCurve0New = curve2.PointAt(paramCurve0New); double distNewPoints0 = pointOnCircle.DistanceTo(pointCurve0New); param2 = paramCurve0New + distNewPoints0; //New parameter at curves[1] double paramCurve1New; curve3.ClosestPoint(pointOnCircle, out paramCurve1New); Point3d pointCurve1New = curve3.PointAt(paramCurve1New); double distNewPoints1 = pointOnCircle.DistanceTo(pointCurve1New); param3 = paramCurve1New + distNewPoints1; } doc.Views.Redraw(); //Options var go = new GetOption(); go.SetCommandPrompt("Set options."); var stoneOff = new Rhino.Input.Custom.OptionDouble(offSetStone); var distStone = new Rhino.Input.Custom.OptionDouble(stoneDist); var boolOption = new Rhino.Input.Custom.OptionToggle(false, "Off", "On"); go.AddOptionDouble("Offset", ref stoneOff); go.AddOptionDouble("Distance", ref distStone); go.AddOptionToggle("Reverse", ref boolOption); go.AcceptNothing(true); var res = go.Get(); if (res == GetResult.Nothing) { break; } if (res == GetResult.Cancel) { break; } foreach (var gui in cir_guid_list) { var gu = doc.Objects.Find(gui); doc.Objects.Delete(gu); } offSetStone = stoneOff.CurrentValue; stoneDist = distStone.CurrentValue; optionBool = boolOption.CurrentValue; if (optionBool == true) { curve2.Reverse(); curve2 = curve2.Rebuild(60, 3, false); curve3.Reverse(); curve3 = curve3.Rebuild(60, 3, false); optionBool = false; } } } else { while (true) { cir_guid_list = new List <Guid>(); List <Point3d> points = new List <Point3d>(); double length = (diamStone / 2) + offSetStone; double crv_length = curve.GetLength(); Point3d point = curve.PointAtLength(length); points.Add(point); while (true) { length += diamStone + offSetStone; if (length > crv_length) { break; } point = curve.PointAtLength(length); points.Add(point); } foreach (var poi in points) { double u, v; surface.ClosestPoint(poi, out u, out v); var direction = surface.NormalAt(u, v); double x = direction.X; double y = direction.Y; double z = direction.Z; Vector3d vt1 = new Vector3d(x, y, z); Plane pl1 = new Plane(poi, vt1); Circle circle = new Circle(pl1, poi, diamStone / 2); Guid cir_guid = doc.Objects.AddCircle(circle); cir_guid_list.Add(cir_guid); } doc.Views.Redraw(); //Options var go = new GetOption(); go.SetCommandPrompt("Set options."); var stoneDiam = new Rhino.Input.Custom.OptionDouble(diamStone); var stoneOff = new Rhino.Input.Custom.OptionDouble(offSetStone); var boolOption = new Rhino.Input.Custom.OptionToggle(false, "Off", "On"); go.AddOptionDouble("StoneDiam", ref stoneDiam); go.AddOptionDouble("Offset", ref stoneOff); go.AddOptionToggle("Reverse", ref boolOption); go.AcceptNothing(true); var res = go.Get(); if (res == GetResult.Nothing) { break; } if (res == GetResult.Cancel) { break; } foreach (var gui in cir_guid_list) { var gu = doc.Objects.Find(gui); doc.Objects.Delete(gu); } diamStone = stoneDiam.CurrentValue; offSetStone = stoneOff.CurrentValue; optionBool = boolOption.CurrentValue; if (optionBool == true) { curve.Reverse(); } } } doc.Views.Redraw(); doc.Groups.Add(cir_guid_list); return(Result.Success); }
/// <summary> /// Command.RunCommand override /// </summary> protected override Result RunCommand(RhinoDoc doc, RunMode mode) { Potrace.Clear(); // Prompt the user for the name of the image file to vectorize. string path = GetImageFileName(mode); if (string.IsNullOrEmpty(path)) { return(Result.Cancel); } // Creates a bitmap from the specified file. var bitmap = Image.FromFile(path) as Bitmap; if (null == bitmap) { RhinoApp.WriteLine("The specified file cannot be identifed as a supported type."); return(Result.Failure); } // Verify bitmap size if (0 == bitmap.Width || 0 == bitmap.Height) { RhinoApp.WriteLine("Error reading the specified file."); return(Result.Failure); } // Calculate scale factor so curves of a reasonable size are added to Rhino var unit_scale = (doc.ModelUnitSystem != UnitSystem.Inches) ? RhinoMath.UnitScale(UnitSystem.Inches, doc.ModelUnitSystem) : 1.0; var scale = (double)(1.0 / bitmap.HorizontalResolution * unit_scale); // I'm not convinced this is useful... if (true) { var format = $"F{doc.DistanceDisplayPrecision}"; // Print image size in pixels RhinoApp.WriteLine("Image size in pixels: {0} x {1}", bitmap.Width, bitmap.Height ); // Print image size in inches var width = (double)(bitmap.Width / bitmap.HorizontalResolution); var height = (double)(bitmap.Height / bitmap.VerticalResolution); RhinoApp.WriteLine("Image size in inches: {0} x {1}", width.ToString(format, CultureInfo.InvariantCulture), height.ToString(format, CultureInfo.InvariantCulture) ); // Image size in in model units, if needed if (doc.ModelUnitSystem != UnitSystem.Inches) { width = (double)(bitmap.Width / bitmap.HorizontalResolution * unit_scale); height = (double)(bitmap.Height / bitmap.VerticalResolution * unit_scale); RhinoApp.WriteLine("Image size in {0}: {1} x {2}", doc.ModelUnitSystem.ToString().ToLower(), width.ToString(format, CultureInfo.InvariantCulture), height.ToString(format, CultureInfo.InvariantCulture) ); } } // Convert the bitmap to an Eto bitmap var eto_bitmap = ConvertBitmapToEto(bitmap); if (null == eto_bitmap) { RhinoApp.WriteLine("Unable to convert image to Eto bitmap."); return(Result.Failure); } // 12-Jan-2021 Dale Fugier // This should prevent Eto.Drawing.BitmapData.GetPixels() from throwing an exception if (!IsCompatibleBitmap(eto_bitmap)) { RhinoApp.WriteLine("The image has an incompatible pixel format. Please select an image with 24 or 32 bits per pixel, or 8 bit indexed."); return(Result.Failure); } // This bitmap is not needed anymore, so dispose of it bitmap.Dispose(); // Gets the Potrace settings from the plug-in settings file GetPotraceSettings(); // Create the conduit, which does most of the work var conduit = new VectorizeConduit( eto_bitmap, scale, doc.ModelAbsoluteTolerance, m_select_output ? Rhino.ApplicationSettings.AppearanceSettings.SelectedObjectColor : doc.Layers.CurrentLayer.Color ) { Enabled = true }; if (mode == RunMode.Interactive) { // Show the interactive dialog box var dialog = new VectorizeDialog(doc, conduit); dialog.RestorePosition(); var result = dialog.ShowSemiModal(doc, RhinoEtoApp.MainWindow); dialog.SavePosition(); if (result != Result.Success) { conduit.Enabled = false; Potrace.Clear(); doc.Views.Redraw(); return(Result.Cancel); } } else { // Show the command line options var go = new GetOption(); go.SetCommandPrompt("Vectorization options. Press Enter when done"); go.AcceptNothing(true); while (true) { conduit.TraceBitmap(); doc.Views.Redraw(); go.ClearCommandOptions(); // IgnoreArea var turdsize_opt = new OptionInteger(Potrace.turdsize, 2, 100); var turdsize_idx = go.AddOptionInteger("FilterSize", ref turdsize_opt, "Filter speckles of up to this size in pixels"); // TurnPolicy var turnpolicy_idx = go.AddOptionEnumList("TurnPolicy", Potrace.turnpolicy); // Optimizing var curveoptimizing_opt = new OptionToggle(Potrace.curveoptimizing, "No", "Yes"); var curveoptimizing_idx = go.AddOptionToggle("Optimizing", ref curveoptimizing_opt); // Tolerance var opttolerance_opt = new OptionDouble(Potrace.opttolerance, 0.0, 1.0); var opttolerance_idx = go.AddOptionDouble("Tolerance", ref opttolerance_opt, "Optimizing tolerance"); // CornerThreshold var alphamax_opt = new OptionDouble(Potrace.alphamax, 0.0, 100.0); var alphamax_idx = go.AddOptionDouble("CornerRounding", ref alphamax_opt, "Corner rounding threshold"); // Threshold var threshold_opt = new OptionDouble(Potrace.Treshold, 0.0, 100.0); var threshold_idx = go.AddOptionDouble("Threshold", ref threshold_opt, "Threshold"); // RestoreDefaults var defaults_idx = go.AddOption("RestoreDefaults"); var res = go.Get(); if (res == GetResult.Option) { var option = go.Option(); if (null != option) { if (turdsize_idx == option.Index) { Potrace.turdsize = turdsize_opt.CurrentValue; } if (turnpolicy_idx == option.Index) { var list = Enum.GetValues(typeof(TurnPolicy)).Cast <TurnPolicy>().ToList(); Potrace.turnpolicy = list[option.CurrentListOptionIndex]; } if (curveoptimizing_idx == option.Index) { Potrace.curveoptimizing = curveoptimizing_opt.CurrentValue; } if (opttolerance_idx == option.Index) { Potrace.opttolerance = opttolerance_opt.CurrentValue; } if (alphamax_idx == option.Index) { Potrace.alphamax = alphamax_opt.CurrentValue; } if (threshold_idx == option.Index) { Potrace.Treshold = threshold_opt.CurrentValue; } if (defaults_idx == option.Index) { Potrace.RestoreDefaults(); } } continue; } if (res != GetResult.Nothing) { conduit.Enabled = false; doc.Views.Redraw(); Potrace.Clear(); return(Result.Cancel); } break; } } // Group curves var attributes = doc.CreateDefaultAttributes(); attributes.AddToGroup(doc.Groups.Add()); for (var i = 0; i < conduit.OutlineCurves.Count; i++) { var rhobj_id = doc.Objects.AddCurve(conduit.OutlineCurves[i], attributes); if (m_select_output) { var rhobj = doc.Objects.Find(rhobj_id); if (null != rhobj) { rhobj.Select(true); } } } conduit.Enabled = false; Potrace.Clear(); doc.Views.Redraw(); // Set the Potrace settings to the plug -in settings file. SetPotraceSettings(); return(Result.Success); }
protected override Result RunCommand(RhinoDoc doc, RunMode mode) { var primal = new PFoam(); var dual = new PFoam(); ContainerType container; try { var guids = LoadData.LoadPrimalDual(out primal, out dual, out container); if (dual.Cells.Count < 1) { RhinoApp.WriteLine("No dual data retrieved from the container!"); return(Result.Failure); } // Primal ( the perping geometry ) // load the foam from the geometry option to update from the geometry if any changes occured // select the structure to be perped - if dual not present raise error // show a set of options // Max steps 10 000 // maximum deviation in degrees from dual direction // Update dual data from geometry // set edge legth constraint // set point position constraint var averageLen = primal.Edges.Select(x => x.GetLength()).Average(); var getOptions = new GetOption(); getOptions.SetDefaultString("enter"); getOptions.SetCommandPrompt("Set max number of steps and perping options"); var optionSteps = new OptionInteger(1000, true, 0); var optionMaxDev = new OptionDouble(0.1, 0.0, 10.0); var optionMinLen = new OptionDouble(averageLen / 4, true, averageLen / 100); var optionSetEdge = new OptionToggle(false, "setE", "E_set"); var optionSetVert = new OptionToggle(false, "setV", "V_set"); var optionSetDualGeo = new OptionToggle(false, "setG", "G_set"); var storedSteps = 1000.0; var storedMaxDev = 0.1; var storedMinLen = averageLen / 4; bool storedEdgeSet = false; bool storedVertSet = false; bool storedDualGeoSet = false; getOptions.AddOptionInteger("MaxIterations", ref optionSteps); getOptions.AddOptionDouble("MaxDeviation", ref optionMaxDev); getOptions.AddOptionDouble("MinEdgeLenght", ref optionMinLen); getOptions.AddOptionToggle("SetEdgeLen", ref optionSetEdge); getOptions.AddOptionToggle("SetVertPos", ref optionSetVert); getOptions.AddOptionToggle("UpdatePrimalGeo", ref optionSetDualGeo); while (true) { var preres = getOptions.Get(); var res = getOptions.CommandResult(); //var numres = getOptions. if (res == Result.Success) { if (optionSetEdge.CurrentValue != storedEdgeSet) { primal.PickEdges(); } if (optionSetVert.CurrentValue != storedVertSet) { primal.PickVertex(); } if (optionSetDualGeo.CurrentValue != storedDualGeoSet) { var updatedDual = new PFoam(); LoadData.LoadPrimalDual(out updatedDual, out PFoam notUsedPrimal, out ContainerType dummyContainer, false); // get the container geometry from a dual from the document // check to see if the id matches // load the point geometry, centroids, meshes and update data in the dual // transform the primal/dual getter into a method to reuse it more easily if (updatedDual.Dual.Id == primal.Id) { dual = updatedDual; Util.ConnectDuals(ref primal, ref updatedDual); } } if (optionSetEdge.CurrentValue == storedEdgeSet && optionSetVert.CurrentValue == storedVertSet && optionSetDualGeo.CurrentValue == storedDualGeoSet && optionSteps.CurrentValue == storedSteps && optionMaxDev.CurrentValue == storedMaxDev && optionMinLen.CurrentValue == storedMinLen ) { break; } storedEdgeSet = optionSetEdge.CurrentValue; storedVertSet = optionSetVert.CurrentValue; storedDualGeoSet = optionSetDualGeo.CurrentValue; storedSteps = optionSteps.CurrentValue; storedMaxDev = optionMaxDev.CurrentValue; storedMinLen = optionMinLen.CurrentValue; } else { return(Result.Cancel); } } //Util.ConnectDuals(ref primal, ref dual); foreach (var edge in primal.Edges) { edge.MinLength = optionMinLen.CurrentValue; } // delete the input objects doc.Objects.Delete(guids, true); primal.PerpSoft(optionSteps.CurrentValue, optionMaxDev.CurrentValue / 180 * Math.PI); //primal.ParaPerp(optionSteps.CurrentValue, 0, optionMaxDev.CurrentValue / 180 * Math.PI, null, 1); primal.Show(true, true, false); var pepedPrimalJsonString = primal.SerializeJson(); if (!primal.SaveToDocument(container)) { primal.Hide(); return(Result.Cancel); } primal.Hide(); return(Result.Success); } catch (PolyFrameworkException pfE) { RhinoApp.WriteLine(pfE.Message); primal.Hide(); dual.Hide(); return(Result.Failure); } // TODO: complete command. }
protected override Result RunCommand(RhinoDoc doc, RunMode mode) { var ptPuffynessOption = new OptionToggle(m_PointPuffyness, "False", "True"); var ptOffsetOption = new OptionDouble(m_PuffynessOffset, 0.5, double.PositiveInfinity); var ptBorderPuffynessOption = new OptionToggle(m_BorderPuffyness, "False", "True"); var borderOffsetOption = new OptionDouble(m_BorderOffset, 0.5, double.PositiveInfinity); var go = new GetOption(); go.SetCommandPrompt("Get meshing properties"); go.AcceptNothing(true); go.AcceptEnterWhenDone(true); int ptPuffyOptionIndex = go.AddOptionToggle("PointPuffyness", ref ptPuffynessOption); int offsetOptionIndex = go.AddOptionDouble("OffsetPtPuffy", ref ptOffsetOption); int borderPuffyOptionIndex = go.AddOptionToggle("BorderPuffyness", ref ptBorderPuffynessOption); int borderOffsetOptionIndex = go.AddOptionDouble("OffsetBorderPuffy", ref borderOffsetOption); go.Get(); var result = go.Result(); while (result != GetResult.Nothing) { if (result == GetResult.Cancel) { return(Result.Cancel); } int optionIdx = go.OptionIndex(); if (optionIdx == ptPuffyOptionIndex) { m_PointPuffyness = ptPuffynessOption.CurrentValue; } else if (optionIdx == offsetOptionIndex) { m_PuffynessOffset = ptOffsetOption.CurrentValue; } else if (optionIdx == borderPuffyOptionIndex) { m_BorderPuffyness = ptBorderPuffynessOption.CurrentValue; } else if (optionIdx == borderOffsetOptionIndex) { m_BorderOffset = borderOffsetOption.CurrentValue; } result = go.Get(); } ObjRef[] rhObjects; var res = RhinoGet.GetMultipleObjects("Select planar curves and Weight points", false, Rhino.DocObjects.ObjectType.Curve | Rhino.DocObjects.ObjectType.Point, out rhObjects); if (res == Result.Success) { // 1. subdive in sets: Closed curves, Opened Curves, weight points; List <Curve> closed_crvs = new List <Curve>(); List <Curve> opened_crvs = new List <Curve>(); List <Point> weight_points = new List <Point>(); bool puffyness = m_PointPuffyness; double offset = m_PuffynessOffset; bool border_puffyness = m_BorderPuffyness; double border_offset = m_BorderOffset; foreach (var ref_obj in rhObjects) { RhinoObject obj = ref_obj.Object(); if (obj.Geometry is Curve) { var crv = obj.Geometry as Curve; if (crv.IsPlanar()) { if (crv.IsClosed) { closed_crvs.Add(crv); } else { opened_crvs.Add(crv); } } } else if (obj.Geometry is Point) { weight_points.Add(obj.Geometry as Point); } } double space = 1; // 2. Insert curves into mesh AM_Region region = null; Curve border_outer_crv = null; Curve offset_outer_crv = null; if (closed_crvs.Count > 0) { region = new AM_Region(); for (int i = 0; i < closed_crvs.Count; i++) { var crv = closed_crvs[i]; region.AddCurve(crv, space, false); AreaMassProperties area = AreaMassProperties.Compute(crv, AM_Util.FLT_EPSILON); if (area.Area > 0 && border_puffyness) { if (border_outer_crv == null) { border_outer_crv = crv; } var offset_Crvs = crv.Offset(Plane.WorldXY, -border_offset, AM_Util.FLT_EPSILON, CurveOffsetCornerStyle.None); foreach (var c in offset_Crvs) { c.Reverse(); doc.Objects.AddCurve(c); offset_outer_crv = c; region.AddCurve(c, space, true); } } } } else { // TODO Debug.Assert(false); return(Result.Failure); } for (int i = 0; i < weight_points.Count; i++) { var pt = weight_points[i]; region.AddWeigthPoint(pt, space / 2); if (puffyness && offset > 0) { var circle = new ArcCurve(new Circle(pt.Location, offset)); var nurbs = circle.ToNurbsCurve(); region.AddCurve(nurbs, space / 2, true); } } for (int i = 0; i < opened_crvs.Count; i++) { var crv = opened_crvs[i]; region.AddCurve(crv, space, false); if (puffyness && offset > 0) { var n = Vector3d.CrossProduct(crv.TangentAtStart, Vector3d.ZAxis); Curve[] offsetCrv = crv.Offset(crv.PointAtStart + offset * n, Vector3d.ZAxis, offset, AM_Util.FLT_EPSILON, CurveOffsetCornerStyle.Round); foreach (var c in offsetCrv) { doc.Objects.AddCurve(c); region.AddCurve(crv, space, false); } Curve[] offsetCrv2 = crv.Offset(crv.PointAtStart - offset * n, Vector3d.ZAxis, offset, AM_Util.FLT_EPSILON, CurveOffsetCornerStyle.Round); foreach (var c in offsetCrv2) { doc.Objects.AddCurve(c); region.AddCurve(crv, space, false); } } } // 3. Mesh della regione if (region != null) { if (region.BuildMesh()) { // Inserisce i punti del contorno foreach (var loop in region.Loops) { for (int i = 0; i < loop.NumSegments; i++) { var points = loop.GetGeneratedPoints(i); //if (points != null) { // foreach (var p in points) { // doc.Objects.AddPoint(new Point3d(p.X, p.Y, 0)); // } //} } } } // Trasforma in Mesh di Rhino var mesh = region.Mesh2D; if (mesh != null) { Mesh rhino_mesh = new Mesh(); double t = 5; for (int i = 0; i < mesh.ArrayVertexes.Count; i++) { mesh.ArrayVertexes[i].Z = t; } // PostProcessa il puffyness if (puffyness) { for (int i = 0; i < region.ArrayInnerVertex.Count; i++) { var iv = region.ArrayInnerVertex[i]; if (iv.MeshVertex != null) { iv.MeshVertex.Z = (4 / 5d) * t; } // Ricerca i punti nell'intorno fino all'offset (molto grezza!) for (int j = 0; j < mesh.ArrayVertexes.Count; j++) { var v = mesh.ArrayVertexes[j]; double d = (iv.MeshVertex.Coord - v.Coord).Length; if (d < offset) { double r = d / offset; AM_Util.EInterpolation interpolation = AM_Util.EInterpolation.Parabolic; v.Z = AM_Util.Interpolation(interpolation, iv.MeshVertex.Z, t, r); } } } } // Individua i punti all'interno della zona di transizione List <int> transitionVts = new List <int>(); if (border_puffyness && border_offset > 0) { // Individua i vertici di partenza e utilizza u flag di lavoro List <AM_Vertex> transitionStartVts = new List <AM_Vertex>(); for (int i = 0; i < mesh.ArrayVertexes.Count; i++) { var v = mesh.ArrayVertexes[i]; bool is_loop_vertex = (v.Flag & 0x1) > 0; v.Flag &= ~0x02; if (is_loop_vertex && BelongToBorder(v)) { transitionStartVts.Add(v); } } // Si usa 0x04 come flag di lavoro for (int i = 0; i < mesh.ArrayWEdges.Count; i++) { var e = mesh.ArrayWEdges[i]; e.Edge().Flag &= ~0x04; e.Edge().Symm().Flag &= ~0x04; } for (int i = 0; i < transitionStartVts.Count; i++) { var v = transitionStartVts[i]; AddTransitionVertexes(v, transitionVts); } if (offset_outer_crv != null) { foreach (var iv in transitionVts) { var v = mesh.ArrayVertexes[iv]; double par; if (offset_outer_crv.ClosestPoint(AM_Util.To3d(v.Coord), out par, 2 * border_offset)) { Point3d cp = offset_outer_crv.PointAt(par); double r = ((cp - AM_Util.To3d(v.Coord)).Length) / border_offset; double z = AM_Util.Interpolation(AM_Util.EInterpolation.Parabolic, 0.8 * t, t, 1 - r); v.Z = z; } } } } // Facce int totVtx = mesh.ArrayVertexes.Count; for (int iSide = 0; iSide < 2; iSide++) { for (int i = 0; i < mesh.ArrayVertexes.Count; i++) { var v = mesh.ArrayVertexes[i]; Point3d pt = v.Coord3d; if (iSide == 1) { pt.Z = 0; } rhino_mesh.Vertices.Add(pt); } for (int i = 0; i < mesh.ArrayFaces.Count; i++) { var f = mesh.ArrayFaces[i]; int numEdges = f.NumEdges; if (numEdges == 3) { int[] vtx = { f.Vertex(0).Index, f.Vertex(1).Index, f.Vertex(2).Index }; if (iSide == 1) { vtx = new int[] { f.Vertex(0).Index + totVtx, f.Vertex(2).Index + totVtx, f.Vertex(1).Index + totVtx }; } rhino_mesh.Faces.AddFace(vtx[0], vtx[1], vtx[2]); } else if (numEdges == 4) { int[] vtx = { f.Vertex(0).Index, f.Vertex(1).Index, f.Vertex(2).Index, f.Vertex(3).Index }; if (iSide == 1) { vtx = new int[] { f.Vertex(0).Index + totVtx, f.Vertex(3).Index + totVtx, f.Vertex(2).Index + totVtx, f.Vertex(1).Index + totVtx }; } rhino_mesh.Faces.AddFace(vtx[0], vtx[1], vtx[2], vtx[3]); } } } for (int iEdge = 0; iEdge < mesh.ArrayWEdges.Count; iEdge++) { var edge = mesh.ArrayWEdges[iEdge].Edge(); if (edge.CcwFace() == null || edge.CwFace() == null) { // E' uno spigolo di bordo int[] vtx = { edge.Destination().Index, edge.Origin().Index, edge.Origin().Index + totVtx, edge.Destination().Index + totVtx, }; rhino_mesh.Faces.AddFace(vtx[0], vtx[1], vtx[2], vtx[3]); } } rhino_mesh.Normals.ComputeNormals(); rhino_mesh.Compact(); if (doc.Objects.AddMesh(rhino_mesh) != Guid.Empty) { doc.Views.Redraw(); return(Rhino.Commands.Result.Success); } } } return(Result.Success); } return(Result.Cancel); }
protected override Result RunCommand(RhinoDoc doc, RunMode mode) { //Pick curve for chain GetObject getCurve = new GetObject(); getCurve.GeometryFilter = Rhino.DocObjects.ObjectType.Curve; getCurve.SetCommandPrompt("Select curve for chain"); var res = getCurve.Get(); Rhino.DocObjects.ObjRef objref = getCurve.Object(0); Rhino.DocObjects.RhinoObject obj = objref.Object(); if (obj == null) { return(Result.Failure); } curve = objref.Curve(); if (curve == null) { return(Result.Failure); } obj.Select(false); //Pick object for chain (instance) //pick objekt to orient GetObject go = new GetObject(); go.SetCommandPrompt("Select chain element."); go.SubObjectSelect = true; go.DeselectAllBeforePostSelect = false; //go.GroupSelect = true; //go.GetMultiple(1, -1); go.Get(); if (go.CommandResult() != Result.Success) { return(go.CommandResult()); } Rhino.DocObjects.ObjRef objref1 = go.Object(0); Rhino.DocObjects.RhinoObject obj1 = objref1.Object(); GeometryBase obj1Base = obj1.Geometry; int obCount = go.ObjectCount; string instDefCount = DateTime.Now.ToString("ddMMyyyyHHmmss"); //create block instance and plane for instance Rhino.Input.Custom.GetPoint gp1 = new Rhino.Input.Custom.GetPoint(); gp1.SetCommandPrompt("Center point to orient from"); gp1.Get(); if (gp1.CommandResult() != Rhino.Commands.Result.Success) { return(gp1.CommandResult()); } Point3d pt1 = gp1.Point(); Rhino.Input.Custom.GetPoint gp2 = new Rhino.Input.Custom.GetPoint(); gp2.SetCommandPrompt("Point for orientation"); gp2.DrawLineFromPoint(pt1, false); gp2.Get(); if (gp2.CommandResult() != Rhino.Commands.Result.Success) { return(gp2.CommandResult()); } Point3d pt2 = gp2.Point(); Vector3d vt1 = pt2 - pt1; sourcePlane = new Plane(pt1, vt1); Plane originPlane = new Plane(Point3d.Origin, vt1); Transform bform = Rhino.Geometry.Transform.PlaneToPlane(sourcePlane, originPlane); obj1Base.Transform(bform); GeometryBase[] obj1List = new GeometryBase[1] { obj1Base }; var orientBlock = doc.InstanceDefinitions.Add("Block" + instDefCount, "OrientBlock", Point3d.Origin, obj1List); //orient instances along curve List <Guid> chainBlocks = new List <Guid>(); Guid chainBlock; while (true) { foreach (var block in chainBlocks) { doc.Objects.Delete(block, false); } chainBlocks = new List <Guid>(); double curveLength = curve.GetLength(); double curveDivide = curveLength / chainDis; int curveDivideInt = Convert.ToInt32(curveDivide); for (int ic = 0; ic < curveDivideInt; ic++) { Point3d insertPoint = curve.PointAtLength(chainDis * ic); Vector3d insertVec = curve.PointAtLength(chainDis * ic + 1) - curve.PointAtLength(chainDis * ic - 1); Plane targetPlane = new Plane(insertPoint, insertVec); var xvec = targetPlane.XAxis; if (xvec.Z != 0) { targetPlane.Rotate(Math.PI / 2, insertVec); } var yvec = targetPlane.YAxis; if (yvec.Z < 0) { targetPlane.Rotate(Math.PI, insertVec); } if (ic % 2 == 0) { targetPlane.Rotate(Math.PI / 2, insertVec); } targetPlane.Rotate(axisOffsetRadiant, insertVec); Rhino.Geometry.Transform xform = Rhino.Geometry.Transform.PlaneToPlane(originPlane, targetPlane); chainBlock = doc.Objects.AddInstanceObject(orientBlock, xform); chainBlocks.Add(chainBlock); } doc.Views.Redraw(); GetOption gd = new GetOption(); gd.SetCommandPrompt("Set distance between element centers in mm and rotation offset in degree. Press enter to accept."); var dis = new Rhino.Input.Custom.OptionDouble(chainDis); var axisOffset = new Rhino.Input.Custom.OptionInteger(chainAxisOffset); gd.AddOptionDouble("distance", ref dis); gd.AddOptionInteger("rotation", ref axisOffset); gd.AcceptNothing(true); var resdis = gd.Get(); if (resdis == GetResult.Nothing) { break; } chainDis = dis.CurrentValue; chainAxisOffset = axisOffset.CurrentValue; axisOffsetRadiant = chainAxisOffset * (Math.PI / 180); } int index = doc.Groups.Add(chainBlocks); return(Result.Success); }