Draw point where mouse clicked - c#

I'm using HelixToolkit to see and interact with STL files. I need to draw or mark a point clicked by user on the window. I have the coordinates, I know where to draw that point, but I don't know how to draw it, can someone help me? I post some code to explain what I have right now:
private void vierport3d_MouseRightClick(object sender, MouseButtonEventArgs e)
{
Point mousePos = e.GetPosition(viewPort3d);
PointHitTestParameters hitParams = new PointHitTestParameters(mousePos);
VisualTreeHelper.HitTest(viewPort3d, null, ResultCallback, hitParams);
}
public HitTestResultBehavior ResultCallback(HitTestResult result)
{
RayHitTestResult rayResult = result as RayHitTestResult;
if (rayResult != null)
{
RayMeshGeometry3DHitTestResult rayMeshResult = rayResult as RayMeshGeometry3DHitTestResult;
//HERE I HAVE THE LOCATION TO DRAW
MessageBox.Show(rayMeshResult.PointHit.X + " " + rayMeshResult.PointHit.Y + " " + rayMeshResult.PointHit.Z);
if (rayMeshResult != null)
{
// I THINK I HAVE TO DRAW THE POINT HERE
}
}
return HitTestResultBehavior.Continue;
}
PD: I show the stl on a viewport3d.

We had same scenario in our project and used a sphere to visually indicate the point.
<ht:SphereVisual3D Radius="0.75" Fill="Red" Center="{Binding ContactPoint}" />
ContactPoint is a Point3D type.

This might help, but its probably not the most effecient.
Try the following:
This will create a 3D sphere that can be rendered at the given coordinates.
var sphereSize = 0.025;
/* keep these values low, the higher the values the more detailed the sphere which may impact your rendering perfomance.*/
var phi = 12;
var theta = 12;
MeshBuilder meshBuilder = new MeshBuilder();
Pass in your x,y,z to the first parameter. i.e. the click 3D location.
meshBuilder.AddSphere( new Point3D(x,y,z), sphereSize , theta, phi);
GeometryModel3D sphereModel = new GeometryModel3D(meshBuilder.ToMesh(),MaterialHelper.CreateMaterial(Brushes.Green,null,null,1,0));
Rendering the Point in your viewport
You will need a ModelVisual3D component as a child of the HelixViewport. ( This can be implemented in C# or in XAML) its up to you, ill show both ways.
C# version
NB: You need a reference to the helixviewport if its defined in xaml. Set the x:Name:"" to something appropriate. e.g x:Name="helixViewPort"
ModelVisual3D visualizer = new ModelVisual3D();
visualizer.Content = sphereModel;
helixViewPort.Children.Add(visualizer);
XAML version
I'll assume your xaml code has at least a helix view port so you'll have to add a ModelVisual3D child to the helix viewport if there's none.
<h:HelixViewport3D x:Name="HelixPlotViewPort" >
<h:DefaultLights/>
<ModelVisual3D x:Name="Visualizer">
</ModelVisual3D>
</h:HelixViewport3D>
//Then in C# add the following
Visualizer.Content = sphereModel;
That should do it, hope it helps, do inform us if you find a better solution. :)

Related

Zooming about point when using a Viewbox inside a ZoomableCanvas?

Thanks to Kael Rowan, you can easily create a zoomable canvas in WPF. Sample project can be downloaded at the bottom of this blog entry.
Now, I need to modify this sample project to use its Viewbox feature. In MainWindow.xaml set the Viewbox, Stretch and ApplyTransform properties as follows:
<ZoomableCanvas ... Viewbox="0 0 400 400" Stretch="Fill" ApplyTransform="True" />
The problem
With this feature enabled, the zooming using the mouse wheel does not zoom about the mouse position. Instead, it seems to zoom around (0,0). This piece of code (in the mouse wheel handler) works without Viewbox:
// Adjust the offset to make the point under the mouse stay still.
var position = (Vector)e.GetPosition(MyListBox);
MyCanvas.Offset = (Point)((Vector)(MyCanvas.Offset + position) * x - position);
How can I get it working with a Viewbox? This is driving me nuts! Math/WPF gurus out there, please help!
Try this code
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
var position = e.GetPosition(this.MyCanvas);
var pre = this.MyCanvas.TransformToAncestor(this).Transform(position);
var x = Math.Pow(2, e.Delta / 3.0 / Mouse.MouseWheelDeltaForOneLine);
MyCanvas.Scale *= x;
var cur = this.MyCanvas.TransformToAncestor(this).Transform(position);
var offset = (cur - pre);
this.MyCanvas.Offset += offset;
}

