Move object when mouse move on Helix- viewport 3D - c#

I try to move multiple object open on Helix viewport 3D. so curtly mutiple object are open succesfuly. but problem in when i try to move any specific model at that time object move mouse opposit position like when i move on Right side at time object is goes to left side same as all axis. so i past here mouse move click event hrer, please provide a solution.
Number of query -
multiple object open at time i need to select particular object and move it. curntly all model are move in oposite axix.
Mouse move time object move opposite direction.
Object load Event :
private void loadbtn_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.DefaultExt = ".stl";
dlg.Filter = "STL Files|*.stl;";
Nullable<bool> result = dlg.ShowDialog();
if (result == true)
{
string filename = dlg.FileName;
openfile = filename;
// txt1.Text = dlg.FileName;
}
ModelVisual3D device3D = new ModelVisual3D();
device3D.Content = Display3d(openfile);
// viewPort3d.Children.Add(device3D);
var reader = new StLReader();
_modelGroup = reader.Read(openfile);
var modelVisual = new ModelVisual3D();
modelVisual.Content = _modelGroup;
// Apply the TranslateTransform3D to your STL object
_modelGroup.Transform = _translate;
// Add the ModelVisual3D to the Children property of the HelixViewport3D
viewPort3d.Children.Add(modelVisual);
}
Mouse Down event is as per below.
private void viewPort3d_MouseDown(object sender, MouseButtonEventArgs e)
{
//*** MOVE ***
var position = e.GetPosition(viewPort3d);
var origin = new Point3D(position.X, position.Y, 0);
Point originPoint = new Point(origin.X, origin.Y);
var transformedOrigin = Viewport3DHelper.UnProject(ConvertToViewport3D(viewPort3d), originPoint);
_lastPosition = position;
viewPort3d.MouseMove += viewPort3d_MouseMove;
viewPort3d.MouseUp += viewPort3d_MouseUp;
}
private Viewport3D ConvertToViewport3D(HelixViewport3D helixViewport)
{
Viewport3D viewport = new Viewport3D();
viewport.Camera = helixViewport.Camera;
foreach (var child in helixViewport.Children)
{
if (child is ModelVisual3D modelVisual)
{
if (modelVisual.Content is Model3D model)
{
ModelVisual3D newChild = new ModelVisual3D();
newChild.Content = model;
viewport.Children.Add(newChild);
}
else
{
// handle other types of modelVisual.Content if necessary
}
}
else
{
// handle other types of Visual3D objects if necessary
}
}
return viewport;
}
Mouse Move event is as per below.
private void viewPort3d_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
System.Windows.Point position = e.GetPosition(this); // this = viewPort3D
double pX = position.X;
double pY = position.Y;
_translate.OffsetX -=pX;
_translate.OffsetY += pY;
_lastPosition = position;
}
Mouse Up event is as per below.
private void viewPort3d_MouseUp(object sender, MouseButtonEventArgs e)
{
//_isDragging = false;
viewPort3d.MouseMove -= viewPort3d_MouseMove;
viewPort3d.MouseUp -= viewPort3d_MouseUp;
//ReleaseMouseCapture();
}

Related

How to keep a control within its parent control while dragging it?

So I have a control named UI_TileInformation which needs to be kept inside its parent container (a canvas), while allowing the user to drag it freely. This solution was helpful in getting it to function, it now drags perfectly fine. However, it can be dragged outside of the bounds of its container. This solution was no help as I do not see where the _transform variable comes from.
The control has the following default variables:
protected bool isDragging;
private Point clickPosition;
As well as these event handlers:
this.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(Control_MouseLeftButtonDown);
this.PreviewMouseLeftButtonUp += new MouseButtonEventHandler(Control_MouseLeftButtonUp);
this.PreviewMouseMove += new MouseEventHandler(Control_MouseMove);
I am fairly new to c# and WPF but I figured out that those event handlers would only work with when previewed (PreviewMouseMove as opposed to MouseMove)
As for the code that makes it drag, it is similar to the first link above:
private void Control_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
isDragging = true;
var draggableControl = sender as UI_TileInformation;
clickPosition = e.GetPosition(this);
draggableControl.CaptureMouse();
}
private void Control_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
isDragging = false;
var draggableControl = sender as UI_TileInformation;
draggableControl.ReleaseMouseCapture();
}
private void Control_MouseMove(object sender, MouseEventArgs e)
{
var draggableControl = sender as UI_TileInformation;
if (isDragging && draggableControl != null)
{
Point positionInUIElement = e.GetPosition(this);
var transform = draggableControl.RenderTransform as TranslateTransform;
if (transform == null)
{
transform = new TranslateTransform();
draggableControl.RenderTransform = transform;
}
transform.X = positionInCanvas.X - clickPosition.X;
transform.Y = positionInCanvas.Y - clickPosition.Y;
}
}
How can I get my control to stay inside the canvas?

