protected override Result RunCommand(RhinoDoc doc, RunMode mode) { ObjRef obj_ref; var rc = RhinoGet.GetOneObject("Select object", false, ObjectType.AnyObject, out obj_ref); if (rc != Result.Success) return rc; var rhino_object = obj_ref.Object(); var color = rhino_object.Attributes.ObjectColor; bool b = Rhino.UI.Dialogs.ShowColorDialog(ref color); if (!b) return Result.Cancel; rhino_object.Attributes.ObjectColor = color; rhino_object.Attributes.ColorSource = ObjectColorSource.ColorFromObject; rhino_object.CommitChanges(); // an object's color attributes can also be specified // when the object is added to Rhino var sphere = new Sphere(Point3d.Origin, 5.0); var attributes = new ObjectAttributes(); attributes.ObjectColor = Color.CadetBlue; attributes.ColorSource = ObjectColorSource.ColorFromObject; doc.Objects.AddSphere(sphere, attributes); doc.Views.Redraw(); return Result.Success; }
public void Main(ref cSapModel Model) { if (rhinoCore == null) { // Load Rhino try { var schemeName = "SAP"; rhinoCore = new RhinoCore(new string[] { $"/scheme={schemeName}", "/nosplash" }, WindowStyle.Normal, Process.GetCurrentProcess().MainWindowHandle); } catch (Exception e) { Debug.Fail(e.Source, e.Message); return; } } // RhinoCommon code var sphere = new Rhino.Geometry.Sphere(Point3d.Origin, 12000); var brep = sphere.ToBrep(); var mp = MeshingParameters.Default; var meshes = Rhino.Geometry.Mesh.CreateFromBrep(brep, mp); foreach (var mesh in meshes.ToList()) { for (int i = 0; i < mesh.Faces.Count; i++) { Point3f a; Point3f b; Point3f c; Point3f d; mesh.Faces.GetFaceVertices(i, out a, out b, out c, out d); List <Point3f> vertices = new List <Point3f>(); vertices.Add(a); vertices.Add(b); vertices.Add(c); if (c != d) { vertices.Add(d); } List <string> points = new List <string>(); foreach (var v in vertices) { string p = string.Empty; Model.PointObj.AddCartesian(v.X, v.Y, v.Z, ref p); points.Add(p); } string area = string.Empty; string[] pts = points.ToArray(); Model.AreaObj.AddByPoint(points.Count, ref pts, ref area); } } }
protected override Result RunCommand(RhinoDoc doc, RunMode mode) { // user input ObjRef[] obj_refs; var rc = RhinoGet.GetMultipleObjects("Select curve to divide", false, ObjectType.Curve | ObjectType.EdgeFilter, out obj_refs); if (rc != Result.Success || obj_refs == null) return rc; double distance_between_divisions = 5; rc = RhinoGet.GetNumber("Distance between divisions", false, ref distance_between_divisions, 1.0, Double.MaxValue); if (rc != Result.Success) return rc; // generate the points var points = new List<Point3d>(); foreach (var obj_ref in obj_refs) { var curve = obj_ref.Curve(); if (curve == null) return Result.Failure; var t0 = curve.Domain.Min; points.Add(curve.PointAt(t0)); var sphere_center = curve.PointAt(t0); var t = t0; var rest_of_curve = curve; while (true) { var sphere = new Sphere(sphere_center, distance_between_divisions); Curve[] overlap_curves; Point3d[] intersect_points; var b = Intersection.CurveBrep(rest_of_curve, sphere.ToBrep(), 0.0, out overlap_curves, out intersect_points); if (!b || (overlap_curves.Length == 0 && intersect_points.Length == 0)) break; double intersect_param; Point3d intersect_point; NextintersectParamAndPoint(overlap_curves, intersect_points, rest_of_curve, out intersect_param, out intersect_point); points.Add(intersect_point); t = intersect_param; sphere_center = intersect_point; rest_of_curve = curve.Split(t)[1]; } } foreach (var point in points) doc.Objects.AddPoint(point); doc.Views.Redraw(); return Result.Success; }
public static Rhino.Commands.Result AddSphere(Rhino.RhinoDoc doc) { Rhino.Geometry.Point3d center = new Rhino.Geometry.Point3d(0, 0, 0); double radius = 5.0; Rhino.Geometry.Sphere sphere = new Rhino.Geometry.Sphere(center, radius); if( doc.Objects.AddSphere(sphere) != Guid.Empty ) { doc.Views.Redraw(); return Rhino.Commands.Result.Success; } return Rhino.Commands.Result.Failure; }
public override void Setup() { origin = new Point3d(0.0,0.0,0.0); earth_r = 63.71; // actually its 6,371km moon_r = 17.37; sun_earth_distance = 1496.00; // actually its 149,600,000km earth_moon_distance = 384.00; // actually its 384,000km // make new sphere earth = new Sphere(new Point3d(0.0,sun_earth_distance,0.0),earth_r); moon = new Sphere(new Point3d(0.0,sun_earth_distance+earth_moon_distance,0.0),moon_r); }
// constructors public AstroObject( double _radius, Point3d _rotation_origin, double _rotation_radius, double _rotation_days ) { // set variables radius = _radius; rotation_origin = _rotation_origin; rotation_radius = _rotation_radius; rotation_days = _rotation_days; // make the Sphere object. Point3d initial_position = rotation_origin; initial_position.Y += rotation_radius; obj = new Sphere(initial_position,radius); }
protected override Rhino.Commands.Result RunCommand(RhinoDoc doc, Rhino.Commands.RunMode mode) { Rhino.DocObjects.ObjRef objref; var rc = Rhino.Input.RhinoGet.GetOneObject("select mesh", false, Rhino.DocObjects.ObjectType.Mesh, out objref); if (rc != Rhino.Commands.Result.Success) return rc; Mesh mesh = objref.Mesh(); objref.Object().Select(false); doc.Views.Redraw(); using (RTree tree = new RTree()) { for (int i = 0; i < mesh.Vertices.Count; i++) { // we can make a C++ function that just builds an rtree from the // vertices in one quick shot, but for now... tree.Insert(mesh.Vertices[i], i); } Point3d point; while (true) { rc = Rhino.Input.RhinoGet.GetPoint("test point", false, out point); if (rc != Rhino.Commands.Result.Success) break; SearchData data = new SearchData(mesh, point); // Use the first vertex in the mesh to define a start sphere double distance = point.DistanceTo(mesh.Vertices[0]); Sphere sphere = new Sphere(point, distance * 1.1); if (tree.Search(sphere, SearchCallback, data)) { doc.Objects.AddPoint(mesh.Vertices[data.Index]); doc.Views.Redraw(); RhinoApp.WriteLine("Found point in {0} tests", data.HitCount); } } } return Rhino.Commands.Result.Success; }
protected override Vector3d CalculateDesiredVelocity() { Vector3d offsetVec = agent.Velocity; offsetVec.Unitize(); offsetVec = Vector3d.Multiply(offsetVec, strength + RS.SQUARE_ROOT_OF_TWO * agent.MaxSpeed); Transform xform = Transform.Translation(offsetVec); Point3d pt = agent.Position3D; pt.Transform(xform); sphere = new Sphere(pt, strength); agent.Lon += Util.Random.RandomDouble(-rate * RS.TWO_PI, rate * RS.TWO_PI); agent.Lat += Util.Random.RandomDouble(-rate * Math.PI, rate * Math.PI); //if (agent.Lon < 0) agent.Lon = Math.PI - agent.Lon; //if (agent.Lon > 2*Math.PI) agent.Lon = agent.Lon - Math.PI; //if (agent.Lat < -Math.PI/2) agent.Lon = Math.PI/2 - agent.Lat; //if (agent.Lat > Math.PI / 2) agent.Lon = agent.Lat - Math.PI/2; //agent.Lon = Util.Number.Clamp(agent.Lon, 0, 2 * Math.PI); //agent.Lat = Util.Number.Clamp(agent.Lat, -Math.PI / 2, Math.PI / 2); targetPt = sphere.PointAt(agent.Lon, agent.Lat); targetPt = agent.Environment.MapTo2D(targetPt); Vector3d desired = Util.Agent.Seek(agent, targetPt); return desired; }
public static Rhino.Commands.Result AddMaterial(Rhino.RhinoDoc doc) { // materials are stored in the document's material table int index = doc.Materials.Add(); Rhino.DocObjects.Material mat = doc.Materials[index]; mat.DiffuseColor = System.Drawing.Color.Chocolate; mat.SpecularColor = System.Drawing.Color.CadetBlue; mat.CommitChanges(); // set up object attributes to say they use a specific material Rhino.Geometry.Sphere sp = new Rhino.Geometry.Sphere(Rhino.Geometry.Plane.WorldXY, 5); Rhino.DocObjects.ObjectAttributes attr = new Rhino.DocObjects.ObjectAttributes(); attr.MaterialIndex = index; attr.MaterialSource = Rhino.DocObjects.ObjectMaterialSource.MaterialFromObject; doc.Objects.AddSphere(sp, attr); // add a sphere without the material attributes set sp.Center = new Rhino.Geometry.Point3d(10, 10, 0); doc.Objects.AddSphere(sp); doc.Views.Redraw(); return Rhino.Commands.Result.Success; }
/***************************************************/ /**** Public Methods - Solids ****/ /***************************************************/ public static BHG.Sphere FromRhino(this RHG.Sphere sphere) { return(new BHG.Sphere { Centre = sphere.Center.FromRhino(), Radius = sphere.Radius }); }
/// <summary> /// Create a spherical projection texture mapping. /// </summary> /// <param name="sphere"> /// sphere in world space used to define a spherical coordinate system. /// The longitude parameter maps (0,2pi) to texture "u" (0,1). /// The latitude paramter maps (-pi/2,+pi/2) to texture "v" (0,1). /// The radial parameter maps (0,r) to texture "w" (0,1). /// </param> /// <returns>TextureMapping instance if input is valid</returns> public static TextureMapping CreateSphereMapping(Sphere sphere) { TextureMapping rc = new TextureMapping(); IntPtr pMapping = rc.NonConstPointer(); if( !UnsafeNativeMethods.ON_TextureMapping_SetSphereMapping(pMapping, ref sphere) ) { rc.Dispose(); rc = null; } return rc; }
/***************************************************/ public static RHG.Mesh CreatePreviewMesh(RHG.Sphere sphere, RHG.MeshingParameters parameters) { return(CreatePreviewMesh(sphere.ToBrep(), parameters)); }
/// <summary>Test a surface to see if it is a portion of a sphere and return the sphere.</summary> /// <param name="sphere">On success, the sphere parameters are filled in.</param> /// <returns>true if the surface is a portion of a sphere.</returns> public bool TryGetSphere(out Sphere sphere) { return TryGetSphere(out sphere, RhinoMath.ZeroTolerance); }
/// <summary> /// Gets near and far clipping distances of a sphere. /// </summary> /// <param name="sphere">The sphere.</param> /// <param name="nearDistance">The near distance is assigned to this out parameter during this call.</param> /// <param name="farDistance">The far distance is assigned to this out parameter during this call.</param> /// <returns> /// true if the sphere intersects the view frustum and near_dist/far_dist were set. /// false if the sphere does not intesect the view frustum. /// </returns> public bool GetDepth(Sphere sphere, out double nearDistance, out double farDistance) { IntPtr ptr = ConstPointer(); nearDistance = farDistance = 0; return UnsafeNativeMethods.CRhinoViewport_VP_GetDepth3(ptr, ref sphere, ref nearDistance, ref farDistance); }
/// <summary>Constrains the picked point to lie on a sphere.</summary> /// <param name="sphere">A sphere to use as constraint.</param> /// <returns>true if constraint could be applied.</returns> public bool Constrain(Sphere sphere) { IntPtr ptr = NonConstPointer(); return UnsafeNativeMethods.CRhinoGetPoint_Constrain5(ptr, ref sphere); }
/// <summary> /// Searches for items in a sphere. /// </summary> /// <param name="sphere">bounds used for searching.</param> /// <param name="callback">An event handler to be raised when items are found.</param> /// <returns> /// true if entire tree was searched. It is possible no results were found. /// </returns> public bool Search(Sphere sphere, EventHandler <RTreeEventArgs> callback) { return(Search(sphere, callback, null)); }
/// <summary> /// Searches for items in a sphere. /// </summary> /// <param name="sphere">bounds used for searching.</param> /// <param name="callback">An event handler to be raised when items are found.</param> /// <returns> /// true if entire tree was searched. It is possible no results were found. /// </returns> public bool Search(Sphere sphere, EventHandler<RTreeEventArgs> callback) { return Search(sphere, callback, null); }
/***************************************************/ public static void RenderRhinoWires(RHG.Sphere sphere, Rhino.Display.DisplayPipeline pipeline, Color bhColour, int thickness) { pipeline.DrawSphere(sphere, bhColour); }
/// <summary> /// Add primitive sphere and material. /// </summary> /// <param name="sphere">Sphere to add.</param> /// <param name="material"> /// Material to add, may be null if not needed. /// </param> public void Add(Sphere sphere, RenderMaterial material) { var material_pointer = (null == material ? IntPtr.Zero : material.ConstPointer()); var pointer = NonConstPointer(); UnsafeNativeMethods.Rdk_CustomMeshes_AddSphere(pointer, sphere.Center, sphere.EquitorialPlane.XAxis, sphere.EquitorialPlane.YAxis, sphere.Radius, material_pointer); }
/// <summary> /// Searches for items in a sphere. /// </summary> /// <param name="sphere">bounds used for searching.</param> /// <param name="callback">An event handler to be raised when items are found.</param> /// <param name="tag">State to be passed inside the <see cref="RTreeEventArgs"/> Tag property.</param> /// <returns> /// true if entire tree was searched. It is possible no results were found. /// </returns> /// <example> /// <code source='examples\vbnet\ex_closestpoint.vb' lang='vbnet'/> /// <code source='examples\cs\ex_closestpoint.cs' lang='cs'/> /// <code source='examples\py\ex_closestpoint.py' lang='py'/> /// </example> public bool Search(Sphere sphere, EventHandler<RTreeEventArgs> callback, object tag) { IntPtr pConstTree = ConstPointer(); if (m_callbacks == null) m_callbacks = new List<Callbackholder>(); Callbackholder cbh = new Callbackholder(); cbh.SerialNumber = m_next_serial_number++; cbh.Callback = callback; cbh.Sender = this; cbh.Tag = tag; m_callbacks.Add(cbh); SearchCallback searcher = CustomSearchCallback; bool rc = UnsafeNativeMethods.ON_RTree_SearchSphere(pConstTree, sphere.Center, sphere.Radius, cbh.SerialNumber, searcher); for (int i = 0; i < m_callbacks.Count; i++) { if (m_callbacks[i].SerialNumber == cbh.SerialNumber) { m_callbacks.RemoveAt(i); break; } } return rc; }
/// <summary> /// Call this method to get a box at the specified index. /// </summary> /// <param name="index"> /// The zero based index of the item in the list. Valid values are greater /// than or equal to 0 and less than Count. /// </param> /// <param name="sphere"> /// Will contain the sphere at the requested index if the index is in range /// and the primitive at the requested index is a box. /// </param> /// <returns> /// Return true if the index is in range and the primitive at the requested /// index is a box otherwise returns false. /// </returns> public bool TryGetSphere(int index, out Sphere sphere) { var origin = new Point3d(); var xaxis = new Vector3d(); var yaxis = new Vector3d(); var radius = 0.0; if (UnsafeNativeMethods.Rdk_CustomMeshes_Sphere(ConstPointer(), index, ref origin, ref xaxis, ref yaxis, ref radius)) { sphere = new Sphere(new Plane(origin, xaxis, yaxis), radius); return true; } sphere = new Sphere(); return false; }
/// <summary> /// Constructs a new surface of revolution from the values of a sphere. /// </summary> /// <param name="sphere">A sphere.</param> /// <returns>A new surface of revolution, or null if any of the inputs is invalid or on error.</returns> public static RevSurface CreateFromSphere(Sphere sphere) { IntPtr pRevSurface = UnsafeNativeMethods.ON_Sphere_RevSurfaceForm(ref sphere); if (IntPtr.Zero == pRevSurface) return null; return new RevSurface(pRevSurface, null); }
/***************************************************/ public static void RenderRhinoMeshes(RHG.Sphere sphere, Rhino.Display.DisplayPipeline pipeline, DisplayMaterial material) { pipeline.DrawBrepShaded(sphere.ToBrep(), material); }
/// <summary> /// Draw a wireframe sphere. /// </summary> /// <param name="sphere">Sphere to draw.</param> /// <param name="color">Color to draw with.</param> /// <param name="thickness">Thickness (in pixels) of Sphere wires.</param> public void DrawSphere(Sphere sphere, System.Drawing.Color color, int thickness) { int argb = color.ToArgb(); UnsafeNativeMethods.CRhinoDisplayPipeline_DrawSphere(m_ptr, ref sphere, argb, thickness); }
public void createEntities(RhinoDoc doc) { // Add nozzleStartPoints and nozzleEndPoints for (int i = 0; i < numNozzles; i++) { nozzleStartPointRxRx[i] = new Point3d(nozzleXOffset + (nozzleXMultiplier * nozzleX[i]), 0.0, nozzleZOffset); nozzleEndPointRxRx[i] = new Point3d(nozzleXOffset + (nozzleXMultiplier * nozzleX[i]), 0.0, nozzleZOffset + nozzleSprayLength); } //nozzleEndPointRxRx[11] = new Point3d(nozzleXOffset + (nozzleXMultiplier * nozzleX[11]), 0.0, nozzleZOffset + nozzleSprayLength + nozzleSprayLength); ball = new Sphere(new Point3d(0.0, 0.0, 0.0), 5.0); RhinoApp.WriteLine("Generating printHead objects!!"); }
/// <summary> /// Determines if the surface is a portion of a sphere within a given tolerance. /// </summary> /// <param name="tolerance">tolerance to use when checking.</param> /// <returns>true if the surface is a portion of a sphere.</returns> public bool IsSphere(double tolerance) { Sphere sphere = new Sphere(); IntPtr pThis = ConstPointer(); return UnsafeNativeMethods.ON_Surface_IsSphere(pThis, ref sphere, tolerance, false); }
protected override Rhino.Commands.Result RunCommand(RhinoDoc doc, Rhino.Commands.RunMode mode) { nishanchiPlugin pluginObj = ((nishanchiPlugin)this.PlugIn); Boolean selectedObjectIsBrep = false; Boolean selectedObjectIsCurve = false; if (!pluginObj.trackerConnected) { RhinoApp.WriteLine("Tracker disconnected"); return Rhino.Commands.Result.Failure; } connectKbEvt(); //Ask the user to select Breps to print. //Result rc = Rhino.Input.RhinoGet.GetMultipleObjects("Select the surfaces to print", //false, Rhino.DocObjects.ObjectType.Surface, out objrefs); Rhino.Input.Custom.GetObject go = new Rhino.Input.Custom.GetObject(); go.SetCommandPrompt("Select the entity to print"); go.GroupSelect = true; //Set this to go.GetMultiple(0,0) if you want to allow multiple entities to be selected go.GetMultiple(0, 1); Result rc = go.CommandResult(); if (rc != Rhino.Commands.Result.Success) { disconnectKbEvt(); return rc; } List<Rhino.Geometry.Brep> breps = new List<Rhino.Geometry.Brep>(); List<Rhino.Geometry.Curve> curves = new List<Rhino.Geometry.Curve>(); for (int i = 0; i < go.ObjectCount; i++) { ObjRef tmpRef = new ObjRef(go.Object(i).ObjectId); Rhino.Geometry.Brep brep = tmpRef.Brep(); if (brep != null) { breps.Add(brep); selectedObjectIsBrep = true; } Rhino.Geometry.Curve curve = tmpRef.Curve(); if (curve != null) { curves.Add(curve); selectedObjectIsCurve = true; } } if (selectedObjectIsBrep) RhinoApp.WriteLine("Selected " + breps.Count + " surfaces! Good! No, not, really, I'm just a program, I couldn't care less."); if (selectedObjectIsCurve) RhinoApp.WriteLine("Selected " + curves.Count + " curves! Good! No, not, really, I'm just a program, I couldn't care less."); createEntities(doc); fastrak trackerObj = pluginObj.trackerObj; int numPoints = 0; int numIntersections = 0; Boolean retval; RhinoApp.WriteLine(string.Format("Starting continuous mode on the tracker.")); pluginObj.trackerObj.setContinuous(); RhinoApp.WriteLine(string.Format("Printing mode enabled now.")); Curve[] intersectionCurves; Point3d[] intersectionPoints; running = true; while (running) { retval = trackerObj.readFrame(); if (retval) { //q0,q1,q2,q3 Quaternion begin //Compute the rotation matrix rxTxTx = new Point3d(trackerObj.x, trackerObj.y, trackerObj.z); orientationQuat = new Quaternion(trackerObj.q0, trackerObj.q1, trackerObj.q2, trackerObj.q3); orientationQuat.GetRotation(out angle, out axis); rotMat = Transform.Rotation(angle, axis, origin); // Compute the new positions for the nozzlePoints and also compute the new lines for (int i = 0; i < numNozzles; i++) { nozzleStartPointRxTx[i] = rotMat * nozzleStartPointRxRx[i]; nozzleStartPointTxTx[i] = nozzleStartPointRxTx[i] + rxTxTx; nozzleEndPointRxTx[i] = rotMat * nozzleEndPointRxRx[i]; nozzleEndPointTxTx[i] = nozzleEndPointRxTx[i] + rxTxTx; nozzleLinesTx[i] = new Line(nozzleStartPointTxTx[i], nozzleEndPointTxTx[i]); nozzleCurves[i] = new LineCurve(nozzleLinesTx[i]); } numIntersections = 0; if (selectedObjectIsBrep) { for (int i = 0; i < numNozzles; i++) { foreach (Brep b in breps) { try { Intersection.CurveBrep(nozzleCurves[i], b, nozzleTolerance, out intersectionCurves, out intersectionPoints); if (intersectionPoints.Length > 0) { intersectionsBits[i] = 1; numIntersections++; } else { intersectionsBits[i] = 0; } } catch (Exception e) { RhinoApp.WriteLine(e.Message); } } } } if (selectedObjectIsCurve) { for (int i = 0; i < numNozzles; i++) { foreach (Curve c in curves) { try { var events = Intersection.CurveCurve(nozzleCurves[i], c, nozzleTolerance, nozzleTolerance); if (events != null) { if (events.Count >= 1) { intersectionsBits[i] = 1; numIntersections++; } else { intersectionsBits[i] = 0; } } } catch (Exception e) { RhinoApp.WriteLine(e.Message); } } } } if (pluginObj.printHeadConnected) { // I print if (((numPoints % 5) == 0)&&(numIntersections > 0)) { string p = printCommand(); //RhinoApp.WriteLine(p); pluginObj.printHeadObj.printFrame(p); //pluginObj.printHeadObj.printFullLine(); } } numPoints++; } //And, I move the printer like thing on the screen if ((numPoints % 10) == 0) { for (int i = 0; i < numNozzles; i++) { doc.Objects.Delete(lineGuids[i],false); lineGuids[i] = doc.Objects.AddLine(nozzleLinesTx[i]); } doc.Objects.Delete(ballGuid, false); ball = new Sphere(rxTxTx, ballRadius); ballGuid = doc.Objects.AddSphere(ball); doc.Views.ActiveView.Redraw(); RhinoApp.Wait(); } } running = false; removeEntities(doc); RhinoApp.WriteLine(string.Format("Stopping continuous mode on the tracker.")); pluginObj.trackerObj.stopContinuous(); disconnectKbEvt(); RhinoApp.WriteLine(string.Format("I guess you don't wanna print anymore, well who cares! Not me!")); return Rhino.Commands.Result.Success; }
/// <summary>Test a surface to see if it is a portion of a sphere and return the sphere.</summary> /// <param name="sphere">On success, the sphere parameters are filled in.</param> /// <param name="tolerance">tolerance to use when checking.</param> /// <returns>true if the surface is a portion of a sphere.</returns> public bool TryGetSphere(out Sphere sphere, double tolerance) { sphere = new Sphere(); IntPtr pThis = ConstPointer(); return UnsafeNativeMethods.ON_Surface_IsSphere(pThis, ref sphere, tolerance, true); }
/// <summary> /// Get a spherical projection parameters from this texture mapping. /// </summary> /// <param name="sphere">/// </param> /// <returns> /// Returns true if a valid sphere is returned. /// </returns> /// <remarks> /// Generally, GetMappingShere will not return the same parameters passed /// to SetSphereMapping. However, the location of the sphere will be the /// same. If this mapping is not cylindrical, the cylinder will /// approximate the actual mapping primitive. /// </remarks> public bool TryGetMappingSphere(out Sphere sphere) { var ptr = ConstPointer(); sphere = Sphere.Unset; var success = UnsafeNativeMethods.ON_TextureMapping_GetMappingSphere(ptr, ref sphere); return success; }