How to update wireframe without WPF button click? - c#

I'm developing a Windows Form application with WPF User Control embedded in the WF. If I add a button and execute my userControl.DrawWireFrameCube(); My ViewPort3D get updated. I'm using Helix 3D Toolkit. But If I call my method from my MainWindowForm class it doesn't get executed and UI is not updated,but only userControl.DrawWireFrameCube(); isn't working. The other userControl.Draw3DObject(insertionPoint, points, color); method is working fine.
private void VisualizePart(int index)
{
InsertionPoint insertionPoint = new InsertionPoint
{
X = _duplicatedListParts[index].INFO1,
Y = _duplicatedListParts[index].INFO2,
Z = _duplicatedListParts[index].INFO3
};
DetailSize points = new DetailSize
{
Length = _duplicatedListParts[index].LENGTH,
Width = _duplicatedListParts[index].WIDTH,
Thickness = _duplicatedListParts[index].THICKNESS
};
userControl.Dispatcher.Invoke(() =>
{
System.Windows.Media.Color color = System.Windows.Media.Color.FromRgb(255, 90, 0);
userControl.Draw3DObject(insertionPoint, points, color);
userControl.DrawWireFrameCube();
});
}
The difference is that in my Draw3DObject() I add items to Model3DGroup and in DrawWireFrameCube() I add items to MyViewPort3D. I'm not using XAML and I want to stay that way.
Any ideas what is wrong here?
P.S I love negative vote without explanation :)

Related

UWP XAML BladeView control - scroll newly-created BladeItem into view

I'm using the BladeView control from Microsoft's Windows Community Toolkit. When the application window is < 640px, the BladeMode property changes to Fullscreen.
When a new blade is created in my code behind, I want the BladeView to scroll to the right so that new blade is displayed. It seems like I should be able to use StartBringIntoView() to accomplish this, but it's not doing anything.
Here's what I'm doing:
if (bladeView.BladeMode == BladeMode.Fullscreen)
{
// current window width
Rect windowBounds = Window.Current.Bounds;
int currentWidth = (int)windowBounds.Width;
// scroll to view
BringIntoViewOptions opts = new BringIntoViewOptions();
Rect target = new Rect { Height = windowBounds.Height, Width = windowBounds.Width, X = currentWidth, Y = 0 };
opts.TargetRect = target;
newBlade.StartBringIntoView(opts);
}
This is what my XAML tree looks like:
I just needed to use bladeView.UpdateLayout() before calling StartBringIntoView().
Example:
if (bladeView.BladeMode == BladeMode.Fullscreen)
{
// update the layout so StartBringIntoView() works
bladeView.UpdateLayout();
// scroll BladeView to newly-created BladeItem
newBlade.StartBringIntoView();
}

Xamarin iOS - Mapkit ArgumentNullException: Value cannot be null