WPF How to dynamically draw one shape over another using Path and Geometry Group

I'm trying to make an application for a homework assignment that adds a RectangleGeometry to the path.data as GeometryGroup Children and then updates the size while I hold down the mouse button and move the mouse and then finalizes it when on mouseup. The problem is that I need the subsequent rectangles to be drawn over top of the preceeding ones. Setting FillRule to nonzero doesn't accomplish this because it still shows the stroke of the underlying rectangles. So how can I accomplish this?
private void path_MouseDown(object sender, MouseButtonEventArgs e)
{
path.Stroke = strokeColor;
path.Fill = fillColor;
path.StrokeThickness = thickness;
p = Mouse.GetPosition((UIElement)sender);
gg = path.Data as GeometryGroup;
gg.Children.Add(new RectangleGeometry());
}
private void path_MouseMove(object sender, MouseEventArgs e)
{
if (p == null) return;
var pp = Mouse.GetPosition((UIElement)sender);
gg = path.Data as GeometryGroup;
if (index == 0)
{
var pg = gg.Children.Last() as RectangleGeometry;
pg.Rect = new Rect(p.Value, pp);
}
else if(index == 1)
{
var pg = gg.Children.Last() as RectangleGeometry;
pg.RadiusX = pp.X - p.Value.X;
pg.RadiusY = pp.Y - p.Value.Y;
pg.Rect = new Rect(p.Value, pp);
}
}
private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
p = null;
}

WPF: Rotate a rectangle with slider

I'm trying to rotate a rectangle when scrolling slider
there are 2 steps: Click on a rectangle - Scroll the slider.
If I draw only one rectangle, everything is ok.
But when I draw 2 rectangles or more and start rotating, all of my rectangle are rotated together with same angle.
I have no idea about this.
Can anyone help me?
Thanks in advance!
Here is my code: (I found the code for rotating at another post in this page)
Shape _shape;
RotateTransform rt = new RotateTransform();
private void MyCanvas_MouseRightButtonDown(object sender, MouseButtonEventArgs)
{
/////////////////////////////////////////////////////
//for know which rectangle has been clicked
if (MyTransform_type == TRANSFORM_TYPE.ROTATE)
{
_shape = e.OriginalSource as Shape;
if (_shape != null)
{
_shape = (Shape)e.OriginalSource;
}
}
}
private void MyCanvas_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
if (MyTransform_type != TRANSFORM_TYPE.NONE && MyTransform_type != TRANSFORM_TYPE.ROTATE)
{
if (_shape == null)
return;
//_shape.ReleaseMouseCapture();
Cursor = Cursors.Arrow;
}
}
private void sldRotate_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (_shape != null)
{
_shape.RenderTransform = rt;
_shape.RenderTransformOrigin = new Point(0.5, 0.5);
var da = new DoubleAnimation(rt.Angle, sldRotate.Value, new Duration(TimeSpan.FromSeconds(0.001)));
rt.BeginAnimation(RotateTransform.AngleProperty, da);
rt.Angle = sldRotate.Value;
}
}
Your mistake is that you create a single RotateTransform object and assign it to the different shapes. So after clicking on several rectangles, every rectangle has the same rotatetransform instance. If you now change the value of the rotatetransform, every rectangle will rotate...
In order to fix that you should change your sldRotate_ValueChanged method. Check if the current shape has already a rotatetransform. If not then create one, if yes adjust the rotatetransform...
Additionally, if you have such a small animation time, you can just leave it out:
private void sldRotate_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (_shape != null)
{
var rt = new RotateTransform();
rt.Angle = sldRotate.Value;
_shape.RenderTransform = rt;
_shape.RenderTransformOrigin = new Point(0.5, 0.5);
}
}
It looks like you are using the same RotateTransform named "rt" for all of your rectangles. The simpliest solution will be:
private void MyCanvas_MouseRightButtonDown(object sender, MouseButtonEventArgs)
{
if (MyTransform_type == TRANSFORM_TYPE.ROTATE)
{
_shape = e.OriginalSource as Shape;
//creating new RotateTransform
rt=new RotateTransform();
if (_shape != null)
{
_shape = (Shape)e.OriginalSource;
}
}
}
also you could do
_shape.RenderTransform = rt;
in MyCanvas_MouseRightButtonDown after
_shape = e.OriginalSource as Shape;
instead of doing it each time, when sldRotate_ValueChanged executes to avoid unneeded assignments.

