70002424 Osnaps improvements

Article 70002424
Type Wish
Product Engine
Version 1004
Date Added 10/19/2023 12:00:00 AM
Fixed 10.1005.0.2 (10/23/2023 12:00:00 AM)
Submitted by Ferhat Altun

Summary

Improve osnaps .

Solution

In version 1005.0.2 Osnaps was improved
vdConst.OsnapMode_NEA is working with a geometric precision for line, arcs, polylines , circle rect objects .
Also Osnaps improved to working better for entities inside blocks
New properties cursorptview , object2world, world2view was added to OnCustomGetOsnaps event arguments in order to support custom implementation for vdConst.OsnapMode_NEA see following example
cursorptview :The current mouse cursor position in View Coordinate System
object2world : Matrix used to transform from entitiy Coordinate System to World
world2view: Active rendering world toview matrix
Also new utility methods linenearest and projectionTomatrix of vdgeo object was added
vdgeo.linenearest(sp,ep,pickpoi) :returns the nearest of a pick point to a line segment
vdgeo.projectionTomatrix(pt,elevation,matrix) : projects the passed point to a plane defined by the passed matrix.The passed point is updated with new coordinates relative to te passed plane after the method returns
NOTE:if vdConst.OsnapMode_NEA the control is trying to find a geometric precision osnap and if not returns the transformation of the pixel point with saved z buffer with different symbolic drawing.
NOTE: when webgl is active in 3d render modes osnaps for objects inside blocks is not working Also osnaps are limited for polyline and polyface objects up to 32 sub items( segments or faces)


Example implement osnaps of a custom object that draws a cross