How to turn off default Mouse Event Handlers in ILNumerics PlotCube?

I'm using the ILNumerics Math Library to create some 2D Plots. To display the data I use the ILPlotCube Class. I would like to turn off the default behavior of the EventHandler for MouseDoubleClick events, because I would like to implement my own. Is that possible?
Here's some more context:
The default event handler of an ILPlotCube for MouseDoubleClick events resets the view to default values. Usually this works quite well, but there seems to be a problem with very small x- and y-values. When I add a linePlot with very small y-values the limits of the plots are automatically set to YMax=0.525 and YMin=-0.525. Unfortunately, that's not what I want. So, I set the values myself after adding the linePlot and the plot looks exactly how I'd like to have it. Great... but: if I double click on the scene it uses the default (0.525) values again. Dough! That's why I would like to turn off or overwrite this behavior.
Any ideas?
private void ilPanel1_Load(object sender, EventArgs e)
{
var scene = new ILScene();
//data with very small "y-values"
ILArray<float> line1 = new float[,] {
{0.0f, 1.0f, 2.0f },
{2.042166e-08f, 2.070141e-08f , 2.042166e-08f} };
var linePlot1 = new ILLinePlot(line1.T,
lineColor: Color.Blue,
lineWidth: 3,
markerStyle: MarkerStyle.Dot);
//Create Plot Cube
var plotCube = new ILPlotCube();
plotCube.Add(linePlot1);
//plotCube.Plots.Limits.YMax is now 0.525
//plotCube.Plots.Limits.YMin is now -0.525
//manually set the value
float maxY = 0.0f;
using (ILScope.Enter())
{
var aPos = linePlot1.Line.Positions.Storage["1;:"];
maxY = ILMath.max(aPos).FirstOrDefault();
}
plotCube.Plots.Limits.YMax = maxY;
plotCube.Plots.Limits.YMin = 0.0f;
var plot = scene.Add(plotCube);
ilPanel1.Scene = scene;
}
Thanks,
Tim
All nodes in ILNumerics provide access to the common mouse handlers which you can use to provide your own logic - or to simply disable existing individual handlers. In your case, you can override the double click handler for the plot cube:
// ....
plotCube.MouseDoubleClick += (_e, _a) => {
_a.Cancel = true;
};
// you may want disable zoom and pan as well?
plot.AllowZoom = false;
plot.AllowPan = false;
// continue with your code here...
ilPanel1.Scene = scene;
The mouse handlers in ILNumerics are actually very flexible and powerful. See the documentation here: http://ilnumerics.net/mouse-events.html
#Edit: for your situation, the ILPlotCube.AutoScaleOnAdd property might also be of interest. It determines, if the plot cube limits are to be recomputed once a new plot has been added to the plot cube. You might find false more convenient.

Create images using shapes

