How to check if created CurveVector contains knots after CurveOffset function? CONNECT

Hello guys! 

Lately I have been playing around with the Solids interface in the new CONNECT API and trying to play with CurveOffset to make a smaller version of complex shapes I have. However, I found a problem:

As you can see in the picture, shape drawn with the bold line is the original and the thin shape is the element created with my code : 

CurveOffsetOptions options(dist);
options.SetTolerance(tolerance);

CurveVectorPtr offset = bodyPath->CloneOffsetCurvesXY(options);

As you can see it contains these weird knots, caused by the function i called. When I use the AreaOffset function, all works fine, however I would like to detect it automatically from the code, that the created shape contains these weird shapes and only then use AreaOffset. Is there a way to do it from the code instead of looking at the element in the DGN?
Thanks in advance.

Parents Reply Children
  • Thanks for your answer! However. is there a way to use the CurveVector API or SolidUtils to achieve the same functionality? Or, how do I use this function when I have ISolidKernelEntityPtr from ElementToBody function from SolidUtil namespace?

  • is there a way to use the CurveVector API or SolidUtils to achieve the same functionality?

    IMO, No. SolidUtils doesn't wrap mdlSolid_offsetWire function.

    I found a very old thread to discuss same topic before, where I provided a V8XM version runnable code. We need to revise this code on CE.

    communities.bentley.com/.../mdl-v8xm-i-copy-parallel-using-miter-mode



  • I´ve tried following code:

    double tol = 0.5;
    BODY_TAG pWireBody;
    int status = mdlSolid_elementToBody(&pWireBody, nullptr, inDscr, MASTERFILE);
    if (mdlSolid_isSheetBody(pWireBody))
    {
        int numFaces;
        TAG_ENTITY_LIST* pFaceList;
        status = mdlSolid_listCreate(&pFaceList);
        mdlSolid_getFaceList(pFaceList, pWireBody);
        status = mdlSolid_listCount(&numFaces, pFaceList);
        for (auto i = 0; i < numFaces; i++)
        {
            FACE_TAG pFace;
            status = mdlSolid_listNthEl(&pFace, pFaceList, i);
            status = mdlSolid_uncoverFace(pFace);
        }
        status = mdlSolid_listDelete(&pFaceList);
    }
    
    if (SUCCESS != status || !mdlSolid_isWireBody(pWireBody))
    {
        if (pWireBody)
             mdlSolid_freeBody(pWireBody);
        return ERROR;
    }
     
     EDGE_TAG pEdge = NULL;
     auto statusOffset = mdlSolid_bodyAskFirstEdge(&pEdge, pWireBody);
     if (NULL == pEdge)
     {
        mdlSolid_freeBody(pWireBody);
        return ERROR;
     }
     TAG_ENTITY_LIST* pList = nullptr; 
     status = mdlSolid_listCreate(&pList);
     mdlSolid_beginCurrTrans(ACTIVEMODEL);
     mdlCurrTrans_invScaleDoubleArray(&distance, &distance, 1);
     mdlCurrTrans_invScaleDoubleArray(&tol, &tol, 1);
     mdlSolid_endCurrTrans();
     
     if (SUCCESS == mdlSolid_wireIsG1(pWireBody))
     {
        gapFill = 0;
     } 
     
     statusOffset = mdlSolid_offsetWire(pList, pWireBody, pEdge, normal, 1, tol, gapFill, FALSE);
    However the mdlSolid_offsetWire function returns error code 5019 and it tells me nothing about whats wrong. (Or maybe im missing some documentation which explains what this error code means). Or am i setting the body tag/body incorrectly? As you can see i check the status everywhere and debugged it, but it returns SUCCESS until the offsetWIre method is called.

  • I managed to get through the problem I mentioned above, but even after i rewrote the algorithm  mentioned in his link, it cannot add element or element descriptor into model. Am i missing something ? There is a code:

    int CreateElementByBody(MSElementDescr** resultEdp, BODY_TAG* pBody)
    {
        *resultEdp = NULL;
        BODY_TAG pCopy;
        mdlSolid_copyBody(&pCopy, *pBody);
        bool simplified = false;
        if (SUCCESS == mdlSolid_simplifyBody(&pCopy, FALSE))
            simplified = true;
        if (SUCCESS != mdlSolid_bodyToElement(resultEdp, simplified ? pCopy : *pBody,
            TRUE, -1, -1, 0, NULL, ACTIVEMODEL) || NULL == *resultEdp)
        {
            if (NULL != pCopy)
                mdlSolid_deleteEntity(pCopy);
            return ERROR;
        }
        if (NULL != pCopy)
            mdlSolid_deleteEntity(pCopy);
        return (NULL == *resultEdp) ? ERROR : SUCCESS;
    }
    
    MdlPublic  int mdlElmdscr_copyParallelExt
    (
        MSElementDescr** outDscr,
        MSElementDescr*  inDscr,
        double           distance,
        DPoint3d*        normal,
        int              gapFill    // 0 for arc fill, 1 for tangent extension fill, 2 for curve extension fill
    )
    {
        BODY_TAG pWireBody;
        int status = mdlSolid_elementToBody(&pWireBody, nullptr,inDscr, MASTERFILE);
    
        if (mdlSolid_isSheetBody(pWireBody))
        {
            int numFaces;
            TAG_ENTITY_LIST* pFaceList = nullptr;
    
            status = mdlSolid_listCreate(&pFaceList);
            mdlSolid_getFaceList(pFaceList, pWireBody);
            status = mdlSolid_listCount(&numFaces, pFaceList);
            for (auto i = 0; i < numFaces; i++)
            {
                FACE_TAG pFace;
    
                status = mdlSolid_listNthEl(&pFace, pFaceList, i);
                status = mdlSolid_uncoverFace(pFace);
            }
            status = mdlSolid_listDelete(&pFaceList);
        }
    
    
        if (SUCCESS != status || !mdlSolid_isWireBody(pWireBody))
        {
            if (pWireBody)
                mdlSolid_freeBody(pWireBody);
            return ERROR;
        }
        EDGE_TAG pEdge;
        mdlSolid_bodyAskFirstEdge(&pEdge, pWireBody);
        if (NULL == pEdge)
        {
            mdlSolid_freeBody(pWireBody);
            return ERROR;
        }
    
        TAG_ENTITY_LIST* pList = NULL;
        mdlSolid_listCreate(&pList);
    
        double tol = 0.1;
        mdlSolid_beginCurrTrans(ACTIVEMODEL);
        mdlCurrTrans_invScaleDoubleArray(&distance, &distance, 1);
        mdlCurrTrans_invScaleDoubleArray(&tol, &tol, 1);
        mdlSolid_endCurrTrans();
    
        if (SUCCESS != mdlSolid_offsetWire(pList, pWireBody, pEdge, normal, distance, tol, gapFill, FALSE))
        {
            mdlSolid_freeBody(pWireBody);
            mdlSolid_listDelete(&pList);
            return ERROR;
        }
        int count = 0;
        mdlSolid_listCount(&count, pList);
        for (int i = 0; i < count; i++)
        {
            BODY_TAG pBody;
            MSElementDescr*   tempEdp = NULL;
            mdlSolid_listNthEl(&pBody, pList, i);
            if (SUCCESS != CreateElementByBody(&tempEdp, &pBody) || NULL == tempEdp)
            {
                if (NULL != tempEdp)
                {
                    mdlElmdscr_freeAll(&tempEdp);
                    tempEdp = NULL;
                }
                continue;
            }
            mdlElmdscr_initOrAddToChain(outDscr, tempEdp);
        }
        mdlSolid_listDelete(&pList);
        return (NULL == *outDscr) ? ERROR : SUCCESS;
    }

    Thanks for any kind of input, im kinda without ideas.

  • I wrote below test code, it works well in 3D model.

    void OffsetWire()
    {
    	if (!SelectionSetManager::GetManager().IsActive())
    	{
    		mdlDialog_dmsgsPrint(L"No selection set found");
    		return;
    	}
    	ElementRefP elemRef = nullptr;
    	DgnModelRefP modelRef = nullptr;
    	SelectionSetManager::GetManager().GetElement(0, &elemRef, &modelRef);
    	ElementHandle eh(elemRef, modelRef);
    
    	double offsetDist = 1000, tolerance = 0.5;
    
    	mdlSolid_beginCurrTrans(ACTIVEMODEL);
    	BODY_TAG  body;
    	Transform trans;
    	mdlSolid_elementToBody(&body, &trans, const_cast<MSElementDescrP>(eh.GetElementDescrCP()), ACTIVEMODEL);
    	if (mdlSolid_isSheetBody(body))
    	{
    		int numFaces = 0;
    		TAG_ENTITY_LIST* pFaceList = NULL;
    		mdlSolid_listCreate(&pFaceList);
    		mdlSolid_getFaceList(pFaceList, body);
    		mdlSolid_listCount(&numFaces, pFaceList);
    		for (int i = 0; i < numFaces; i++)
    		{
    			FACE_TAG pFace = NULL;
    			mdlSolid_listNthEl(&pFace, pFaceList, i);
    			mdlSolid_uncoverFace(pFace);
    		}
    		mdlSolid_listDelete(&pFaceList);
    	}
    	TAG_ENTITY_LIST* pOffsetList;
    	mdlSolid_listCreate(&pOffsetList);
    	EDGE_TAG  pEdge;
    	mdlSolid_bodyAskFirstEdge(&pEdge, body);
    	DPoint3d normal = DPoint3d::From(0, 0, 1);
    	mdlCurrTrans_invScaleDoubleArray(&offsetDist, &offsetDist, 1);
    	mdlCurrTrans_invScaleDoubleArray(&tolerance, &tolerance, 1);
    	int gapFill = (SUCCESS == mdlSolid_wireIsG1(body)) ? 0 : 1;
    	if (SUCCESS != mdlSolid_offsetWire(pOffsetList, body, pEdge, &normal, offsetDist, tolerance, gapFill, false))
    		mdlDialog_dmsgsPrint(L"mdlSolid_offsetWire failed");
    	else
    		for (TAG_ENTITY_LIST::iterator iter = pOffsetList->begin(); iter != pOffsetList->end(); ++iter)
    		{
    			if (mdlSolid_isWireBody((*iter)))
    			{
    				MSElementDescrP elmdscr = NULL;
    				mdlSolid_bodyToElement(&elmdscr, (*iter), true, 0, 0, 0, NULL, ACTIVEMODEL);
    				mdlElmdscr_transform(&elmdscr, &trans);
    				EditElementHandle eeh(elmdscr, true, false);
    				eeh.AddToModel();
    			}
    		}
    	mdlSolid_listDelete(&pOffsetList);
    	mdlSolid_freeBody(body);
    	mdlSolid_endCurrTrans();
    }



    Answer Verified By: Lubo B 

  • Thanks! That helped me a lot and also solved my problem.