ILNumerics Ultimate VS

PanelPickPrimitiveAt Method

ILNumerics Ultimate VS Documentation
ILNumerics - Technical Application Development
Pick primitive(s) below specific screen position

[ILNumerics Visualization Engine]

Namespace:  ILNumerics.Drawing
Assembly:  ILNumerics.Drawing (in ILNumerics.Drawing.dll) Version: ILNumerics Ultimate VS 4
Syntax

public IPickingResult PickPrimitiveAt(
	Drawable drawable,
	Point point,
	long time = 0,
	bool ignoreLogAxis = false
)

Parameters

drawable
Type: ILNumerics.DrawingDrawable
The shape to pick the primitive from
point
Type: System.DrawingPoint
Windows coordinates of the point to pick
time (Optional)
Type: SystemInt64
[Optional] time frame for rendering (for animations only)
ignoreLogAxis (Optional)
Type: SystemBoolean
[Optional] true: never log() vertex data returned, even for logaritmic log axis scales. Default: false

Return Value

Type: IPickingResult
Interface giving access to detailed information of the primitive(s) found
Remarks

PickPrimitiveAt(Drawable, Point, Int64, Boolean) finds all primitives below the position given in point which belong to the drawable object specified in drawable. In difference to PickAt(Point, Int64) which only finds the drawable, i.e. the shape or the label below the window position, PickPrimitiveAt(Drawable, Point, Int64, Boolean) finds all primitives within that drawable. This allows the identification of individual tiles (triangles), line segments and individual points of arbitrary shapes. Detailed information is given for the primitives found, including vertex data in object and screen coordinates, order of the primitives relative to the camera and interpolated position data.

If drawable is null, a regular picking operation is performed first in order to identify the closest drawable object under point and the primitives are picked from that afterwards.

point is expected in window (pixel) coordinates. All mouse events provide the window position in the [!:MouseEventArgs.Location] property. Note, that the origin (0,0) for window coordinates lays in the upper left corner of the window.

If the drawable is displayed in the context of a plot cube with logarithmic axis scales the vertex data returned are also logarithmic. Therefore, they reflect the rendered position rather than the original data specified for the object. If this is not intended, one can set the ignoreLogAxis flag to true and the data returned in VerticesWorld will correspond to the actual data specified by the user and not be logarithmic. Note that the vertex screen data returned in VerticesScreen will always correspond to the logarithmic representation in that context, regardless of the setting of ignoreLogAxis.

[ILNumerics Visualization Engine]

Examples

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ILNumerics; 
using ILNumerics.Drawing; 
using ILNumerics.Drawing.Plotting;



namespace WindowsFormsApplication3 {

    // Picking Example. The application creates a surface in a plot cube. It registers several event handler 
    // demonstrating the picking of primitives and the interactive manipulation of the scene to display 
    // the picking results. A small blue dot is moving below the mouse at interpolated positions. A larger red dot 
    // is placed at the nearest vertex to the mouse. Hovering over the red dot displays a tool tip with the position 
    // value of the vertex in a screen overlay.  
    // 
    // Create a new WindowsForms application and paste the content of the following class into it. Start the application
    // and move the mouse over the surface. Watch the values and positions of the red and blue dot change. Hover 
    // over the red dot. A tool tip window is shown displaying the values of its position. 
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        // attributes: red point marking vertices, blue for interpolated value
        Points m_pointsRed, m_pointsBlue;
        // a screen object is used as tool tip label
        ScreenObject m_labelObj;  