how to drag & drop image from wrap panel to canvas

I am using Visual Studio 2012 to write a C# WPF application.
I got some images from a database and put them into a wrap panel. From the wrap panel, I want to drag the images and drop them into a canvas. This is how I get the images from the database:
private void GetImages(int taskID, int activityID)
{
IList<ModelSQL.TwoCategory> ImagesList = twocat.GetImageURL(taskid, type);
foreach (ModelSQL.TwoCategory tc in ImagesList)
{
var uriSource = new Uri(root.SetupInformation.ApplicationBase + tc.Pictures);
Image img = new Image();
img.Source = new BitmapImage(uriSource);
img.VerticalAlignment = VerticalAlignment.Center;
img.HorizontalAlignment = HorizontalAlignment.Center;
img.Stretch = Stretch.Uniform;
img.Height = 100;
img.Width = 100;
img.AllowDrop = true;
img.PreviewMouseDown += new MouseButtonEventHandler(img_MouseDown);
img.PreviewMouseMove += new MouseEventHandler(img_MouseMove);
img.PreviewGiveFeedback += new GiveFeedbackEventHandler(img_GiveFeedback);
img.PreviewMouseUp += new MouseButtonEventHandler(img_PreviewMouseUp);
Canvas1.AllowDrop = true;
Canvas2.AllowDrop = true;
//Canvas1.PreviewDrop += new DragEventHandler(Canvas1_PreviewDrop);
//Canvas2.PreviewDrop += new DragEventHandler(Canvas2_PreviewDrop);
imgPanel.Children.Add(img);
}
}
I used the drag adorner to drag the images and it works fine.
private void img_MouseDown(object sender, MouseButtonEventArgs e)
{
startPoint = e.GetPosition(this);
}
private void img_MouseMove(object sender, MouseEventArgs e)
{
// int y = 0, z = 0;
if (e.LeftButton == MouseButtonState.Pressed)
{
var source = sender as UIElement;
Image img = sender as Image;
//img.Background = System.Windows.Media.Brushes.YellowGreen;
Point current = e.GetPosition(this);
Vector diff = startPoint - current;
if (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)
{
adorner = new DragAdorner(img, e.GetPosition(img));
AdornerLayer.GetAdornerLayer(img).Add(adorner);
var dragData = new DataObject(this);
//string str = img.Content.ToString();
//DragDrop.DoDragDrop(lbl, lbl.Content, DragDropEffects.Move | DragDropEffects.Copy);
DragDrop.DoDragDrop(img, dragData, DragDropEffects.Move | DragDropEffects.Copy);
AdornerLayer.GetAdornerLayer(img).Remove(adorner);
}
}
}
private void img_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{ }
private void img_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
if (adorner != null)
{
Image img = sender as Image;
var pos = img.PointFromScreen(GetMousePosition());
adorner.UpdatePosition(pos);
e.Handled = true;
}
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetCursorPos(ref Win32Point pt);
[StructLayout(LayoutKind.Sequential)]
internal struct Win32Point
{
public Int32 X;
public Int32 Y;
};
public static Point GetMousePosition()
{
Win32Point w32Mouse = new Win32Point();
GetCursorPos(ref w32Mouse);
return new Point(w32Mouse.X, w32Mouse.Y);
}
But I'm having trouble dropping the image into the canvas, and I'm able to drag the image to anywhere in the application. How do I disable that?
This is the GUI
THIS IS THE DROP EVENT
private void Canvas1_Drop(object sender, DragEventArgs e)
{
ImageSource imageSource = e.Data.GetData(typeof(ImageSource)) as ImageSource;
Image img = sender as Image;
img.Source = imageSource;
Canvas Canvas1 = sender as Canvas;
Canvas1.Children.Add(img);
}
With
DragDrop.DoDragDrop(img, dragData, DragDropEffects.Move | DragDropEffects.Copy);
you managed, that the data has been given to the drag drop operation.
Now, every other Control, e.g. the canvas, can decide in their DragOver and Drop events, if they want/can do anything with the data or not.
The source of the data is more or less out of the game, when the drag and drop starts, it's the drop target that does the rest.
If you do not want your data to leave the source control, you should attach to its DragLeave-event and cancel the Drag and Drop operation, if the mouse moves away.

