我想实现左键选中实体的某个面(假如是个长方体),然后随着鼠标的移动、实时显示这个面沿法相方向被拉伸的效果,然后点击左键呈现拉伸的效果,请问该怎么做?
SDK例子中exampleSubEntityTool功能只能实现选点、线、面,但是当我重载了databutton功能后,左键就不能选面了
下面的帖子或许能帮到您:
https://communities.bentley.com/communities/other_communities/chinafirst/f/microstation-projectwise/194161/locatesubentitytool/575463#575463
主要是我在修改实体的例子里面找不到鼠标的操作,无法把鼠标操作和选择的面关联起来
建议您搜索下交互式工具的使用,一个工具要么是用来对整个元素操作的,就用DgnElementSetTool,如果该元素是Solid/SmartSolid,为了提高效率可改用ElementGraphicsTool。如果是操作Solid/SmartSolid中的子实体(SubEntity)则需要用LocateSubEntityTool。
https://communities.bentley.com/communities/other_communities/bdn_other_communities/w/chinabdn-wiki/43485/microstation
DgnElementSetTool和DgnPrimitiveTool的例子我都看过,我现在要做的事情属于交互式修改Solid/SmartSolid中的子实体(SubEntity),肯定是要用LocateSubEntityTool,但是SDK的例子里面没有找到交互修改子实体的内容
邢 万里 said:肯定是要用LocateSubEntityTool,但是SDK的例子里面没有找到交互修改子实体的内容
请参考SDK中的例子C:\Program Files\Bentley\MicroStationCONNECTSDK\examples\Elements\exampleSolids\exampleModifyFaceTool.cpp
经过三天以来不断的尝试,很遗憾还是没有成功,同时我发现:(1)重载_OnDynamicFrame、_OnDataButton、_OnResetButton函数时如果函数中包含实体修改内容,就会出现奇怪的结果(如之前的附图),(2)GetPlanarFaceData(&point, &normal1, *subEntity))获取的点坐标point并不在选取的平面上,下面是在例子上面修改的代码~~
struct TestModifyFaceTool : LocateSubEntityTool { enum ToolOperation { OP_FaceOffset = 0, OP_FaceTranslate = 1, OP_FaceRotate = 2, OP_FaceDelete = 3, OP_FaceHollow = 4, }; private: DPoint3d pointDynamic; //记录实时变化的坐标 protected: ToolOperation m_operation; /*---------------------------------------------------------------------------------**//** * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ TestModifyFaceTool(int cmdName, ToolOperation operation) { SetCmdName(cmdName, 0); m_operation = operation; } /*---------------------------------------------------------------------------------**//** * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ virtual bool _CollectCurves() override { return false; } // Tool does not support wire bodies...wire bodies won't be collected. virtual bool _CollectSurfaces() override { return false; } // Tool does not support sheet bodies...sheet bodies won't be collected. /*---------------------------------------------------------------------------------**//** * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ virtual BentleyStatus _OnProcessSolidPrimitive(ISolidPrimitivePtr& geomPtr, DisplayPathCR path) override { return ERROR; } // Promote capped surface to solid body... virtual BentleyStatus _OnProcessPolyface(PolyfaceHeaderPtr& geomPtr, DisplayPathCR path) override { return SUCCESS; } // Don't convert a closed mesh to a BRep (and don't collect), can be expensive for large meshes... /*---------------------------------------------------------------------------------**//** * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ virtual ISubEntity::SubEntityType _GetSubEntityTypeMask() override { return ISubEntity::SubEntityType_Face; } virtual bool _RequireSubEntitySupport() override { return true; } // Require solid w/at least 1 face... virtual bool _AcceptIdentifiesSubEntity() { return OP_FaceHollow != m_operation; } // Solid accept point may also accept first face (except hollow which can apply to entire body)... virtual bool _AllowMissToAccept(DgnButtonEventCR ev) { return (OP_FaceHollow == m_operation ? true : __super::_AllowMissToAccept(ev)); } // Don't require face for hollow... /*---------------------------------------------------------------------------------**//** * Return true if this element should be accepted for the modify operation. * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ virtual bool _IsElementValidForOperation(ElementHandleCR eh, HitPathCP path, WStringR cantAcceptReason) override { // Base class implementation returns true if geometry cache isn't empty, which in this case means the cache contains at least 1 BRep solid. // To be valid for modification element should be fully represented by a single solid; reject if there are multiple solid bodies or missing geometry. // NOTE: Simple count test is sufficient (w/o also checking TryGetAsBRep) as override of _Collect and _OnProcess methods have tool only collecting BRep solids. return (__super::_IsElementValidForOperation(eh, path, cantAcceptReason) && 1 == GetElementGraphicsCacheCount(eh) && !IsGeometryMissing(eh)); } /*---------------------------------------------------------------------------------**//** * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ double GetDistance() { // For testing purposes just use some % of element's range. This value would normally be supplied via tool settings. ScanRangeCP elRange = &GetElementAgenda().GetFirstP()->GetElementCP()->hdr.dhdr.range; DPoint3d range[2]; range[0].x = (double)elRange->xlowlim; range[0].y = (double)elRange->ylowlim; range[0].z = (double)elRange->zlowlim; range[1].x = (double)elRange->xhighlim; range[1].y = (double)elRange->yhighlim; range[1].z = (double)elRange->zhighlim; return range[0].Distance(range[1]) * 0.1; } /*---------------------------------------------------------------------------------**//** * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ double GetAngle() { // For testing purposes just use 10 degrees. This value would normally be supplied via tool settings. return Angle::DegreesToRadians(10.0); } /*---------------------------------------------------------------------------------**//** * Perform the solid operation using the accepted faces. * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ StatusInt DoOperation(ISolidKernelEntityPtr& entityPtr, bvector<ISubEntityPtr>& faces) { double distance = 0.0; for each (ISubEntityPtr subEntity in faces) { DPoint3d point; DVec3d normal1, normal2; if ((SUCCESS == SolidUtil::GetPlanarFaceData(&point, &normal1, *subEntity))) { normal2.x = pointDynamic.x - point.x; normal2.y = pointDynamic.y - point.y; normal2.z = pointDynamic.z - point.z; distance = std::abs(normal1.x * normal2.x + normal1.y * normal2.y + normal1.z * normal2.z); break; } } bvector<double> offsets; offsets.insert(offsets.begin(), faces.size(), distance); return SolidUtil::Modify::OffsetFaces(entityPtr, &faces.front(), &offsets.front(), faces.size()); } /*---------------------------------------------------------------------------------**//** * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ virtual StatusInt _OnElementModify(EditElementHandleR eeh) override { bvector<IElementGraphicsPtr> geomCache; // NOTE: Since we setup tool to only collect a single brep, we can just grab first cache entry... ISolidKernelEntityPtr entityPtr = (SUCCESS == GetElementGraphicsCache(eeh, geomCache) ? TryGetAsBRep(geomCache.front()) : NULL); if (!entityPtr.IsValid()) return ERROR; if (SUCCESS != DoOperation(entityPtr, GetAcceptedSubEntities())) return ERROR; return SolidUtil::Convert::BodyToElement(eeh, *entityPtr, &eeh, *eeh.GetModelRef()); } /*---------------------------------------------------------------------------------**//** * Install a new instance of the tool. Will be called in response to external events * such as undo or by the base class from _OnReinitialize when the tool needs to be * reset to it's initial state. * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ virtual void _OnRestartTool() override { InstallNewInstance(GetToolId(), m_operation); } virtual void _OnDynamicFrame(DgnButtonEventCR ev) override { pointDynamic = *ev.GetPoint(); if (GetElementAgenda().GetCount() > 0 && GetAcceptedSubEntities().size() > 0) { ElementHandleCP eeh = GetElementAgenda().GetFirstP(); //获取元素 bvector<IElementGraphicsPtr> geomCache; ISolidKernelEntityPtr entityPtr = (SUCCESS == GetElementGraphicsCache(*eeh, geomCache) ? TryGetAsBRep(geomCache.front()) : NULL); if (!entityPtr.IsValid()) return; bvector<ISubEntityPtr> faces = GetAcceptedSubEntities(); double distance = 0.0; for each (ISubEntityPtr subEntity in faces) { DPoint3d point; DVec3d normal1, normal2; if ((SUCCESS == SolidUtil::GetPlanarFaceData(&point, &normal1, *subEntity))) { normal2.x = pointDynamic.x - point.x; normal2.y = pointDynamic.y - point.y; normal2.z = pointDynamic.z - point.z; distance = std::abs(normal1.x*normal2.x + normal1.y*normal2.y + normal1.z*normal2.z); } } bvector<double> offsets; offsets.insert(offsets.begin(), faces.size(), distance); SolidUtil::Modify::OffsetFaces(entityPtr, &faces.front(), &offsets.front(), faces.size()); //if (SUCCESS != SolidUtil::Modify::OffsetFaces(entityPtr, &faces.front(), &offsets.front(), faces.size())) } } public: /*---------------------------------------------------------------------------------**//** * Method to create and install a new instance of the tool. If InstallTool returns ERROR, * the new tool instance will be freed/invalid. Never call delete on RefCounted classes. * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ static void InstallNewInstance(int toolId, ToolOperation operation) { TestModifyFaceTool* tool = new TestModifyFaceTool(toolId, operation); tool->InstallTool(); } }; // TestModifyFaceTool