当前位置:首页 > 帮助文档 > 网页开发 > 自定义实体
简介绘制自定义实体对象动态绘制自定义实体响应事件,动态绘制响应事件,绘制自定义实体响应事件,返回自定义实体夹点响应事件,夹点移动处理响应事件, 增加坐标变换功能响应事件,增加实体求交响应事件,增加捕捉
简介

在控件中除了内置的直线,圆,文字等实体外,开发人员还可以增加自定义实体。点击此处在线演示

绘制自定义实体对象

调用控件函数:DrawCustomEntity直接在图上,绘制自定义实体,如下js代码:

 

function  button2_Click()
    {
        // 调用DrawCustomEntity绘制一个自定义实体,实体类型字符串为:DrawCustEntity
        var ent = mxOcx.DrawCustomEntity("DrawCustEntity","");

        // 开始设置自定义实体的属性。
        ent.BeginSetValue();
        // 设置属性Width
        ent.SetDouble("Width", 30);
        var pt1 = mxOcx.NewPoint();
        pt1.x = 10;
        pt1.y = 10;
        var pt2 = mxOcx.NewPoint();
        pt2.x = 100;
        pt2.y = 200;
        // 设置属性Point1,Point2
        ent.SetPoint("Point1", pt1);
        ent.SetPoint("Point2", pt2);
        ent.SetLong("Count", 2);
        // 结束设置自定义实体的属性。
        ent.EntSetValue();
        // 更新显示
        mxOcx.UpdateDisplay();
    }

 

下面函数MyDrawMline,用来具体绘制自定义实体,将用在后面的事件中调用。

 

 // MyDrawMline,用来绘制我们的自定义实体
    function MyDrawMline(pWorldDraw, pCustomEntity, curPt)
    {
        // 取自定义实体的端点数目。
        if (!pCustomEntity.IsHave("Count"))
            return;
        var lCount = pCustomEntity.GetLong("Count");

        var tmpPl = mxOcx.NewEntity("IMxDrawPolyline");
        //var tmpPl = new MxDrawPolyline();

        for (var i = 0; i < lCount; i++)
        {
            var sName;
            sName = "Point" + (i + 1).toString();
            if (!pCustomEntity.IsHave(sName))
                break;
            // 取自定义实体的端点坐标。
            var pt = pCustomEntity.GetPoint(sName);
            // 把端点坐标,传给pl线,用于生成双线。
            tmpPl.AddVertexAt(pt);
        }
        if (curPt != null)
            tmpPl.AddVertexAt(curPt);
        if (tmpPl.NumVerts < 2)
        {
            // 端点数少于2就,不构成直线,就不需要显示。
            return;
        }
        // 求pl线,开始点的导数.
        var vecFx = tmpPl.GetFirstDeriv2(tmpPl.GetStartParam());
        if (!vecFx)
        return;

         if (vecFx.IsZeroLength())
             return;

        // 把向量旋转90度.
        vecFx.RotateByXyPlan(3.14159265 / 2.0);
        vecFx.Normalize();
        //  得到双线的宽度属性。
        var dWidth = pCustomEntity.GetDouble("Width");
        vecFx.Mult(dWidth);
        var startPt = tmpPl.GetStartPoint();
        // 向pl线,两个方向偏移,
        var offsetPt1 = mxOcx.NewPoint();
        offsetPt1.x = startPt.x;
        offsetPt1.y = startPt.y;
        offsetPt1.Add(vecFx);
        var offsetPt2 = mxOcx.NewPoint();
        offsetPt2.x = startPt.x;
        offsetPt2.y = startPt.y;
        offsetPt2.Sum(vecFx);
        var text = mxOcx.NewEntity("IMxDrawText");
        text.TextString = "Test";
        text.Height = 100;
        text.Position = startPt;
        text.AlignmentPoint = startPt;

        var pt1 = mxOcx.NewPoint();
        var pt2 = mxOcx.NewPoint();

        text.GetBoundingBox(pt1,pt2);
        var pt3 = mxOcx.NewPoint();
        pt3.x = pt1.x;
        pt3.y = pt2.y;
        var pt4 = mxOcx.NewPoint();
        pt4.x = pt2.x;
        pt4.y = pt1.y;
        var pts = mxOcx.NewComObject("IMxDrawPoints");
        pts.Add(pt1.x, pt1.y,0);
        pts.Add(pt3.x, pt3.y,0);
        pts.Add(pt2.x, pt2.y,0);
        pts.Add(pt4.x, pt4.y,0);
        var lDraworder = pWorldDraw.Draworder;
        pWorldDraw.Draworder = lDraworder + 1;
        pWorldDraw.DrawWipeout(pts);
        pWorldDraw.Draworder = lDraworder + 2;
        pWorldDraw.DrawEntity(text);
        pWorldDraw.Draworder = lDraworder;
        {
            var newobj =tmpPl.OffsetCurves2(dWidth, offsetPt1);
            if (newobj)
            {
                for (var j = 0; j < newobj.Count; j++)
                {
                    var tmpObj = newobj.AtObject(j);
                    if (tmpObj == null)
                        continue;
                    pWorldDraw.DrawEntity(tmpObj);
                }
                newobj.RemoveAll();
            }
        }
        {

            var newobj =tmpPl.OffsetCurves2(dWidth, offsetPt2);

            if (newobj)
            {
                for (var j = 0; j < newobj.Count; j++)
                {
                    var tmpObj = newobj.AtObject(j);
                    if (tmpObj == null)
                        continue;
                    pWorldDraw.DrawEntity(tmpObj);
                }
                // 这不使用newobj,需要显示调用RemoveAll函数清楚内存。
                // 不然这个可能就会程序退出时才释放,这时它会去释放控件对象指针,有可能会出错。
                newobj.RemoveAll();
            }
        }
    }