Im trying to create a drag and drop module which can be used to build an Image.
EX: Using a triangle and rectangles to create a House.
I have created the drag and drop module but I cant make them fix with each other.
It will be a great help if someone can give me an idea or a sample code for this problem.
Please help me in this.
I'll explain the functionality a little bit, but forgive my English if any mistakes since it's not my native language.
The user is given a set of shapes and a question like "CREATE A HOUSE" so he should be able to drag the shapes that is
given and and build the house.
Thanks in Advance.
if you want to snap the house pieces to grid let's say 50 pixels put these equations
inside mouse up event
box.x = Math.floor(mouseX/50)*50;
box.y = Math.floor(mouseY/50)*50;
box.addEventListener(MouseEvent.MOUSE_UP,mUp)
function mUp(e:MouseEvent)
{
box.stopDrag();
box.x = Math.floor(mouseX/50)*50;
box.y = Math.floor(mouseY/50)*50;
}
that will fit the pieces together
Use this as a base class for your drag-able objects:
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
public class Dragable extends Sprite
{
// vars
private const SNAP:uint = 40;
/**
* Constructor
*/
public function Dragable()
{
addEventListener(MouseEvent.MOUSE_DOWN, _drag);
addEventListener(MouseEvent.MOUSE_UP, _drop);
}
/**
* MOUSE_DOWN
*/
private function _drag(e:MouseEvent):void
{
startDrag();
}
/**
* MOUSE_UP
*/
private function _drop(e:MouseEvent):void
{
stopDrag();
x = Math.round(x / SNAP) * SNAP;
y = Math.round(y / SNAP) * SNAP;
}
}
}
Modify SNAP to meet your requirements.
For something like this (ignoring the dragging and dropping, which you've got some good examples for here), you set all this up previously.
Say your goal is to build a house. Here, you'd assemble the pieces beforehand and save out the final position and rotation in an xml or something similar. When you drag the pieces in the game, you just need to check if it's close enough to the final position and if it is, just snap it to the final position. You can work in rotation easily enough (though I'd keep the angles to 45 degrees for simplicitly).
As an idea for position:
private var m_finalPos:Point = new Point( 10.0, 10.0 );
private var m_snapDist:Number = 100.0;
private function _onDrop( e:MouseEvent ):void
{
// get the distance squared (quicker, and we don't really care about the distance)
var diffX:Number = this.m_finalPos.x - this.x;
var diffY:Number = this.m_finalPos.y - this.y;
var distSq:Number = ( diffX * diffX ) + ( diffY * diffY );
// if we're close enough, snap to the final position
if( distSq < this.m_snapDist )
{
this.x = this.m_finalPos.x;
this.y = this.m_finalPos.y;
}
}
Lower the snapDist to make it harder.

Weird shape resizing behavior in WPF

I am making a WPF application that will let the user draw and resize shapes.
The resizing part is done using adorners, and the shapes are my own classes derived from Shape.
For example I have a Polyline, and for each of it's points I am adorning a Thumb with a handler on it's DragDelta event:
void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
{
PolylineEx polyline = this.AdornedElement as PolylineEx;
ResizingThumb thumb = sender as ResizingThumb;
int index = (int)thumb.Tag;
Point newPoint = new Point(
polyline.Points[index].X + e.HorizontalChange,
polyline.Points[index].Y + e.VerticalChange);
Trace.WriteLine(String.Format("Arranging point {0}:{1},{2}", index, newPoint.X, newPoint.Y));
polyline.Points[index] = newPoint;
}
Well, the problem is that sometimes (often), dragging a thumb is not smooth at all. First I thought it was a performance issue, because of a new Point being created every time (and other things), but then I noticed that sometimes the point is set up at weird coordinates that have nothing to do with the position of the mouse.
I've also uploaded a sample project HERE, could someone who knows his way around wpf take a look and enlighten me of what is happening?
Also, if anyone thinks of a better way for doing this, any feedback would be highly appreciated.
Thank you.
Edit: HERE is a new link to the project files.
I'm ending up answering my own question :)
I think the problem was here:
protected override System.Windows.Media.Geometry DefiningGeometry
{
get
{
StreamGeometry geometry = new StreamGeometry();
using (StreamGeometryContext context = geometry.Open())
{
context.BeginFigure(Points[0], false, true);
foreach (Point pt in Points)
{
context.LineTo(pt, true, true);
}
geometry.Freeze();
return geometry;
}
}
}
I switched to using PathGeometry & LineSegments and it works fine now.

Determine location of a UIElement on a Canvas

I have spent 20 minutes trying to find an example in C# of how to draw a line between two rectangles, and I can't find anything. I don't know if I just don't understand the paradigm of drawing 2D shapes in Silverlight, or if I'm just looking in the wrong place.
I have set up the rectangles so I can drag them around, and now I want to draw a line between the two shapes as I drag a rectangle across the canvas. I want to be able to do something like this as I drag the second rectangle:
void host1_MouseLeftButtonMove(object sender, MouseEventArgs e)
{
if (isDown)
{
this.host1TranslateTransform.X = e.GetPosition(canvas).X - x;
this.host1TranslateTransform.Y = e.GetPosition(canvas).Y - y;
Line l = new Line();
l.X1 = rect1.X; // does not work
l.X2 = e.GetPosition(canvas).X;
l.Y1 = rect1.Y; // does not work
l.Y2 = e.GetPosition(canvas).Y;
}
}
How do I get the coordinates of the first box? I can't figure out how to get the coordinates of shapes relative to the canvas in my application. I would appreciate any tutorials that give a beginner overview for how to draw simple 2D shapes.
Thanks!
try this
Canvas.GetTop(element);
Canvas.GetLeft(element);
position properties are attached properties ;)

Categories