I have the following code:
if (frame != null)
{
canvas.Children.Clear();
_bodies = new Body[frame.BodyFrameSource.BodyCount];
frame.GetAndRefreshBodyData(_bodies);
foreach (var body in _bodies)
{
if (body != null)
{
if (body.IsTracked)
{
// choose which hand to track
string whichHand = "right"; //change to "left" in order to track left hand
Joint handRight = body.Joints[JointType.HandRight];
if (whichHand.Equals("right"))
{
string rightHandState = "-"; //find the right hand state
switch (body.HandRightState)
{
case HandState.Open:
rightHandState = "Open";
break;
case HandState.Closed:
rightHandState = "Closed";
break;
default:
break;
}
canvas.DrawPoint(handRight, _sensor.CoordinateMapper);
}
Here is my DrawPoint code:
public static void DrawPoint(this Canvas canvas, Joint joint, CoordinateMapper mapper)
{
if (joint.TrackingState == TrackingState.NotTracked) return;
Point point = joint.Scale(mapper);
Ellipse ellipse = new Ellipse
{
Width = 20,
Height = 20,
Fill = new SolidColorBrush(Colors.LightBlue)
};
Canvas.SetLeft(ellipse, point.X - ellipse.Width / 2);
Canvas.SetTop(ellipse, point.Y - ellipse.Height / 2);
canvas.Children.Add(ellipse);
}
And Scale:
public static Point Scale(this Joint joint, CoordinateMapper mapper)
{
Point point = new Point();
ColorSpacePoint colorPoint = mapper.MapCameraPointToColorSpace(joint.Position);
point.X *= float.IsInfinity(colorPoint.X) ? 0.0 : colorPoint.X;
point.Y *= float.IsInfinity(colorPoint.Y) ? 0.0 : colorPoint.Y;
return point;
}
The problem that I have is that while the circle does get drawn, it is not drawn over my hand. Instead it stays in the top left corner (0,0), so I'm guessing that it's not getting updated properly. Could anybody tell me what is going on or what the problem is? I would like it to be in the center of my hand (which is being tracked fine because the state of the hand gets updated immediately) and follow my hand as I move it.
The _sensor is my Kinect sensor.
Related
I have a custom written chart control. My charts are displaying time on x-axis and current on y-axis. What I want is, selected zoom. So when user clicks and drag mouse over chart it shows selection rectangle and selects particular area on chart and updates the chart to display points of only selected area.
My problem is, I can zoom in for the first time and it shows me correct results on updated chart. with correctly updated x coordinates. But when I do it again (anytime after 1st zoom in) points are always off.
All I want is when user selects another area on already zoom in chart it should do further zoom in with updated x coordinates.
What I tried: From proper observation of my chart zoom in behavior I found that every time when I click on chart that point is mapped to my original chart width and not updated width(updated width I found as (endingXPoints - beginingXPoints) when I do zoom). So I have to map points according to updated width. But That does not work. I still do not get correct zoom in. Also I tried using scaling factor as chart size is changing but still result is not correct.
So my question how to map the points of zoomed chart on my original chart. I am doing this in windows form and using custom written library.
I just began my career as developer and still in learning process. Any suggestion will be great help to me. Thank you
Here is my mouse_up event, if that code helps. I have try to add as many comments as possible. In this code I am saving previous points clicked on stack and using it to get scale factor and get the scaled
private void chart_MouseUp(object sender, MouseEventArgs e)
{
Point p1, p2;
//when mouse up occurs it first checks, with isMousePressed, if mouse was pressed or not
if (isMousepressed)
{
isMousepressed = false;
isMouseEventOccured = true;
int xLeft = chartA.GetLeftDistToXaxis;//left distance from starting of control to x axis
int xWidth = chartA.chartWidth;//actual x-axis width shown on control
int yBottom = chartA.yTopPadding + chartA.chartHeight;//bottom distance from starting of control to y axis
//if no start - end points are selected then do nothing and return
if (endSelectionPoint == Point.Empty || beginSelectionPoint == Point.Empty) return;
//if start point is same as end point, do noting and return and if selection is made on left side of Y axis do nothing
if (endSelectionPoint.X == beginSelectionPoint.X) return;
if (endSelectionPoint.Y == beginSelectionPoint.Y) return;
if (beginSelectionPoint.X < xLeft && endSelectionPoint.X < xLeft) return;//avoid left chart area
if (beginSelectionPoint.Y > yBottom && endSelectionPoint.Y > yBottom) return;//avoid bottom chart area
endSelectionPoint.X = e.X;
endSelectionPoint.Y = e.Y;
//when all of the above conditions are false, we have two different start/end points which is not empty. map it & draw rectangle
p1 = ((Control)sender).PointToScreen(beginSelectionPoint);
p2 = ((Control)sender).PointToScreen(endSelectionPoint);
//draw selection rectangle
ControlPaint.DrawReversibleFrame(chartA.getRectangleForPoints(p1, p2), Color.Black, FrameStyle.Dashed);
//checking the begin and end value of x-y coordinates to see if they are on chart. if not then set the boundaries
//check it for begin coordinates
if (beginSelectionPoint.X < xLeft) { beginSelectionPoint.X = xLeft; }
if (beginSelectionPoint.X > (xLeft + chartA.Width)) { return; /*beginSelectionPoint.X = (xLeft + chartA.Width);*/ }
//if (beginSelectionPoint.Y < yBottom) { beginSelectionPoint.Y = yBottom; }
//if (beginSelectionPoint.Y > (yBottom + chartA.Height)) { beginSelectionPoint.Y = (yBottom + chartA.Height); }
//check it for end coordinates
if (endSelectionPoint.X > (xLeft + chartA.Width)) { endSelectionPoint.X = (xLeft + chartA.Width); }
if (endSelectionPoint.X < xLeft) { endSelectionPoint.X = xLeft; }
//if (endSelectionPoint.Y < yBottom) { endSelectionPoint.Y = yBottom; }
//if (endSelectionPoint.Y > (yBottom + chartA.Height)) { endSelectionPoint.Y = (yBottom + chartA.Height); }
//actual x-y value on chart.....x->corresponding time; y-> corresponding Amperage
xStart = 10 * chartA.MouseToXProportion(beginSelectionPoint.X );//multiplied with 10 to get the correct x values, if not used values in 0.+
yStart = chartA.MouseToYProportion(beginSelectionPoint.Y);
xEnd = 10 * chartA.MouseToXProportion(endSelectionPoint.X);
yEnd = chartA.MouseToYProportion(endSelectionPoint.Y);
if (zoomStack.Count != 0)
{
Point prevZoomPtEnd = (Point)zoomStack.Pop();
Point prevZoomPtStart = (Point)zoomStack.Pop();
double oldWidth = prevZoomPtEnd.X - prevZoomPtStart.X;
double zoomedWidth = endSelectionPoint.X - beginSelectionPoint.X;
double scaleFactor = zoomedWidth / oldWidth;
xStart = 10 * (chartA.MouseToXProportion(beginSelectionPoint.X) * scaleFactor);
xEnd = 10 * (chartA.MouseToXProportion(endSelectionPoint.X) * scaleFactor);
zoomStack.Push(beginSelectionPoint);
zoomStack.Push(endSelectionPoint);
}
else
{
zoomStack.Push(beginSelectionPoint);
zoomStack.Push(endSelectionPoint);
}
double xTemp;
if (xStart > xEnd) { xTemp = xEnd; xEnd = xStart; xStart = xTemp; }
//call updatechart() with start and end points on graph being p1/p2 or beginselection/endselection
updateChart(lastSelectedProfile, lastSelectedWeldIndex, xStart, xEnd);
}
else return;
}
Do you have to map the points? The chart's built in zoom should handle zooming correctly without trying to re-invent the wheel. The code below should be enough, hold left click and drag to zoom into the range.
private void setUserSelection(Chart cht)
{
cht.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
cht.ChartAreas[0].CursorX.IsUserEnabled = true;
cht.ChartAreas[0].CursorX.LineColor = Color.Transparent;
cht.ChartAreas[0].CursorX.SelectionColor = Color.Lime;
cht.ChartAreas[0].CursorX.Interval = 0;
cht.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
cht.ChartAreas[0].AxisX2.ScaleView.Zoomable = true;
cht.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
cht.ChartAreas[0].CursorY.IsUserEnabled = true;
cht.ChartAreas[0].CursorY.LineColor = Color.Transparent;
cht.ChartAreas[0].CursorY.SelectionColor = Color.Lime;
cht.ChartAreas[0].CursorY.Interval = 0;
cht.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
cht.ChartAreas[0].AxisY2.ScaleView.Zoomable = true;
}
To zoom out back one zoom, you'll need to add the following code somewhere. In my example below I have mine on the mouse right click.
private void chart1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
chart1.ChartAreas[0].AxisX.ScaleView.ZoomReset(1);
chart1.ChartAreas[0].AxisY.ScaleView.ZoomReset(1);
}
}
I'm new to Xamarin Android and currently working on a floating action button, I implemented View.IOnTouchListener and normal button click event (faButton.Click += floatButtonPressed;) to carry out my actions. But for the case MotionEventActions.Move, it doesn't work as I wanted. Moving left and right it works fine but for top and bottom it will move downwards a little bit whenever I start moving it. Besides, when I move the button to screen border it will be able to exceed the screen. Hence, I tried detect screen size and restrict it but it still not good enough, is there any other available solution or settings?
public bool OnTouch(View v, MotionEvent e)
{
switch (e.Action)
{
case MotionEventActions.Down:
oldXvalue = e.GetX();
oldYvalue = e.GetY();
if (oldXvalue == e.GetX() && oldYvalue == e.GetY())
{
return false;
}
break;
case MotionEventActions.Up:
if (oldXvalue == e.GetX() && oldYvalue == e.GetY())
{
return false;
}
break;
case MotionEventActions.Move:
var xleft = (int)(e.RawX - oldXvalue);
var xright = xleft + v.Width;
var ytop = (int)(e.RawY - oldYvalue);
var ybtm = (ytop + v.Height);
if (xleft + v.Width >= intWidth)
{
break;
}
if (xleft <= 0)
{
break;
}
if (ytop + v.Height >= intHeight)
{
break;
}
if (ytop <= 0)
{
break;
}
v.Layout(xleft, ytop, xright, ybtm);
break;
}
return true;
}
You can get the screen height and screen width first. And when the button exceed the screen you need to reset the button position.
Try the following code:
public class MainActivity : Activity, IOnTouchListener
{
Button dragAbleBt;
int screenWidth = 0;
int screenHeight = 0;
int lastX = 0, lastY = 0;
public bool OnTouch(View v, MotionEvent e)
{
MotionEventActions ea = e.Action;
switch (ea) {
case MotionEventActions.Down:
lastX = (int)e.RawX;
lastY = (int)e.RawY;
break;
case MotionEventActions.Move:
int dx = (int)e.RawX - lastX;
int dy = (int)e.RawY - lastY;
int left = v.Left + dx;
int right = v.Right + dx;
int top = v.Top + dy;
int bottom = v.Bottom + dy;
if (left < 0)
{
left = 0;
right = left + v.Width;
}
if (right > screenWidth)
{
right = screenWidth;
left = right - v.Width;
}
if (top < 0)
{
top = 0;
bottom = top + v.Height;
}
if (bottom > screenHeight)
{
bottom = screenHeight;
top = bottom - v.Height;
}
v.Layout(left, top, right, bottom);
lastX = (int) e.RawX;
lastY = (int) e.RawY;
v.PostInvalidate();
break;
case MotionEventActions.Up:
break;
}
return false;
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView (Resource.Layout.Main);
//DisplayMetrics dm = Resources.DisplayMetrics;
//screenWidth = dm.WidthPixels;
//screenHeight = dm.HeightPixels;
dragAbleBt = FindViewById<Button>(Resource.Id.button1);
dragAbleBt.SetOnTouchListener(this);
}
public override void OnWindowFocusChanged(bool hasFocus)
{
base.OnWindowFocusChanged(hasFocus);
if (hasFocus)
{
Rect outRect = new Rect();
this.Window.FindViewById(Window.IdAndroidContent).GetDrawingRect(outRect);
screenWidth = outRect.Width();
screenHeight = outRect.Height();
}
}
}
I tried detect screen size and restrict it but it still not good enough, is there any other available solution or settings?
You may got the whole screen width and height, the button will exceed the screen height, In this kind of situation you need get the view drawing area by this.Window.FindViewById(Window.IdAndroidContent).GetDrawingRect(outRect)
Screen Shot:
Note: I am using the emulator that is slow, If you are using the real device it will be faster.
I looked everywhere and haven't come across anything but I would like to know the best way to contain a selection rectangle so that it wouldn't go out of bounds. I have an application were user draws a selection rectangle on top of an image. The rectangle can be also be moved and resized. Currently I just use an exception handler which when an out of range exception is catched it would alert the user. The out of range exception only occurs when moving the drawn rectangle and I would like to make it more streamlined that the actual rectangle cant be dragged or resized outside of the image. Below is the xaml and code behind for my crop control.
Crop Control Code Behind:
public partial class CropControl : UserControl
{
#region Data's
private bool isDragging = false;
private Point anchorPoint = new Point();
private bool MoveRect = false; //flag which intially set to false which means a crop rectangle is not moved but created.
private bool MoveInProgress = false; //flag that is set to true if the crop rect is moving, otherwise false.
private Point LastPoint; // The drag's last point
HitType MouseHitType = HitType.None; //part of the rectangle under the mouse
private enum HitType { None, Body, UL, UR, LR, LL, L, R, T, B }; //Enum for the part of the rectangle the mouse is over.
#endregion
#region Constructor
public CropControl()
{
InitializeComponent();
}
#endregion
#region Dependency Property
//Register the Dependency Property
public static readonly DependencyProperty SelectionProperty =
DependencyProperty.Register("Selection", typeof(Rect), typeof(CropControl), new PropertyMetadata(default(Rect)));
public Rect Selection
{
get { return (Rect)GetValue(SelectionProperty); }
set { SetValue(SelectionProperty, value); }
}
// this is used, to react on changes from ViewModel. If you assign a
// new Rect in your ViewModel you will have to redraw your Rect here
private static void OnSelectionChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
{
Rect newRect = (Rect)e.NewValue;
Rectangle selectionRectangle = d as Rectangle;
if (selectionRectangle != null)
return;
selectionRectangle.SetValue(Canvas.LeftProperty, newRect.X);
selectionRectangle.SetValue(Canvas.TopProperty, newRect.Y);
selectionRectangle.Width = newRect.Width;
selectionRectangle.Height = newRect.Height;
}
#endregion
private Point lastLoc;
#region MouseLeftButtonDown Event
private void LoadedImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
lastLoc = new Point(Canvas.GetLeft(selectionRectangle), Canvas.GetTop(selectionRectangle));
//This statement will enable the creation of a new rectangle only if the mouse left
//button press is outside of a created rectangle and that crop rectangle was initially created.
//This is known since the HitType if outside the rectangle will always be set to None and the crop rect width > 0.
//The previous cropping rect will be removed by setting its value to null.
if (MouseHitType== HitType.None && selectionRectangle.Width>0)
{
selectionRectangle.Width = 0; //set crop rectangle's width to 0
selectionRectangle.Height = 0; //set crop rectangle's height to 0
SetMouseCursor();
MoveRect = false; //flag that crop rectangle is not being moved but drawn.
}
//This statement test if the crop rectangle is not being dragged and moved. If true it would
//set the x and y position of the crop rect in accordance to Canvas. If false it means that
//crop rectangle was already created and is now being moved to different position in the canvas.
if (!isDragging && !MoveRect)
{
anchorPoint.X = e.GetPosition(BackPanel).X; //get the x position of the mouse
anchorPoint.Y = e.GetPosition(BackPanel).Y; //get the y position of the mouse
isDragging = true; //flag that the user is dragging the mouse to create a rectangle
BackPanel.Cursor = Cursors.Cross; //change the cursor to a cross while left button is held down
}
else
{
MouseHitType = SetHitType(selectionRectangle, e.GetPosition(BackPanel)); //get hittype
SetMouseCursor(); //set the mouse cursor based on the hittype
if (MouseHitType == HitType.None) return;
LastPoint = e.GetPosition(BackPanel);
MoveInProgress = true; //flag true since rectangle is being moved
}
}
#endregion
private double CanvasTop, CanvasLeft;
#region MouseMove Event
private void LoadedImage_MouseMove(object sender, MouseEventArgs e)
{
Point offset = new Point((anchorPoint.X-lastLoc.X),(anchorPoint.Y-lastLoc.Y));
var newX=(anchorPoint.X+(e.GetPosition(BackPanel).X)-anchorPoint.X);
var newY=(anchorPoint.Y+(e.GetPosition(BackPanel).Y)-anchorPoint.Y);
CanvasTop = newX - offset.X;
CanvasLeft = newY - offset.Y;
//Statement that checks if crop rect is being created or moved. If moved it will set the
//dimension of the rectanlge and if not it would set the location of the new rectangle.
if (isDragging && !MoveRect)
{
double x = e.GetPosition(BackPanel).X; //get x position of mouse
double y = e.GetPosition(BackPanel).Y; //get y position of mouse
selectionRectangle.SetValue(Canvas.LeftProperty, Math.Min(x, anchorPoint.X)); //set the bottom
selectionRectangle.SetValue(Canvas.TopProperty, Math.Min(y, anchorPoint.Y)); //set the top
selectionRectangle.Width = Math.Abs(x - anchorPoint.X); //set the width
selectionRectangle.Height = Math.Abs(y - anchorPoint.Y); //set the height
if (selectionRectangle.Visibility != Visibility.Visible) //make crop rectangle visible if its not.
selectionRectangle.Visibility = Visibility.Visible;
}
else if (!isDragging && MoveRect)
{
if (!MoveInProgress)
{
MouseHitType = SetHitType(selectionRectangle, e.GetPosition(BackPanel));
SetMouseCursor();
}
else
{
// See how much the mouse has moved.
Point point = e.GetPosition(BackPanel);
double offset_x = point.X - LastPoint.X;
double offset_y = point.Y - LastPoint.Y;
// Get the rectangle's current position.
double new_x = Canvas.GetLeft(selectionRectangle);
double new_y = Canvas.GetTop(selectionRectangle);
double new_width = selectionRectangle.Width;
double new_height = selectionRectangle.Height;
// Update the rectangle.
switch (MouseHitType)
{
case HitType.Body:
new_x += offset_x;
new_y += offset_y;
break;
case HitType.UL:
new_x += offset_x;
new_y += offset_y;
new_width -= offset_x;
new_height -= offset_y;
break;
case HitType.UR:
new_y += offset_y;
new_width += offset_x;
new_height -= offset_y;
break;
case HitType.LR:
new_width += offset_x;
new_height += offset_y;
break;
case HitType.LL:
new_x += offset_x;
new_width -= offset_x;
new_height += offset_y;
break;
case HitType.L:
new_x += offset_x;
new_width -= offset_x;
break;
case HitType.R:
new_width += offset_x;
break;
case HitType.B:
new_height += offset_y;
break;
case HitType.T:
new_y += offset_y;
new_height -= offset_y;
break;
}
// Don't use negative width or height.
if ((new_width > 0) && (new_height > 0))
{
// Update the rectangle.
Canvas.SetLeft(selectionRectangle, new_x);
Canvas.SetTop(selectionRectangle, new_y);
selectionRectangle.Width = new_width;
selectionRectangle.Height = new_height;
// Save the mouse's new location.
LastPoint = point;
}
}
}
}
#endregion
#region MouseLeftButtonUp Event
private void LoadedImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
//statement which checks if the mouse left button action is for either creating or
//moving the crop rectangle. If true, isDragging=false since the crop rect is created
//and moverect = true since the created rectangle is ready to be moved.
if (isDragging && !MoveRect)
{
isDragging = false;
if (selectionRectangle.Width > 0)
{
MoveRect = true;
}
}
else
{
MoveInProgress = false; //flags Move in progress as false since rect move action is done.
}
// Set the Selection to the new rect, when the mouse button has been released
Selection = new Rect(
(double)selectionRectangle.GetValue(Canvas.LeftProperty),
(double)selectionRectangle.GetValue(Canvas.TopProperty),
selectionRectangle.Width,
selectionRectangle.Height);
}
#endregion
#region Mutator's
// Return a HitType value to indicate what is at the point.
private HitType SetHitType(Rectangle rect, Point point)
{
double left = Canvas.GetLeft(selectionRectangle);
double top = Canvas.GetTop(selectionRectangle);
double right = left + selectionRectangle.Width;
double bottom = top + selectionRectangle.Height;
//statement that checks if cursor is outside the area of the crop rectangle
//and returns HitType.None.
if (point.X < left) return HitType.None;
if (point.X > right) return HitType.None;
if (point.Y < top) return HitType.None;
if (point.Y > bottom) return HitType.None;
const double GAP = 10; //sets the gap which when mouse over a cursor change is triggered
//statement that checks where the mouse is located within the rectangle.
if (point.X - left < GAP)
{
// Left edge.
if (point.Y - top < GAP) return HitType.UL;
if (bottom - point.Y < GAP) return HitType.LL;
return HitType.L;
}
if (right - point.X < GAP)
{
// Right edge.
if (point.Y - top < GAP) return HitType.UR;
if (bottom - point.Y < GAP) return HitType.LR;
return HitType.R;
}
if (point.Y - top < GAP) return HitType.T;
if (bottom - point.Y < GAP) return HitType.B;
return HitType.Body;
}
// Set a mouse cursor appropriate for the current hit type.
private void SetMouseCursor()
{
// See what cursor we should display.
Cursor desired_cursor = Cursors.Arrow;
switch (MouseHitType)
{
case HitType.None:
desired_cursor = Cursors.Arrow;
break;
case HitType.Body:
desired_cursor = Cursors.ScrollAll;
break;
case HitType.UL:
case HitType.LR:
desired_cursor = Cursors.SizeNWSE;
break;
case HitType.LL:
case HitType.UR:
desired_cursor = Cursors.SizeNESW;
break;
case HitType.T:
case HitType.B:
desired_cursor = Cursors.SizeNS;
break;
case HitType.L:
case HitType.R:
desired_cursor = Cursors.SizeWE;
break;
}
// Display the desired cursor.
if (BackPanel.Cursor != desired_cursor)
BackPanel.Cursor = desired_cursor;
}
#endregion
}
Crop Control XAML:
<UserControl.Resources>
<Storyboard x:Key="MarchingAnts">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="selectionRectangle"
Storyboard.TargetProperty="(Shape.StrokeDashOffset)"
RepeatBehavior="Forever">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000"
Value="10"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource MarchingAnts}"/>
</EventTrigger>
</UserControl.Triggers>
<Canvas Name="BackPanel" Background="Transparent" MouseLeftButtonDown="LoadedImage_MouseLeftButtonDown" MouseMove="LoadedImage_MouseMove" MouseLeftButtonUp="LoadedImage_MouseLeftButtonUp">
<Rectangle Name="selectionRectangle" Stroke="#FFFFFFFF"
StrokeThickness="1" StrokeDashOffset="0"
Fill="#220000FF" Visibility="Collapsed"
StrokeDashArray="5"/>
</Canvas>
Sorry for the confusion but i changed my explanation. The rectangle don't go out of bounds when drawn but only happens if the drawn rectangle is moved. Also the exception is caught in my view model's crop method which is shown below:
public void Crop()
{
////Get a copy of the selection in case it changes during execution
Rect cropSelection = Selection;
//// use it to crop your image
Int32Rect rcFrom = new Int32Rect();
rcFrom.X = (int)((cropSelection.X) * (ImagePath.Width) / (ImagePath.Width));
rcFrom.Y = (int)((cropSelection.Y) * (ImagePath.Height) / (ImagePath.Height));
rcFrom.Width = (int)cropSelection.Width;
rcFrom.Height = (int)cropSelection.Height;
try
{
BitmapSource bs = new CroppedBitmap(ImagePath as BitmapSource, rcFrom);
CroppedImage = bs;
}
catch (Exception e)
{
MessageBox.Show("Selection Rectangle is outside the image." + "\n" + "Adjust the cropping rectangle so it's within the boundaries of the Image ", " Error Message", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
Update:
I was able to get it working by calculating the size and position of the selection rectangle against its parent (Canvas) which takes takes the same size as the image. Below is what I added to my code.
double bottom = new_y + selectionRectangle.Height;
double right = new_x+selectionRectangle.Width;
if (new_y< 0)
new_y = 0;
if (new_x < 0)
new_x = 0;
if (bottom > BackPanel.ActualHeight)
new_y = BackPanel.ActualHeight-selectionRectangle.Height;
if (right > BackPanel.ActualWidth)
new_x = BackPanel.ActualWidth - selectionRectangle.Width;
if (new_height > BackPanel.ActualHeight)
new_height = BackPanel.ActualHeight;
if (new_width > BackPanel.ActualWidth)
new_width = BackPanel.ActualWidth;
The new_height and new_width was added because an exception is still thrown if the rectangle occupies the entire image.
If i correctly understood question - you shows message to the user when selection rect goes outside of image rect? If so, why not check that: if new selection state will out of image area - then just not move selection and keep it in old state? I mean - compare borders positions of new selection rect with image rect and make decision: move or not your selection rect in new position (or change or not it's size).
Okay, I am pretty new to Kinect, I have the joints tracked and drawn however I cannot for the life of me draw the bones between each joint.
I have this code which will draw the joints of the skeleton
private void DrawBody(Body body) //takes body as argument
{
// Draw points
foreach (JointType type in body.Joints.Keys)
{
// Draw all the body joints
switch (type)
{
case JointType.Head:
case JointType.FootLeft:
case JointType.FootRight:
DrawJoint(body.Joints[type], 20, Brushes.Yellow, 2, Brushes.White);
break;
case JointType.ShoulderLeft:
case JointType.ShoulderRight:
case JointType.HipLeft:
case JointType.HipRight:
DrawJoint(body.Joints[type], 20, Brushes.YellowGreen, 2, Brushes.White);
break;
case JointType.ElbowLeft:
case JointType.ElbowRight:
case JointType.KneeLeft:
case JointType.KneeRight:
DrawJoint(body.Joints[type], 15, Brushes.LawnGreen, 2, Brushes.White);
break;
case JointType.HandLeft:
DrawHandJoint(body.Joints[type], body.HandLeftState, 20, 2, Brushes.White);
break;
case JointType.HandRight:
DrawHandJoint(body.Joints[type], body.HandRightState, 20, 2, Brushes.White);
break;
default:
DrawJoint(body.Joints[type], 15, Brushes.RoyalBlue, 2, Brushes.White);
break;
}
}
}
My DrawJoint Function:
private void DrawJoint(Joint joint, double radius, SolidColorBrush fill, double borderWidth, SolidColorBrush border)
{
//If Joint not tracked then return Joint
if (joint.TrackingState != TrackingState.Tracked) return;
// Map the CameraPoint to ColorSpace so they match
ColorSpacePoint colorPoint = kinectSensor.CoordinateMapper.MapCameraPointToColorSpace(joint.Position);
// Create the UI element based on the parameters
Ellipse El = new Ellipse();
El.Fill = fill;
El.Stroke = border;
El.StrokeThickness = borderWidth;
El.Width = 25;
El.Height = 25;
radius = 25;
// Add the Ellipse to the canvas
SkeletonCanvas.Children.Add(El);
// Avoid exceptions based on bad tracking
if (float.IsInfinity(colorPoint.X) || float.IsInfinity(colorPoint.X)) return;
// Allign ellipse on canvas
Canvas.SetLeft(El, colorPoint.X);
Canvas.SetTop(El, colorPoint.Y);
}
Now I am stuck, from this point onwards how would I draw the 'Bones' of the body between each joint on a canvas similiar to how I added the Eclipse for the Joints?.
Any help is appreciated thanks
In your DrawBody(Body body) function, you'll need to set up the "bones" that you want to draw. Eg:
private void DrawBody(Body body)
{
// left forearm
DrawBone(body.Joints[JointType.HandLeft], body.Joints[JointType.ElbowLeft]);
// right forearm
DrawBone(body.Joints[JointType.HandRight], body.Joints[JointType.ElbowRight]);
// ...etc...
}
The DrawBone(Joint, Joint) function would look something like this:
private void DrawBone(Joint first, Joint second)
{
Line line = new Line();
line.Stroke = Brushes.LightSteelBlue;
line.X1 = first.Position.X;
line.X2 = second.Position.X;
line.Y1 = first.Position.Y;
line.Y2 = second.Position.Y;
line.StrokeThickness = 2;
myCanvas.Children.Add(line);
}
I'm working from memory here so syntax might be off a little.
On MouseDownEvent I set upper left corner of Ellipse I'm trying to draw.
public MyCircle(Point location)
{
ellipseObject = new Ellipse
{
Stroke = Brushes.Black,
StrokeThickness = 2,
Margin = new Thickness(location.X, location.Y, 0, 0)
};
}
Then on MouseMoveEvent I update Width and Height properties and it works fine as long as I don't move mouse above or/and to the left of my Ellipse upper left corner, in that case I'm getting exception that these properties can't be negative (which of course makes perfect sense).
public void Draw(Point location)
{
if (ellipseObject != null)
{
ellipseObject.Width = location.X - ellipseObject.Margin.Left;
ellipseObject.Height = location.Y - ellipseObject.Margin.Top;
}
}
The problem doesn't exist with drawing lines:
public void Draw(Point location)
{
lineObject.X2 = location.X;
lineObject.Y2 = location.Y;
}
I know it's trivial, but I'm completely stuck on this. How should I handle drawing Ellipses?
I had this EXACT problem when trying to create a crop tool. Problem is that you need to create if statements for when the cursor goes negative X or negative Y from your starting point. For starters, you'll need to have a global Point that you mark as your 'start' point. Also specify a global current point position that we'll talk about in a minute.
public Point startingPoint;
public Point currentPoint;
Then, make sure you have an onMouseDown event on whatever control you are trying to put the ellipse on.
private void control_MouseDown(object sender, MouseEventArgs e)
{
startingPoint.X = e.X;
startingPoint.Y = e.Y;
}
Then, you need to create if statements in your MouseMove event to check with point (current mouse position, or starting point) has a lower X/Y value
private void control_MouseMove(object sender, MouseEventArgs e)
{
//The below point is what we'll draw the ellipse with.
Point ellipsePoint;
Ellipse ellipseObject = new Ellipse();
currentPoint.X = e.X;
currentPoint.Y = e.Y;
//Then we need to get the proper width/height;
if (currentPoint.X >= startingPoint.X)
{
ellipsePoint.X = startingPoint.X;
ellipseObject.Width = currentPoint.X - startingPoint.X;
}
else
{
ellipsePoint.X = currentPoint.X;
ellipseObject.Width = startingPoint.X - currentPoint.X;
}
if (currentPoint.Y >= startingPoint.Y)
{
ellipsePoint.Y = startingPoint.Y;
ellipseObject.Height = currentPoint.Y - startingPoint.Y;
}
else
{
ellipsePoint.Y = currentPoint.Y;
ellipseObject.Height = startingPoint.Y - currentPoint.Y;
}
ellipseObject.Stroke = Brushes.Black;
ellipseObject.StrokeThickness = 2;
ellipseObject.Margin = new Thickness(ellipsePoint.X, ellipsePoint.Y, 0, 0);
}
Hope this helps!
Save the origin point separately and set the X and Y properties of the Ellipse's Margin to the mouse position and the Width and Height to the distances between the mouse and origin point.
Untested:
public MyCircle(Point location)
{
ellipseObject = new Ellipse
{
Stroke = Brushes.Black,
StrokeThickness = 2,
Margin = new Thickness(location.X, location.Y, 0, 0)
Tag = new Point(location.X, location.Y)
};
}
public void Draw(Point location)
{
if (ellipseObject != null)
{
Point o = (Point)ellipseObject.Tag;
double x = Math.Min(location.X, o.Left);
double y = Math.Min(location.Y, o.Top);
double width = Math.Abs(Math.Max(location.X, o.Left) - x);
double height = Math.Abs(Math.Max(location.Y, o.Top) - y);
ellipseObject.Margin.X = x;
ellipseObject.Margin.Y = y;
ellipseObject.Width = width;
ellipseObject.Height = height;
}
}