动态绘制自定义实体

下面代码让用户在图上循环点取点坐标,直接到按ESC退出,然后绘制自定义实体,在点取点过程中可以看动态画制效果,js代码实现如下:


function DrawMlineCommand()
    {
        // 定义取点变量。
        //MxDrawUiPrPoint getPt = new MxDrawUiPrPoint();
        var getPt = mxOcx.NewComObject("IMxDrawUiPrPoint");
        getPt.message = "点取第一点";
        // 等用户在图上点取一个点
        if (getPt.go() != 1)
        {
            return;
        }
        // 返回点的点对象值。
        var frstPt = getPt.value();
        if (frstPt == null)
        {
            return;
        }
        // 定义第二个取点变量。
        var getSecondPt = mxOcx.NewComObject("IMxDrawUiPrPoint");

        getSecondPt.message = "点取第二点";
        getSecondPt.basePoint = frstPt;
        getSecondPt.setUseBasePt(false);
        // 设置在取点时的动态绘制.
        var spDrawData = getSecondPt.InitUserDraw("DrawCustEntity");

        // 设置绘制变量。Width,Point1
        spDrawData.SetDouble("Width", 30);
        spDrawData.SetPoint("Point1", frstPt);
        var lCount = 1;
        spDrawData.SetLong("Count", 1);

        // 循环取点,直到用户按ESC取消.
        while (true)
        {
            if (getSecondPt.go() != 1)
                break;
            var secondPt = getSecondPt.value();
            if (secondPt == null)
                break;
            lCount++;
            var sPointName = "Point" + lCount.toString();
            spDrawData.SetPoint(sPointName, secondPt);
            spDrawData.SetLong("Count", lCount);
        }

        // 把自定义实本对象spDrawData画在图上。
        if (lCount > 1)
            mxOcx.DrawEntity(spDrawData);
    }
响应事件,动态绘制

添加控件DynWorldDraw事件,在事件中响应自定义实体的动态绘制,js代码实现如下:


 function DoDynWorldDrawFun(dX,dY,pWorldDraw, pData, pRet)
    {
        // 得到当前动态绘制数据。
        var pCustomEntity = pData;
        var sGuid = pCustomEntity.Guid;
        pRet = 0;

        // 得到当前鼠标点.
        var curPt = mxOcx.NewPoint();
        curPt.x = dX;
        curPt.y = dY;

        if (sGuid == "DrawCustEntity")
        {
            // 动态绘制DrawCustEntity
            MyDrawMline(pWorldDraw, pCustomEntity, curPt);
        }
    }
响应事件,绘制自定义实体

需要添加DMxDrawXEvents::CustomEntity_Explode事件,绘制自定义实体
注意:该事件必须实现,如果不实现自定义实体将不会保存到图纸中。
如:js代码实现如下:


function ExplodeFun(pCustomEntity,pWorldDraw, pRet)
    {
        // 得到自定义实体类型
        var sGuid = pCustomEntity.Guid;

        if (sGuid == "DrawCustEntity")
        {
            // 绘制自定义实体.
            MyDrawMline(pWorldDraw, pCustomEntity, null);
            pRet = 1;
        }
    }
响应事件,返回自定义实体夹点

自定义实体支持夹点编辑,下面事件返回实体的夹点
需要响应_DMxDrawXEvents::CustomEntity_getGripPoints事件,js代码实现如下:


function GetGripPointsFun(pCustomEntity, pOk)
    {
        // 得到自定实体类型
        var sGuid = pCustomEntity.Guid;
        pOk = 0;
        if (sGuid == "DrawCustEntity")
        {
            if (!pCustomEntity.IsHave("Count"))
                return;

            var lCount = pCustomEntity.GetLong("Count");

            // 把需要的夹点数据,放在ret链表中,用于返回
            var ret = mxOcx.NewResbuf();

            for (var i = 0; i < lCount; i++)
            {
                var sName;
                sName = "Point" + (i + 1).toString();
                if (!pCustomEntity.IsHave(sName))
                    break;
                // 取自定义实体的端点坐标。
                var pt = pCustomEntity.GetPoint(sName);
                ret.AddPoint(pt);
            }
            pOk = 1;
            // 返回夹点数据。
            mxOcx.SetEventRetEx(ret);
        }
    }
响应事件,夹点移动处理

自定义实体夹点移动后,调用moveGripPointsAt事件修改自定义实体。
响应CustomEntity_moveGripPointsAt事件。
下面例子夹点移动后,在moveGripPointsAt修改自定义实体的点坐标,js代码实现如下:


function MoveGripPointsFun(pCustomEntity, lGridIndex, dOffsetX, dOffsetY)
    {
        pRet = 1;
        // 得到自定义实体对像.
        var sGuid = pCustomEntity.Guid;

        if (sGuid == "DrawCustEntity")
        {
            if (!pCustomEntity.IsHave("Count"))
                return;

            var lCount = pCustomEntity.GetLong("Count");

            for (var i = 0; i < lCount; i++)
            {
                var sName;
                sName = "Point" + (i + 1).toString();
                if (!pCustomEntity.IsHave(sName))
                    break;

                // 取自定义实体的端点坐标。
                var pt = pCustomEntity.GetPoint(sName);

                // e.lGridIndex表示移动了第几个夹点.
                if (i == lGridIndex)
                {
                    pt.x = pt.x + dOffsetX;
                    pt.y = pt.y + dOffsetY;

                    // 修改移动后的点坐标值。
                    pCustomEntity.SetPoint(sName, pt);
                }
            }
        }
    }
响应事件, 增加坐标变换功能

想要支持自定义实体的移动,旋转,缩放功能,需要添加坐标变换事件处理,事件名:CustomEntity_transformBy


document.getElementById("MxDrawXCtrl").ImpTransformByFun = TransformByFun;


函数实现js代码如下:


function TransformByFun(pCustomEntity, pMatXform, pOk)
    {
        pOk = 1;
        // 得到自定义实体类型
        var sGuid = pCustomEntity.Guid;

        if (sGuid == "DrawCustEntity")
        {
            if (!pCustomEntity.IsHave("Count"))
                return;
            var lCount = pCustomEntity.GetLong("Count");

            // 对实体的点坐标进行坐标变换。
            for (var i = 0; i < lCount; i++)
            {
                var sName;
                sName = "Point" + (i + 1).toString();
                if (!pCustomEntity.IsHave(sName))
                    break;
                // 取自定义实体的端点坐标。
                var pt = pCustomEntity.GetPoint(sName);
                // 计算出新的坐标。
                pt.TransformBy(pMatXform);
                pCustomEntity.SetPoint(sName, pt);
            }
        }
    }
响应事件,增加实体求交

如果需要捕捉两个实体的交点,需要响应自定义实体求交事件:CustomEntity_intersectWith
下面js代码响应求交事件,然后得到自定义实体,计算出交点返回:


function IntersectWithFun(pCustomEntity, pOhterEntity, pOk)
    {
        // 得到自定义实体。
        var pThis = pCustomEntity;
        // 得到另一个求交的实体。
        var pOther = pOhterEntity;
        if (pThis.ObjectName != "MxDrawXCustomEntity" || pOther.ObjectName != "MxDrawXCustomEntity")
            return;
        var pEnt1 = pThis;
        var pEnt2 = pOther;

        // 判断自定义有没有我们需要的属性。
        if (!pEnt1.IsHave("Point1"))
            return;
        if (!pEnt1.IsHave("Point2"))
            return;

        if (!pEnt2.IsHave("Point1"))
            return;
        if (!pEnt2.IsHave("Point2"))
            return;

        // 取自定义实体的端点坐标。
        var pt11 = pEnt1.GetPoint("Point1");
        var pt12 = pEnt1.GetPoint("Point2");
        var pt21 = pEnt2.GetPoint("Point1");
        var pt22 = pEnt2.GetPoint("Point2");
        // 创建两个临时的直线,用来求交点。
        var line1 = mxOcx.NewComObject("IMxDrawLine");
        line1.StartPoint = pt11;
        line1.EndPoint = pt12;


        var line2 = mxOcx.NewComObject("IMxDrawLine");
        line2.StartPoint = pt21;
        line2.EndPoint = pt22;
        // 返回求到的交点。
        var pts = line1.IntersectWith(line2, MCAD_McExtendOption.mcExtendNone);
        if(pts.Count > 0 )
        {
            var ret = mxOcx.NewResbuf();

            for (var i = 0; i < pts.Count; i++)
            {
                ret.AddPoint(pts.Item(i));
            }
            // 告诉控件,求到了交点。
            pOk = 1;
            mxOcx.SetEventRetEx(ret);
        }
    }


