[ILNumerics Visualization Engine]
Namespace: ILNumerics.Drawing
Assembly: ILNumerics.Drawing (in ILNumerics.Drawing.dll) Version: ILNumerics Ultimate VS 4
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: IPickingResultInterface giving access to detailed information of the primitive(s) found
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]
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) { } } } } }