My question is similar to this but I am not sure how my code relates to the answers given in the other post.
I am using MapKit in Xamarin iOS to create a custom map for my Xamarin iOS project. I have a few different custom things happening at the moment, and am using Polygons annotations and now circles that are added to my map.
I have just started implementing adding MKCircle to my map, but when I try to add Circle Overlays to my map I am receiving this error:
System.ArgumentNullException: Value cannot be null. Parameter name: polygon
I think it is being I trying to return the same overlay to two renderers, but I am not sure how to ammend this. Here is my code:
for(int i=0; i < hazards.Count; i++) //This adds 3 circles in my example
{
LatLong ltlng = JsonConvert.DeserializeObject<LatLong>(hazards[i].coordinates);
coords[i].Latitude = Convert.ToDouble(ltlng.latitude);
coords[i].Longitude = Convert.ToDouble(ltlng.longitude);
var overlay = MKCircle.Circle(coords[i], Convert.ToDouble(hazards[i].radius));
nativeMap.AddOverlay(overlay); //this is the suspected problem
}
And my renderer code here:
MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlayWrapper)
{
if (!Equals(overlayWrapper, null))
{
var overlay = ObjCRuntime.Runtime.GetNSObject(overlayWrapper.Handle) as IMKOverlay;
polygonRenderer = new MKPolygonRenderer(overlay as MKPolygon)
{
FillColor = UIColor.Red,
StrokeColor = UIColor.Blue,
Alpha = 0.4f,
LineWidth = 9
};
}
return polygonRenderer;
}
Do I need to add something to my renderer code like this?:
circleRenderer = new MKCircleRenderer(overlay as MKCircle){};
It appears all your overlays are MKCircle based:
var overlay = MKCircle.Circle(coords[i]
In your GetOverlayRenderer you casting all overlays received as MKPolygon objects which will result in a null object.
polygonRenderer = new MKPolygonRenderer(overlay as MKPolygon)
You are then trying to create a MKPolygonRenderer render for each of your overlays which would not work if you actually did have an MKCircle-based overlay.
If all your overlays are MKCircle based, then yes use:
new MKCircleRenderer(overlay as MKCircle){};

Accessing shapes in ILPanel and ILCamera

I have three question regarding ILPanel in ILNumerics:
How can I disable the double click interaction of ILPanel to reset the view.
How can I increase the speed of panning using right click and drag. The panning is very slow especially when the shape is vary large.
How can access the elements that I add to a camera and modify them.
Here is a simple example. Two spheres are added to a camera and a ILLable, "Hello", is on top of one of them (the blue one). I want the "Hello" label to jump on top of the green sphere if I rotate the scene with mouse and the green sphere become closer to the camera and visa verse. And, how can I change the color of the spheres say by clicking a button?
private void ilPanel1_Load(object sender, EventArgs e)
{
var scene = new ILScene();
var cam = scene.Camera;
var Sphere1 = new ILSphere();
Sphere1.Wireframe.Visible = true;
Sphere1.Fill.Color = Color.Blue;
Sphere1.Wireframe.Color = Color.Blue;
Sphere1.Transform = Matrix4.Translation(0, 0, 0);
var Sphere2 = new ILSphere();
Sphere2.Wireframe.Visible = true;
Sphere2.Transform = Matrix4.Translation(2, 0, 0);
cam.Add(Sphere1);
cam.Add(Sphere2);
cam.Add(new ILLabel("Hello")
{
Font = new System.Drawing.Font(FontFamily.GenericSansSerif, 8),
Position = new Vector3(0, 0, 1.1),
Anchor = new PointF(0, 1),
});
ilPanel1.Scene = scene;
}
Create a label, which is always on top of other 3D objects
cam.Add(
new ILScreenObject() {
Location = new PointF(0.5f, 0.5f),
Children = {
new ILLabel("Hello")
}
});
See also: http://ilnumerics.net/world3d-and-screen2d-nodes.html
Regarding your "jumping sphere" example: if your want your label to jump to another group (spheres are groups actually) at runtime, you will have to implement that logic into a function which is called at runtime. ilPanel1.BeginRenderFrame might be a good place to check for such updates.
Disable default behavior for the first camera:
scene.Camera.MouseDoubleClick += (_, arg) => {
arg.Cancel = true;
};
See: http://ilnumerics.net/mouse-events.html
React on a button press:
button1.Click += (_,args) => {
ilPanel1.Scene.First<ILSphere>().Fill.Color = Color.Red;
ilPanel1.Refresh();
};
Finding objects in the scene:
see: http://ilnumerics.net/nodes-accessing-managing.html
Controlling the panning speed:
There is no easy way to configure the speed currently. The best way would be to implement the corresponding mouse handler on your own:
Override MouseMove for the camera node.
Implement the panning similar to the way it was done in ILNumerics (see: ILCamera.OnMouseMove in the sources).
Increase the scale factor.
Dont forget to cancel the event processing at the end of your handler.

Performance issue of DrawingVisual following cursor while using onMouseMove event

I'm busy with a small application in which I want to display information at the location of the cursor when it hoovers over a Canvas. The Canvas in question is a custom one (inherited from Canvas) which provides functionality to add DrawingVisuals (as shown in basically every tutorial on displaying large amounts of geometric shapes on a canvas).
I would like to display a vertical line and horizontal line as well as the local coordinates (p in the code below) which are directly derived from the canvas coordinates (v). At the moment I'm rendering these objects at position (0,0) and use offset during the OnMouseMove event to update their location.
The horizontal and vertical lines are rendered in the DrawingVisual _cursor and the location in local y,z-coordinates in _info.
private void oCanvas_MouseMove(object sender, MouseEventArgs e)
{
#region 1. Get location data
System.Windows.Vector v = (System.Windows.Vector)e.GetPosition(oCanvas);
// point in YZ coordinates
BSMath.DoubleXY p = new BSMath.DoubleXY();
p.X = (oCanvas.OriginY - v.Y) / oCanvas.ZoomFactor;
p.Y = (oCanvas.OriginX - v.X) / oCanvas.ZoomFactor;
#endregion
#region 2. Update cursor and info
if (oSettings.ShowInformation)
{
_info.Info = p.X.ToString("0.0") + " | " + p.Y.ToString("0.0");
_info.Render(0, 0);
_info.Visual.Offset = v;
}
// move cursor
_cursor.Visual.Offset = v;
}
Using the mousemove event seems to be creating a lot of overhead and I can see that there are issues tracking the mouse movements when I move the mouse quickly.
Can anyone recommend a better way of creating the same effect?
example http://www.iccg.be/test/images/canvas.jpg
Edit:
I investigated it a bit further and the problem seems to occur when the resolution of the canvas is bigger. If it is a 600x400 canvas then there is no delay, but when it is around 1000x800 I get the problem with delays when hoovering. The performance also improves if I use user drawn crosshairs instead of the lines that have the full width/ height of the canvas.
I recently have built something similar and haven't had any performance issues.
Did it the very simple way by adding the stuff directly on the canvas.
The drawn items are in a second canvas behind the mouse position canvas. Both reside in a Grid.
This is for sure not the most sophisticated way to solve this, but it works quite well for me.
Here's the code:
private Point _previous;
private Point _current;
private Line _xLine;
private Line _yLine;
private TextBlock _displayTextBlock;
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
_current = e.GetPosition(myCanvas);
if (_previous != _current)
{
if (_xLine == null)
{
_xLine = new Line() {X1 = 0, X2 = myCanvas.ActualWidth, Stroke = new SolidColorBrush(Colors.Black)};
_yLine = new Line() {Y1 = 0, Y2 = myCanvas.ActualHeight, Stroke = new SolidColorBrush(Colors.Black)};
_displayTextBlock = new TextBlock();
myCanvas.Children.Add(_xLine);
myCanvas.Children.Add(_yLine);
myCanvas.Children.Add(_displayTextBlock);
}
_displayTextBlock.SetValue(Canvas.TopProperty, _current.Y);
_displayTextBlock.SetValue(Canvas.LeftProperty, _current.X);
_displayTextBlock.Text = _current.X.ToString() + " | " + _current.Y.ToString();
_xLine.Y1 = _current.Y;
_xLine.Y2 = _current.Y;
_yLine.X1 = _current.X;
_yLine.X2 = _current.X;
_previous = _current;
}
}