        // this is the regular panel load event handler
        private void ilPanel1_Load(object sender, EventArgs e) {
            // setup objects
            m_pointsRed = new Points("MarkVertex") {
                Color = Color.Red,
                Size = 10
            };
            m_pointsBlue = new Points("MarkPosition") {
                Color = Color.Blue,
                Size = 3
            };
            // the tooltip label is placed inside an ScreenObject
            m_labelObj = new ScreenObject("LabelObj") {
                Children = { 
                    new Label(tag: "Label") {
                        // centered in the screen object
                        Position = new Vector3(.5f,.5f,0),
                        Anchor = new PointF(.5f,.5f)
                    }
                },
                // disable interactive movement of the screen object
                Movable = false,
                // displace slightly away from the mouse 
                Anchor = new PointF(-0.05f,-0.05f),
                Width = 150,
                Height = 30,
                Visible = false
            }; 
            // create some test data
            Array<float> C = SpecialData.sincf(20, 30, 3);
            C["2:5;10:14"] = 1;  // make it more interesting

            // add objects to the scene
            ilPanel1.Scene.Add(new PlotCube(twoDMode: false) {
                new Surface(C),
                // dots and tool tip go into a separated  group
                // so we can render them on top of the surface
                new Group(target: RenderTarget.Screen2DFar) { 
                    m_pointsRed, m_pointsBlue, m_labelObj
                }
            });
            // wire up events 
            ilPanel1.Scene.First<Surface>().MouseMove += ilSurface1_MouseMove;
            m_pointsRed.MouseEnter += m_pointsRed_MouseEnter;
            m_pointsRed.MouseLeave += m_pointsRed_MouseLeave;
        }

        void m_pointsRed_MouseEnter(object sender, MouseEventArgs e) {
            // fetch reference to the tool tip label
            var label = m_labelObj.First<Label>(tag: "Label");
            if (label != null) {
                // display the position of the red dot in the tool tip
                label.Text = m_pointsRed.Positions.GetPositionAt(0).ToString();
                m_labelObj.Location = e.LocationF;
                m_labelObj.Visible = true;
                // always need to Configure() after changes
                m_labelObj.Configure();
                // redraw the scene
                ilPanel1.Refresh();
            }
        }
        void m_pointsRed_MouseLeave(object sender, MouseEventArgs e) {
            m_labelObj.Visible = false;
            // always need to Configure() after changes
            m_labelObj.Configure();
            // redraw the scene
            ilPanel1.Refresh();
        }

        void ilSurface1_MouseMove(object sender, MouseEventArgs e) {
            // perform picking of the primitives below the cursor
            using (var pick = ilPanel1.PickPrimitiveAt(e.Target as Drawable, e.Location)) {

                // TODO: we do perform only simple checks for 'pick' containing data for triangles here. In 
                // a production environment, you should do more extensive checks! Otherwise, 
                // this functions may gets triggered while moving over points or lines of your 
                // scene and below code does not work! Below code expects triangles only.
                if (ILMath.isempty(pick.NextVertex) || pick.VerticesScreen.S[0] != 3) {
                    return; 
                }
                try {
                    // Move the red dot to nearest vertex. pick.NextVertex[0] gives the 
                    // index for the closest primitive in pick.VerticesWorld (row index). 
                    // "0:2" addresses the X,Y and Z values for the vertex in the corrresponding row. 
                    // The third dimension '0' means: the first primtive, which will always be the 
                    // one closest to the camera. 
                    m_pointsRed.Positions.Update(pick.VerticesWorld[pick.NextVertex[0], "0:2", 0][":"]);
                    // compute interpolated point: use the barycentric coordinates provided in 
                    // Vertices["0,1;3;0"] in order to interpolate any value over the triangle 
                    // for the picked point. 
                    float s = pick.VerticesWorld.GetValue(0, 3);
                    float v = pick.VerticesWorld.GetValue(1, 3);
                    // The third barycentric coordinate is not stored. You can compute it easily 
                    // using the following formula: 
                    float t = 1 - s - v;
                    // interpolate: here, we interpolate the position 
                    Array<float> interp = pick.VerticesWorld["0;0:2;0"] * s
                                          + pick.VerticesWorld["1;0:2;0"] * v
                                          + pick.VerticesWorld["2;0:2;0"] * t;
                    m_pointsBlue.Positions.Update(interp[":"]);
                    Text = interp.GetValue(2).ToString();
                    m_pointsRed.Configure();
                    m_pointsBlue.Configure();
                    ilPanel1.Refresh();
                } catch (ArgumentException) { }
            }
        }
    }
}
See Also

Reference