Drawing Line to next point in realtime

My current program allows the user to click a point, then click another point (at least 20 pixels away) and draws a line between the 2 points. I've used a Polyline so that this can be done multiple times. Though the set of all the lines only appear after all the click are done.
void DrawingCanvas_MouseUp(object sender, MouseButtonEventArgs e) {
Point position = e.GetPosition(this);
if (leftList == null) {
//starting a new set
leftList.Add(position);
lastPoint = position;
return;
}
//calculate distance, i.e. end click
double a = lastPoint.X - position.X;
double b = lastPoint.Y - position.Y;
double distance = Math.Sqrt(a * a + b * b);
if (distance > 20) {
//continue to add to list
leftList.Add(position);
lastPoint = position;
} else {
//end of the line
paint();
leftList = new PointCollection();
}
}
private void paint() {
Polyline line = new Polyline();
line.Visibility = System.Windows.Visibility.Visible;
line.StrokeThickness = 2;
line.Stroke = System.Windows.Media.Brushes.Black;
line.Points = leftList;
myCanvas.Children.Add(line);
}
So my question is two-fold:
A) How do I make it so that after each click the new line is immediately added.
B) How do I render a line between the last point and where the mouse cursor is currently at (i.e. just before you choose your next point)
The following simple example starts drawing a new polyline when the left mouse button is pressed and the mouse is moved by the minimum point distance of 20, with the button kept pressed. It draws the last polyline segment (to the current mouse position) in either red or green, depending on its length. If the mouse button is released and the length of the new segment is >= 20, a new point is appended to the polyline. Otherwise the polyline is terminated, and a new polyline can be created.
private Polyline polyline;
private Polyline segment = new Polyline { StrokeThickness = 2 };
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (polyline == null)
{
var canvas = (Canvas)sender;
var point = e.GetPosition(canvas);
// create new polyline
polyline = new Polyline { Stroke = Brushes.Black, StrokeThickness = 2 };
polyline.Points.Add(point);
canvas.Children.Add(polyline);
// initialize current polyline segment
segment.Stroke = Brushes.Red;
segment.Points.Add(point);
segment.Points.Add(point);
canvas.Children.Add(segment);
}
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (polyline != null)
{
// update current polyline segment
var canvas = (Canvas)sender;
segment.Points[1] = e.GetPosition(canvas);
var distance = (segment.Points[0] - segment.Points[1]).Length;
segment.Stroke = distance >= 20 ? Brushes.Green : Brushes.Red;
}
}
private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (polyline != null)
{
var canvas = (Canvas)sender;
segment.Points[1] = e.GetPosition(canvas);
var distance = (segment.Points[0] - segment.Points[1]).Length;
if (distance >= 20)
{
polyline.Points.Add(segment.Points[1]);
segment.Points[0] = segment.Points[1];
}
else
{
if (polyline.Points.Count < 2)
{
canvas.Children.Remove(polyline);
}
polyline = null;
segment.Points.Clear();
canvas.Children.Remove(segment);
}
}
}
please maintain a collection of points on every click. in collection you can add one class which will have two properties like StartPoint and EndPoint.
when the mouse is clicked first time just add one class object to collection having start point only.
and when you click the mouse next time, ad end point to the last object of the class and meanwhile create a new object and assign this point as its start point and add it to collection, after that call the paint function.

Categories

Resources