3.jpg

响应事件,增加捕捉

如果需要捕捉自定义实体的端点,最近点等,需要响应捕捉事件:CustomEntity_getOsnapPoints
如下js代码,返回自定义实体的端点,计算最近点并返回。


function GetOsnapPointsFun(pCustomEntity, lOsnapMode, dPickPointX,dPickPointY,pSnapPointsX,  pSnapPointsY, pOk)
    {
        //         enum OsnapMode         { kOsModeEnd          = 1,
        //             kOsModeMid          = 2,
        //             kOsModeCen          = 3,
        //             kOsModeNode         = 4,
        //             kOsModeQuad         = 5,
        //             kOsModeIns          = 7,
        //             kOsModePerp         = 8,
        //             kOsModeTan          = 9,
        //             kOsModeNear         = 10,
        //             kOsModeInt          = 11
        //         };
        pOk = 0;

        // 得到自义实体对象。
        var sGuid = pCustomEntity.Guid;

        if (sGuid == "DrawCustEntity")
        {
            if (!pCustomEntity.IsHave("Count"))
                return;

            // 得到点数.
            var lCount = pCustomEntity.GetLong("Count");

            if (lCount < 2)
                return;

            if (lOsnapMode == 1)
            {
                // 端点捕捉。
                var pickPoint = mxOcx.NewPoint();

                // 得到当前鼠标点。
                pickPoint.x = dPickPointX;
                pickPoint.y = dPickPointY;

                // 得到开始点,结束点。
                var sName = "Point1";
                var stp = pCustomEntity.GetPoint(sName);
                sName = "Point" + lCount.toString();
                var ept = pCustomEntity.GetPoint(sName);

                // 计算出当前点与那个点最近,然后返回.
                var dDis1 = pickPoint.DistanceTo(stp);
                var dDis2 = pickPoint.DistanceTo(ept);

                if (dDis1 < dDis2)
                {
                    pSnapPointsX = stp.x;
                    pSnapPointsY = stp.y;
                }
                else
                {
                    pSnapPointsX = ept.x;
                    pSnapPointsY = ept.y;
                }

                pOk = 1;

            }
            else if (lOsnapMode == 10)
            {
                // 最近点捕捉。
                var pl = mxOcx.NewEntity("IMxDrawPolyline");

                // 把自定义实体变成一个 PL线,用于计算最近点坐标。
                for (var i = 0; i < lCount; i++)
                {
                    var sName;
                    sName = "Point" + (i + 1).toString();
                    if (!pCustomEntity.IsHave(sName))
                        break;

                    // 取自定义实体的端点坐标。
                    var pt = pCustomEntity.GetPoint(sName);

                    pl.AddVertexAt(pt);

                }

                // 得到当前鼠标点。
                var pickPoint = mxOcx.NewPoint();

                pickPoint.x = dPickPointX;
                pickPoint.y = dPickPointY;


                // 计算最近点。
                var closePoint = pl.GetClosestPointTo2(pickPoint, false);

                if (closePoint != null)
                {
                    // 计算最点,然后返回。
                    pSnapPointsX = closePoint.x;
                    pSnapPointsY = closePoint.y;
                    pOk = 1;
                }
            }
        }
    }


2.png

梦想CAD是专业的CAD插件(控件),可轻松在网页、手机及BS/CS程序中浏览编辑DWG文件,不需安装AutoCAD即可运行。经十余年累积已非常稳定可靠,有关键的空间搜索算法,并使用汇编优化,可同时处理50万级实体,有非常高的图形显示和处理效率。
联系我们
技术TEL:400-888-5703
185-8173-1060
客服 QQ: 3570505660
技术 QQ: 6884123
VIP服务购买
销售TEL:156-8136-8971
销售QQ:710714273
梦想绘图资讯
梦想绘图更新通知群Ⅰ:73281982
梦想绘图更新通知群Ⅱ:112199959
MxCAD云图更新通知群Ⅰ:515771658(已满)
MxCAD云图更新通知群Ⅱ:1043121488
技术I:QQ
6884123
客服I:QQ
3570505660
销售QQ
710714273
联系电话400-888-5703