var vdcanvas;
function vdrawInitPageLoad() {//Intiallize theweb control inside this function.It must be called inside onload event of this page
            vdcanvas = vdmanager.AttachCanvas("canvas"); //create a new web control andattch it to the canvas elemement
            //additional requaired properties and methods calls (see web examples)
            /IFollow Initialze events for custom objects
             vdcanvas.OnCustomDraw = OnCustomDraw;
             vdcanvas.OnIsCustom = OnIsCustom;
             vdcanvas.OnCustomGetGrips = OnCustomGetGrips;
             vdcanvas.OnCustomMovegrips = OnCustomMovegrips;
             vdcanvas.OnCustomGetOsnaps = OnCustomGetOsnaps;
        }
 //method that starts a user command to draw a new cross custom object
        //call this method from a button in your html page to begin a user action that draws a cross entity
        function CustomCrossCommand() {
            vdcanvas.ActiveAction().cancel();
            vdcanvas.GetUserPoint(Action_Cross);
        }

        function OnCustomGetOsnaps(args) {
            var fig = args.entity;
            var ret = [];
            if (fig._t === 1002) {//if figure is cross
                args.innerosnaps.length = 0; //remove existing sub entities osnaps.NOTE:If not then keep them and add additionals as follow
                //add the object NODE osnap
                if ((args.osnapmode & vdConst.OsnapMode_NODE)) {
                    ret.push([fig.center[X], fig.center[Y], fig.center[Z], vdConst.OsnapMode_NODE]);
                }
                if ((args.osnapmode & vdConst.OsnapMode_NEA)) {
                    var object2view = vdgeo.matrixmult(args.object2world, args.world2view);
                    var view2object = vdgeo.matrixGetInversion(object2view);

                    var cursorpt = vdgeo.matrixtransform(view2object, args.cursorptview);
                    vdgeo.projectionTomatrix(cursorpt, fig.center[Z], view2object);
                    var sp = vdgeo.pointPolar(fig.center, vdgeo.HALF_PI, -fig.size);
                    var ep = vdgeo.pointPolar(fig.center, vdgeo.HALF_PI, fig.size)
                    var pt = vdgeo.linenearest(sp, ep, cursorpt);
                    ret.push([pt[X], pt[Y], pt[Z], vdConst.OsnapMode_NEA]);

                    var sp = vdgeo.pointPolar(fig.center, vdgeo.PI, -fig.size);
                    var ep = vdgeo.pointPolar(fig.center, vdgeo.PI, fig.size)
                    var pt = vdgeo.linenearest(sp, ep, cursorpt);
                    ret.push([pt[X], pt[Y], pt[Z], vdConst.OsnapMode_NEA]);

                    
                }
            }
            return ret;
        }
        //event that implement how the grips of each of custom figure are moved
        function OnCustomMovegrips(args) {
            var fig = args.entity;
            var indexes = args.indexes;
            var offset = args.offset;
            var vdraw = args.sender;
            if (fig._t === 1002) {//if figure is cross
                var ret = true;
                fig.center[X] += offset[X];
                fig.center[Y] += offset[Y];
                fig.center[Z] += offset[Z];
            }
            if (ret) vdraw.UpdateFig(fig, true);
            return ret;
        }

        //event that defines the grips of each of custom objects
        //the grips are seted to the fig.grips property collection
        function OnCustomGetGrips(args) {
            var fig = args.entity;
           if (fig._t === 1002) {//if figure is cross
                if (fig.grips === undefined) {
                    fig.grips = [fig.center];
                }
            }
            return fig.grips;
        }
        //event that check the figures that are customized by the user code
        function OnIsCustom(args) {
            var fig = args.entity;
            return fig._t === 1002;
        }
        //event that is called for each custom entity draw
        //note:user must add drawing primitives entities to the fig.Explode property as follow
        function OnCustomDraw(args) {
            var fig = args.entity;
            var vdraw = args.sender;
           if (fig._t === 1002) {//if figure is a cross
                var l1 = vdraw.AddLine(vdgeo.pointPolar(fig.center, vdgeo.HALF_PI, -fig.size), vdgeo.pointPolar(fig.center, vdgeo.HALF_PI, fig.size), false, {});
                l1.PenColor = vdConst.colorFromString("byblock");
                l1.LineWeight = vdConst.LW_BYBLOCK;
                l1.LineType = 'h_' + vdraw.FindLineType("byblock").HandleId.toString();
                var l2 = vdraw.AddLine(vdgeo.pointPolar(fig.center, vdgeo.PI, -fig.size), vdgeo.pointPolar(fig.center, vdgeo.PI, fig.size), false, {});
                l2.PenColor = vdConst.colorFromString("byblock");
                l2.LineWeight = vdConst.LW_BYBLOCK;
                l2.LineType = 'h_' + vdraw.FindLineType("byblock").HandleId.toString();
                fig.Explode = { Items: [l1, l2] };

            }
        }

        //utilty method to create a custom object with all needed common properties
        function create_custom_fig(vdrawobj, typeid, typename) {
            var layout = vdrawobj.GetActiveLayout();
            if (layout == null) return null;
            var vddoc = vdrawobj.GetDocument();
            var customentity = { _t: typeid, CustomType: typename };
            customentity.LineType = vddoc.ActiveLineType;
            customentity.Layer = vddoc.ActiveLayer;
            customentity.PenColor = vdConst.cloneEntity(vdrawobj.GetActivePenColor());
            customentity.PenWidth = vddoc.ActivePenWidth;
            customentity.LineWeight = vddoc.ActiveLineWeight;
            if (vddoc.ActiveLineTypeScale) customentity.LineTypeScale = vddoc.ActiveLineTypeScale;
            return customentity;

        }

        
        //method that begins a user action for custom cross object
        function Action_Cross(action, status) {

            var vdrawObj = action.vdrawOwner();
            if (!action.customMode) action.customMode = 'centerpoint';
            if (action.customMode == "centerpoint") {
                if (status == 'start') {
                    vdrawObj.Prompt("Pick center point:");
                }
                else if (status == 'end') {
                    vdrawObj.Prompt('');
                    if (!action.IsCanceled()) {
                        var pt = action.SelectedPoint();
                        action.Figure = create_custom_fig(vdrawObj, 1002, "vds.customCross");
                        action.Figure.center = pt;

                        action.customMode = 'size';
                        vdrawObj.GetUserLine(Action_Cross, pt);
                    }
                    else {
                        action.customMode = null;
                        action.Figure = null;
                    }
                }
            }
            else if (action.customMode == 'size') {
                if (status == 'start') {
                    vdrawObj.Prompt('Pick end Point of size:');
                }
                else if (status == 'end') {
                    vdrawObj.Prompt('');
                    if (!action.IsCanceled()) {
                        var pt = action.SelectedPoint();
                        action.Figure.size = vdgeo.Distance2D(action.SelectedPoint(), action.Figure.center);

                        vdrawObj.UpdateFig(action.Figure);

                        vdrawObj.ActionDrawEntities([action.Figure]);
                        if (!action.Figure.HandleId)
                            vdrawObj.scriptCommand.RegisterFigure(action.Figure);


                    }
                    vdrawObj.DrawEntity(action.Figure);
                    vdrawObj.Refresh();
                    action.customMode = null;
                    action.Figure = null;

                }
                else if (status == 'draw') {
                    if (action.Figure) {
                        var render = action.render;
                        action.Figure.size = vdgeo.Distance2D(action.DrawPoint(), action.Figure.center);
                        vdrawObj.UpdateFig(action.Figure);
                        vdrawObj.DrawEntity(action.Figure, render);
                        vdrawObj.UpdateFig(action.Figure);
                    }
                }
            }
        }

Send comments on this topic.