This shows you the differences between two versions of the page.
rhino:rhinov5status_extrusion_for_developers [2016/07/11] |
rhino:rhinov5status_extrusion_for_developers [2020/08/14] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Rhino 5.0 Status: | ||
+ | ======Lightweight Extrusion Objects for Developers ====== | ||
+ | |||
+ | Plug-ins written using C++ SDK, .NET SDK or Rhino common might fail to select the new lightweight extrusion objects depending on the programming style. | ||
+ | |||
+ | ===== Overview ===== | ||
+ | |||
+ | In general, the CRhinoObjRef (object reference) that you get from CRhinoGetObject (selecting a polysurface, | ||
+ | |||
+ | CRhinoGetObject go; | ||
+ | go.SetGeometryFilter( ON: | ||
+ | go.GetObject(1, | ||
+ | CRhinoObjRef original_objref = go.Object(0); | ||
+ | |||
+ | Now suppose you picked a box face where the box was actually a lightweight extrusion. Object reference " | ||
+ | |||
+ | const CRhinoObject* original_obj = original_objref.Object(); | ||
+ | const ON_Brep original_brep = original_objref.Brep(); | ||
+ | const ON_BrepFace* original_face = original_objref.Face(); | ||
+ | int face_component_index = original_objref.m_component_index | ||
+ | |||
+ | <color blue> | ||
+ | <color blue> | ||
+ | |||
+ | For help, please post questions to [[news:// | ||
+ | |Rhino developer newsgroup]]. | ||
+ | |||
+ | Following are examples where the code will fail when selecting extrusion objects and suggested solutions. | ||
+ | |||
+ | ===== Casting CRhinoObject as CRhinoBrepObject ===== | ||
+ | |||
+ | Consider the following example to select a polysurface: | ||
+ | |||
+ | CRhinoGetObject go; | ||
+ | go.SetGeometryFilter( CRhinoGetObject:: | ||
+ | go.SetCommandPrompt( L" | ||
+ | go.GetObjects(1, | ||
+ | if( go.CommandResult() != CRhinoCommand:: | ||
+ | return go.CommandResult(); | ||
+ | const CRhinoObject* obj = go.Object(0).Object(); | ||
+ | if( 0 == obj ) | ||
+ | return CRhinoCommand:: | ||
+ | |||
+ | **Problem: | ||
+ | |||
+ | const CRhinoBrepObject* brep_obj = CRhinoBrepObject :: | ||
+ | // | ||
+ | //Note: if you have selected an extrusion object, the pointer will be null | ||
+ | // | ||
+ | if( 0 == brep_obj ) | ||
+ | return CRhinoCommand:: | ||
+ | const ON_Brep* org_brep = brep_obj-> | ||
+ | |||
+ | **Solution: | ||
+ | |||
+ | const ON_Brep* input_brep = go.Object(0).Brep(); | ||
+ | |||
+ | |||
+ | ===== The original getter goes out of scope ===== | ||
+ | |||
+ | If you pass a pointer to an extrusion object from a function or block of code and throw away the object reference, then you will not be able to get to the " | ||
+ | |||
+ | MyGetEdge1() Function: | ||
+ | CRhinoCommand:: | ||
+ | { | ||
+ | CRhinoGetObject go; | ||
+ | go.SetGeometryFilter( CRhinoGetObject:: | ||
+ | go.SetGeometryAttributeFilter( CRhinoGetObject:: | ||
+ | go.GetObjects(1, | ||
+ | if( go.CommandResult() != CRhinoCommand:: | ||
+ | return go.CommandResult(); | ||
+ | const ON_Brep* brep = go.Object(0).Brep(); | ||
+ | if( 0 == brep ) | ||
+ | return CRhinoCommand:: | ||
+ | const ON_BrepEdge* edge = go.Object(0).Edge(); | ||
+ | if( 0 == edge) | ||
+ | return CRhinoCommand:: | ||
+ | // | ||
+ | //At this point we have verified that our geometry is valid | ||
+ | // | ||
+ | selected_object = go.Object(0).Object(); | ||
+ | edge_index = edge-> | ||
+ | return CRhinoCommand:: | ||
+ | } | ||
+ | |||
+ | MyGetEdge2() function: | ||
+ | CRhinoCommand:: | ||
+ | { | ||
+ | CRhinoGetObject go; | ||
+ | go.SetGeometryFilter( CRhinoGetObject:: | ||
+ | go.SetGeometryAttributeFilter( CRhinoGetObject:: | ||
+ | go.GetObjects(1, | ||
+ | if( go.CommandResult() != CRhinoCommand:: | ||
+ | return go.CommandResult(); | ||
+ | const ON_Brep* brep = go.Object(0).Brep(); | ||
+ | if( 0 == brep ) | ||
+ | return CRhinoCommand:: | ||
+ | const ON_BrepEdge* edge = go.Object(0).Edge(); | ||
+ | if( 0 == edge) | ||
+ | return CRhinoCommand:: | ||
+ | // | ||
+ | //At this point we have verified that our geometry is valid | ||
+ | // | ||
+ | selected_brep = brep; | ||
+ | edge_index = edge-> | ||
+ | return CRhinoCommand:: | ||
+ | } | ||
+ | |||
+ | MyGetEdge3() function: | ||
+ | CRhinoCommand:: | ||
+ | { | ||
+ | CRhinoGetObject go; | ||
+ | go.SetGeometryFilter( CRhinoGetObject:: | ||
+ | go.SetGeometryAttributeFilter( CRhinoGetObject:: | ||
+ | go.GetObjects(1, | ||
+ | if( go.CommandResult() != CRhinoCommand:: | ||
+ | return go.CommandResult(); | ||
+ | const ON_Brep* brep = go.Object(0).Brep(); | ||
+ | if( 0 == brep ) | ||
+ | return CRhinoCommand:: | ||
+ | const ON_BrepEdge* edge = go.Object(0).Edge(); | ||
+ | if( 0 == edge) | ||
+ | return CRhinoCommand:: | ||
+ | // | ||
+ | //At this point we have verified that our geometry is valid | ||
+ | // | ||
+ | selected_edge = edge; | ||
+ | return CRhinoCommand:: | ||
+ | } | ||
+ | |||
+ | MyGetEdgeGUID() function: | ||
+ | CRhinoCommand:: | ||
+ | { | ||
+ | CRhinoGetObject go; | ||
+ | go.SetGeometryFilter( CRhinoGetObject:: | ||
+ | go.SetGeometryAttributeFilter( CRhinoGetObject:: | ||
+ | go.GetObjects(1, | ||
+ | if( go.CommandResult() != CRhinoCommand:: | ||
+ | return go.CommandResult(); | ||
+ | const ON_Brep* brep = go.Object(0).Brep(); | ||
+ | if( 0 == brep ) | ||
+ | return CRhinoCommand:: | ||
+ | const ON_BrepEdge* edge = go.Object(0).Edge(); | ||
+ | if( 0 == edge) | ||
+ | return CRhinoCommand:: | ||
+ | // | ||
+ | //At this point we have verified that our geometry is valid | ||
+ | // | ||
+ | guid = go.Object(0).ObjectUuid(); | ||
+ | component_index = edge-> | ||
+ | return CRhinoCommand:: | ||
+ | } | ||
+ | |||
+ | MyMainCommand() - the main caller function illustrating where things might go wrong: | ||
+ | CRhinoCommand:: | ||
+ | { | ||
+ | // | ||
+ | const CRhinoBrepObject* brep_obj = 0; | ||
+ | const CRhinoObject* obj = 0; | ||
+ | const ON_Brep* brep = 0; | ||
+ | const ON_BrepEdge* edge = 0; | ||
+ | int edge_index = -1; | ||
+ | CRhinoCommand:: | ||
+ | |||
+ | <color red> | ||
+ | rc = MyGetEdge1(obj, | ||
+ | if( rc != CRhinoCommand:: | ||
+ | return rc; | ||
+ | CRhinoObjRef new_ref = CRhinoObjRef(obj); | ||
+ | // | ||
+ | //brep will be a null or invalid pointer. Fail at the next linet | ||
+ | // | ||
+ | brep = new_ref.Brep(); | ||
+ | if( 0 == brep || !brep-> | ||
+ | return CRhinoCommand:: | ||
+ | // | ||
+ | // | ||
+ | //If you cast object as follows, you will still fail because brep_obj will be null | ||
+ | // | ||
+ | brep_obj = CRhinoBrepObject:: | ||
+ | if( 0 == brep_obj ) | ||
+ | return CRhinoCommand:: | ||
+ | |||
+ | |||
+ | <color red> | ||
+ | rc = MyGetEdge2(brep, | ||
+ | if( rc != CRhinoCommand:: | ||
+ | return rc; | ||
+ | if( 0 == brep ) | ||
+ | return CRhinoCommand:: | ||
+ | // | ||
+ | //Next line will crash or return null or invalid pointer. brep is now pointing to invalid memory | ||
+ | // because it was destroyed once the getter went out of scope when exiting MyGetFace2 function | ||
+ | // | ||
+ | edge = brep-> | ||
+ | if( 0 == edge || !edge-> | ||
+ | return CRhinoCommand:: | ||
+ | |||
+ | |||
+ | <color red> | ||
+ | rc = MyGetEdge3( edge ); | ||
+ | if( rc != CRhinoCommand:: | ||
+ | return rc; | ||
+ | if( 0 == edge) | ||
+ | return CRhinoCommand:: | ||
+ | // | ||
+ | //Next line will crash or return null or invalid pointer. edge is now pointing to invalid memory | ||
+ | //because it was dietroyed once the getter went out of scope | ||
+ | // | ||
+ | brep = edge-> | ||
+ | if( 0 == brep || !brep-> | ||
+ | return CRhinoCommand:: | ||
+ | |||
+ | |||
+ | <color red> | ||
+ | { | ||
+ | CRhinoGetObject go; //the getter will be destoyed once exiting the block | ||
+ | go.SetGeometryFilter( CRhinoGetObject:: | ||
+ | go.SetGeometryAttributeFilter( CRhinoGetObject:: | ||
+ | go.GetObjects(1, | ||
+ | if( go.CommandResult() != CRhinoCommand:: | ||
+ | return go.CommandResult(); | ||
+ | brep = go.Object(0).Brep(); | ||
+ | if( 0 == brep ) | ||
+ | return CRhinoCommand:: | ||
+ | edge = go.Object(0).Edge(); | ||
+ | if( 0 == edge) | ||
+ | return CRhinoCommand:: | ||
+ | } | ||
+ | //Using the edge pointer will give invalid index or crash | ||
+ | edge_index = edge-> | ||
+ | |||
+ | |||
+ | <color red> | ||
+ | ON_UUID uuid = ON_nil_uuid; | ||
+ | ON_COMPONENT_INDEX component_index; | ||
+ | rc = MyGetEdgeGUID(uuid, | ||
+ | if( rc != CRhinoCommand:: | ||
+ | return rc; | ||
+ | // | ||
+ | //The following reference will not have proxy brep information | ||
+ | // | ||
+ | CRhinoObjRef ref = CRhinoObjRef(uuid); | ||
+ | // | ||
+ | //brep will be invalid (null pointer) | ||
+ | // | ||
+ | brep = ref.Brep(); | ||
+ | if( 0 == brep) | ||
+ | return CRhinoCommand:: | ||
+ | edge = brep-> | ||
+ | if( 0 == edge) | ||
+ | return CRhinoCommand:: | ||
+ | return CRhinoCommand:: | ||
+ | } | ||
+ | |||
+ | |||
+ | <color blue> | ||
+ | |||
+ | CRhinoCommand:: | ||
+ | { | ||
+ | CRhinoGetObject go; | ||
+ | go.SetGeometryFilter( CRhinoGetObject:: | ||
+ | go.SetGeometryAttributeFilter( CRhinoGetObject:: | ||
+ | go.GetObjects(1, | ||
+ | if( go.CommandResult() != CRhinoCommand:: | ||
+ | return go.CommandResult(); | ||
+ | const ON_Brep* brep = go.Object(0).Brep(); | ||
+ | if( 0 == brep ) | ||
+ | return CRhinoCommand:: | ||
+ | const ON_BrepEdge* edge = go.Object(0).Edge(); | ||
+ | if( 0 == edge) | ||
+ | return CRhinoCommand:: | ||
+ | // | ||
+ | //At this point we have verified that our geometry is valid | ||
+ | //Save a copy of the object reference and return success | ||
+ | // | ||
+ | obj_ref = go.Object(0); | ||
+ | return CRhinoCommand:: | ||
+ | } | ||
+ | |||
+ | CRhinoCommand:: | ||
+ | { | ||
+ | CRhinoObjRef obj_ref; | ||
+ | CRhinoCommand:: | ||
+ | if( rc != CRhinoCommand:: | ||
+ | return rc; | ||
+ | // | ||
+ | //Both the following pointers will be valid and good to use | ||
+ | //whether input in brep object or extrusion object | ||
+ | // | ||
+ | const ON_Brep* brep = obj_ref.Brep(); | ||
+ | const ON_BrepEdge* edge = obj_ref.Edge(); | ||
+ | return CRhinoCommand:: | ||
+ | } | ||
+ | |||
+ | |||
+ | ===== Extending CRhinoGetObject ===== | ||
+ | |||
+ | You need to pay special attention when extending CRhinogetObject. | ||
+ | |||
+ | |||
+ | Special class to use for picking the Face | ||
+ | class CMyGetFace : public CRhinoGetObject | ||
+ | { | ||
+ | public: | ||
+ | CMyGetFace(){}; | ||
+ | ~CMyGetFace(){}; | ||
+ | // | ||
+ | // virtual CRhinoGetObject override | ||
+ | // | ||
+ | bool CustomGeometryFilter( | ||
+ | const CRhinoObject* object, | ||
+ | const ON_Geometry* geometry, | ||
+ | | ||
+ | ) const; | ||
+ | // | ||
+ | //virtual CRhinoGetObject override | ||
+ | // | ||
+ | bool PassesGeometryAttributeFilter( | ||
+ | const CRhinoObject* object, | ||
+ | const ON_Geometry* geometry, | ||
+ | | ||
+ | ) const; | ||
+ | }; | ||
+ | |||
+ | bool CMyGetFace:: | ||
+ | const CRhinoObject* object, | ||
+ | const ON_Geometry* geometry, | ||
+ | | ||
+ | ) const | ||
+ | { | ||
+ | |||
+ | <color red> | ||
+ | const CRhinoBrepObject* brep_object = CRhinoBrepObject:: | ||
+ | if ( 0 == brep_object ) | ||
+ | return false; | ||
+ | const ON_Brep* brep = brep_object-> | ||
+ | if ( 0 == brep ) | ||
+ | return false; | ||
+ | const ON_BrepFace* Face = brep-> | ||
+ | if ( 0 == Face ) | ||
+ | return false; | ||
+ | |||
+ | <color blue> | ||
+ | |||
+ | //first, make sure that the component index belongs to a brep | ||
+ | // | ||
+ | if( !component_index.IsBrepComponentIndex() ) | ||
+ | return false; | ||
+ | // | ||
+ | //Cast geometry as ON_BrepFace | ||
+ | // | ||
+ | const ON_BrepFace* face = ON_BrepFace:: | ||
+ | if ( 0 == face ) | ||
+ | return false; | ||
+ | return true; | ||
+ | } | ||
+ | |||
+ | bool CMyGetFace:: | ||
+ | const CRhinoObject* object, | ||
+ | const ON_Geometry* geometry, | ||
+ | | ||
+ | ) const | ||
+ | { | ||
+ | bool rc = CRhinoGetObject:: | ||
+ | if (rc) | ||
+ | { | ||
+ | rc = CustomGeometryFilter(object, | ||
+ | } | ||
+ | return rc; | ||
+ | } | ||