WPF, animate over container boundaries

I'm learning WPF and have a specific goal.
Imagine you have a grid (3 rows by 3 columns), and a control, say a simple blue rectangle fills the middle cell. When I click on the cell I want the square to rotate smoothly through 180 degrees.
The specific issue I have at the moment is; as the rectangle rotates, it won't change its dimensions, so it will extend beyond the boundary of the cell. I don't want it to clip, i want it to appear on top, partially obscuring surrounding cells.
The second part of this is, if there is one cell that fills the entire window, and I click on the blue rectangle in that cell, can I make the rectangle rotate and extend beyond the sides of the form?
If that doesn't make sense, please ask. I'm finding it hard to google because I don't know the exact terms I should be using.
Thank you
The first part can be acomplished by using the attached property Panel.ZIndex, set it to a high value when you start the animation and a lower value when the animation is complete. The second part (having a control outside of the window) is more complicated. I tried a few things and this method seemed to be the best. It uses a full screen window instead of a Popup as I encountered cliping issues. A copy of the element is made using RenderTargetBitmap this is then placed in the same position. The original element is hidden whilst the copy is animated.
public void PopupAnimation(UIElement element)
{
double w = element.RenderSize.Width,h = element.RenderSize.Height;
var screen = new Canvas();
var pos = element.PointToScreen(new Point(0, 0));
var rtb = new RenderTargetBitmap((int)w,(int)h, 96, 96, PixelFormats.Pbgra32);
rtb.Render(element);
Image i = new Image { Source = rtb, Width = w, Height = h,Stretch=Stretch.Fill};
Canvas.SetLeft(i, pos.X);
Canvas.SetTop(i, pos.Y);
screen.Children.Add(i);
var window = new Window() {
Content = screen, AllowsTransparency = true,
Width=SystemParameters.PrimaryScreenWidth,Height=SystemParameters.PrimaryScreenHeight,
WindowStyle=WindowStyle.None,ShowInTaskbar=false,Topmost=true,
Background=Brushes.Transparent,ShowActivated=false,Left=0,Top=0
};
var transform = new RotateTransform();
i.RenderTransformOrigin = new Point(0.5, 0.5);
i.RenderTransform = transform;
var anim = new DoubleAnimation { To = 360 };
anim.Completed += (s,e) =>
{
element.Visibility = Visibility.Visible;
var delay = new Storyboard { Duration = TimeSpan.FromSeconds(0.1) };
delay.Completed += (s2, e2) => window.Close();
delay.Begin();
};
window.ContentRendered += (s, e) =>
{
transform.BeginAnimation(RotateTransform.AngleProperty, anim);
element.Visibility = Visibility.Hidden;
};
window.Show();
}

Categories

Resources