Zoom an object in viewport to fill the screen - c#

I have a requirement where I have to rotate an object in the viewport (only) and then to zoom the object to fill the entire screen size. I am using the below method to rotate and zoom the object in Autodesk Map 3d 2015
public void RotateZoomStakingGrid(Viewport vp, double mRotation, Point2d ptCenter, double aspectEnt,ObjectId Arg_oSelectedObjects,Transaction tr)
{
AcadApplication app = (AcadApplication)Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication;
Document myDoc = acadApp.DocumentManager.MdiActiveDocument;
Editor ed = myDoc.Editor;
Database db = HostApplicationServices.WorkingDatabase;
vp.UpgradeOpen();
mRotation = -Math.PI * 2.0 - mRotation;
vp.TwistAngle += mRotation;
vp.On = true;
vp.ViewTarget = new Point3d(ptCenter.X, ptCenter.Y, 0);
double mScrRatio;
// width/height
mScrRatio = (vp.Width / vp.Height);
Point3d mMaxExt = db.Extmax;
Point3d mMinExt = db.Extmin;
Extents3d mExtents = new Extents3d();
mExtents.Set(mMinExt, mMaxExt);
// prepare Matrix for DCS to WCS transformation
Matrix3d matWCS2DCS;
matWCS2DCS = Matrix3d.PlaneToWorld(vp.ViewDirection);
matWCS2DCS = Matrix3d.Displacement(
vp.ViewTarget - Point3d.Origin)
* matWCS2DCS;
matWCS2DCS = Matrix3d.Rotation(
-vp.TwistAngle, vp.ViewDirection,
vp.ViewTarget) * matWCS2DCS;
matWCS2DCS = matWCS2DCS.Inverse();
// tranform the extents to the DCS
// defined by the viewdir
mExtents.TransformBy(matWCS2DCS);
Entity gridEnt = tr.GetObject(Arg_oSelectedObjects, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead) as Entity;
Extents3d entityExtent = gridEnt.GeometricExtents;
entityExtent.TransformBy(matWCS2DCS);
Point2d ptCenterTemp = new Point2d(
(entityExtent.MaxPoint.X + entityExtent.MinPoint.X) * 0.5,
(entityExtent.MaxPoint.Y + entityExtent.MinPoint.Y) * 0.5);
// width of the entity extents in current view
double mWidth;
mWidth = (entityExtent.MaxPoint.X - entityExtent.MinPoint.X);
//height of the entity extents in current view
double mHeight;
mHeight = (entityExtent.MaxPoint.Y - entityExtent.MinPoint.Y);
//get the view center point
Point2d mCentPt = new Point2d(((entityExtent.MaxPoint.X + entityExtent.MinPoint.X) * 0.5), ((entityExtent.MaxPoint.Y + entityExtent.MinPoint.Y) * 0.5));
//check if the width 'fits' in current window,if not then get the new height as per the viewports aspect ratio
if (mWidth > (mHeight * mScrRatio)) mHeight = mWidth / mScrRatio;
vp.ViewHeight = mHeight * 0.55; //set the ; height - adjusted by 0.7%
vp.ViewCenter = mCentPt; //set the view center
vp.DowngradeOpen();
vp.UpdateDisplay();
ed.SwitchToModelSpace();
}
My concern is that the above code works fine on my system but when I deploy the DLL to some other system then the object is not fully zoomed to fit screen. I have played with the zoomfactor but I guess it changes on the screen resolution. Could you please point out where exactly I am going wrong?

Related

How to rotate a line in UWP?

Currently I need to rotate a line about the midpoint based on angles generically. I have tried using Rotate Transform but it works finely for some angle but doest gives the exact result for some other angles. Kindly suggest if there any solution for rotation .
cx= (line.X1+line.2)/2;
cy=(line.Y1+line.Y2)/2;
RotateTransform transform = new RotateTransform();
transform.Angle = angle;
transform.CenterX = cx / zoomFactor;
transform.CenterY = cy / zoomFactor;
group.Children.Add(transform);
line.RenderTransform = group;
var cx = new Point( (line.X2 - line.X1)/2, (line.Y2 - line.Y1) / 2);
var rotate = new RotateTransform
{
Angle = angle
};
var translate = new TranslateTransform
{
X = (line.X1 + cx.X),
Y = (line.Y1 + cx.Y)
};
var group = new TransformGroup
{
Children =
{
(Transform) translate.Inverse,
rotate,
translate
}
};
line.RenderTransform = group;

Monodroid DensityDpi to Int

I need to convert DensityDpi to Int. I tried like this:
int dens = dm.DensityDpi;
and of curse it doesn't work. The complete code is:
DisplayMetrics dm = new DisplayMetrics();
WindowManager.DefaultDisplay.GetMetrics(dm);
int width = dm.WidthPixels;
int height = dm.HeightPixels;
int dens = dm.DensityDpi;
double wi = (double)width / (double)dens;
double hi = (double)height/(double)dens;
double x = Math.Pow(wi,2);
double y = Math.Pow(hi,2);
double screenInches = Math.Sqrt(x+y);
I'm trying to find the inch of screen.
Considering that there show that constants are int I don't know why it doesn't work.
( http://developer.android.com/reference/android/util/DisplayMetrics.html )
I think that are same things.
For Android:
var metrics = new DisplayMetrics();
this.WindowManager.DefaultDisplay.GetMetrics(metrics);
private const float INCH = 25.4f;
var ydpi = metrics.Ydpi; // dpi in vertical direction
var xdpi = metric.Xdpi; // dpi in horizontal direction
var pHeight = metrics.HeightPixels; // total pixels in vertical direction
var pWidth = metrics.WidthPixels; // total pixels in horizontal direction
var iHeight = (pHeight / ydpi); // screenheight in inches
var iWidth = (pWidth / xdpi); // screenwidth in inches
var mHeight = (pHeight / ydpi) * INCH; // screenheight in millimeters
var mWidth = (pWidth / xdpi) * INCH; // screenwidth in millimeters
Afaik there is no way to query an iOS-device directly about it's DPI.
You can however calculate it using some constants. iPhone's are 163 ppi and iPhone Retina's are exactly double that.
private const float INCH = 25.4f;
var ppi = 163 * UIScreen.MainScreen.Scale; // pixels per inch for an iPhone or iPhone Retina
var ppmm = ppi / INCH; // pixels per millimeter
var pHeight = UIScreen.MainScreen.ApplicationFrame.Height; // screen height in pixels
var pWidth = UIScreen.MainScreen.ApplicationFrame.Width; // screen width in pixels
var iHeight = (pHeight / ppi); // screen height in millimeters
var iWidth = (pWidth / ppi); // screen height in millimeters
var mHeight = (pHeight / ppi) * INCH; // screen height in millimeters
var mWidth = (pWidth / ppi) * INCH; // screen height in millimeters
I have implemented abstraction over the display properties in Xamarin.Forms.Labs project. Although it is targeting Xamarin.Forms it can also be used without it. For Android and WP8 the properties are calculated but for iOS they are determined by the hardware version of the device. You can install the packages from NuGet (Xamarin.Forms.Labs) for each platform (iOS, Android, WP8) to get a fully functional, tested and easy to use classes.
Here is link for the full source code for the Android display:
https://github.com/XForms/Xamarin-Forms-Labs/blob/master/src/Xamarin.Forms.Labs/Xamarin.Forms.Labs.Droid/Device/Display.cs
public Display()
{
var dm = Metrics;
this.Height = dm.HeightPixels;
this.Width = dm.WidthPixels;
this.Xdpi = dm.Xdpi;
this.Ydpi = dm.Ydpi;
this.FontManager = new FontManager(this);
}
public static Android.Util.DisplayMetrics Metrics
{
get
{
return Application.Context.Resources.DisplayMetrics;
}
}
The physical size is calculated with extension methods (so they can be reused by all platforms) based on the display density:
https://github.com/XForms/Xamarin-Forms-Labs/blob/master/src/Xamarin.Forms.Labs/Xamarin.Forms.Labs/Device/DisplayExtensions.cs
public static double ScreenSizeInches(this IDisplay screen)
{
return Math.Sqrt(Math.Pow(screen.ScreenWidthInches(), 2) + Math.Pow(screen.ScreenHeightInches(), 2));
}
public static double ScreenWidthInches(this IDisplay screen)
{
return screen.Width / screen.Xdpi;
}
public static double ScreenHeightInches(this IDisplay screen)
{
return screen.Height / screen.Ydpi;
}
Here is a screenshot of the Android info:
Also available for iOS & WP8:

Detect Pushpins Inside a VE Shape on a Bing Map

I have a map which populates pushpins from a database. And a circle. I want to be able to figure out what other pushpins are within the VE Shape circles radius and create a list of their addresses.
function addPushPin(lat, long) {
//var point = new Microsoft.Maps.Point(e.getX(), e.getY());
//var pushpinLocation = new(lat, long);
var s = new VEShape(VEShapeType.Pushpin, new VELatLong(lat,long));
var customIcon = new VECustomIconSpecification();
//customIcon.TextContent = "yo bana4na4";
customIcon.Image = "http://universidadescancun.com/wp-content/themes/GeoUnis3/images/pinpoint-fiesta.png";
//customIcon.ImageOffset = new VEPixel();
s.SetTitle("First Pin <span style=color:red>Demo Title<>/span>");
s.SetDescription("This comes to the <b>description</b> of pushpin.");
s.SetMoreInfoURL("http://dotnetricks.blogspot.com");
s.SetPhotoURL("http://upload.wikimedia.org/wikipedia/commons/8/8a/Banana-Single.jpg");
s.SetCustomIcon(customIcon);
s.SetIconAnchor(new VELatLong(lat, long));
map.AddShape(s);
}
I also have my map populate a circle around one of these pushpins. It is populated like so.
function getCircleNow(lat, long) {
var latin = lat;
var lonin = long;
var latlong = new VELatLong(latin, lonin);
centerPoint = (latlong);
//var center = map.GetCenter().toString();
//alert(center);
//Get initial circle points
var circlePoints = buildCircle(centerPoint.Latitude, centerPoint.Longitude, 50.74);
//Build circle
circle = new VEShape(VEShapeType.Polygon, circlePoints);
circle.HideIcon();
circle.SetLineWidth(2);
map.AddShape(circle);
//Build mask
circleMask = new VEShape(VEShapeType.Polygon, circlePoints);
circleMask.HideIcon();
circleMask.Hide();
circleMask.SetLineColor(new VEColor(0, 0, 0, 0.5));
circleMask.SetFillColor(new VEColor(0, 0, 0, 0.0));
circleMask.Primitives[0].symbol.stroke_dashstyle = "Dash";
map.AddShape(circleMask);
}
And here is the buildCircle() function it calls.
function buildCircle(latin, lonin, radius) {
var locs = new Array();
var lat1 = latin * Math.PI / 180.0;
var lon1 = lonin * Math.PI / 180.0;
var d = radius / 3956;
var x;
for (x = 0; x <= 360; x += 10) {
var tc = (x / 90) * Math.PI / 2;
var lat = Math.asin(Math.sin(lat1) * Math.cos(d) + Math.cos(lat1) * Math.sin(d) * Math.cos(tc));
lat = 180.0 * lat / Math.PI;
var lon;
if (Math.cos(lat1) == 0) {
lon = lonin; // endpoint a pole
}
else {
lon = ((lon1 - Math.asin(Math.sin(tc) * Math.sin(d) / Math.cos(lat1)) + Math.PI) % (2 * Math.PI)) - Math.PI;
}
lon = 180.0 * lon / Math.PI;
var loc = new VELatLong(lat, lon);
locs.push(loc);
}
return locs;
}
This is what my map looks like after I have added the pushpins and I have populated the circle on the map, with it centered around one of the locations and with a 50 mile radius.
WHAT I WANT TO BE ABLE TO DO
I want to be able to use either JavaScript or C# to detect what other pushpins, besides the one the circle is centered around, are within the radius of the center location. Or more simply, what other locations/pushpins are in the circle, and populate a list with values of each address. I can't think of any special methods that can do this so any help would be appreciated. This is Bing maps That I'm using.
This is fairly easy to do. Take the center point and radius of the circle do the following:
Loop through all pushpins and measure their distance from the center point using the Haversine formula: http://rbrundritt.wordpress.com/2008/10/14/calculate-distance-between-two-coordinates/
If the distance is less than or equal to the circles radius then the pushpin is inside the circle.
That's it. I also wrote an MSDN article on this for v6 of Bing maps a long time ago but it looks like it has been taken offline, along with all the documentation for v6.3 of Bing maps.
With all this said, its worth pointing out that Bing Maps V6.3 is really old and was last updated about 5 or 6 years ago. It's not recommended to do any new development on it but to instead make use of version 7 which is a lot more powerful, has more features, and is significantly smaller in terms of download size. I have a migration guide here: http://social.technet.microsoft.com/wiki/contents/articles/20958.migrating-bing-maps-v6-3-to-v7.aspx

What library for c# to use for the graphs of a Roundness-meter software?

I'm working on a metrology laboratory and i need to develop a software in c# for a roundness-meter equipment, I've already started and I've found a problem, I need the software to show real-time graphics from the measurement that is being made, for that I'll need to use a library like Mscharts or Zedgraph, that is really fast for refreshing the information and has support for round graphs like Polar or radar, especially polar charts.
The problem I've seen in most libraries is that they all lack support for round graphs and are relatively slow.
Does anyone has a sugestion of a lybrary I could use?
Thank you for your help.
PS:The Software should show graphics like these ones:
I would render them with GDI(+) (in winforms app).
Yes that is basic line drawing, but it will be powerful enough for the examples you gave. You need to refresh your highschool mathematics, but it will give you lots of control over the output and it will be fast.
Not sure if this will help or not. Xceed Charts in their advanced section talks about doing polar charts. Unfortunately they did not provide any images so you should talk to their sales people and see if you can get an eval copy to evaluate.
Consider using the roguewave IMSL Numerical .NET library
homepage of the IMSL numerical .NET library
Examples of graph, resembling what you have posted above
Especially the Polar plot seems to be what you need here.
I was surprised that ZedGraph doesn't support polar graphs out-of-the-box and there are very few examples online. Using this guildline, I created my own polar graph with ZedGraph in C#. I hope that WillKraemer has solved his problem already (4 years passed) and someone else finds my implementation useful.
First is the ZedGraphControl initialization:
myZg = new ZedGraphControl();
GraphPane myPane = myZg.GraphPane;
// Init lists
RadarPointList dseries1 = new RadarPointList();
RadarPointList dseries2 = new RadarPointList();
// Maximize available space in pane
myPane.Legend.Position = LegendPos.InsideTopLeft;
myPane.Title.IsVisible = false;
myPane.XAxis.IsVisible = false;
myPane.YAxis.IsVisible = false;
myPane.Border.IsVisible = false;
myPane.Chart.Border.IsVisible = false;
myPane.Margin.All = 0;
// Create concentric grid with 30 degrees spacing & add corresponding labels
for (double i = 0; i < 36; i+=3.0)
{
TextObj gridlbs = new TextObj((i * 10.0).ToString("0°"), (radius + 10.0) * Math.Cos((i * 10.0 * Math.PI) / 180.0), (radius + 10.0) * Math.Sin((i * 10.0 * Math.PI) / 180.0));
gridlbs.FontSpec.Border.IsVisible = false;
LineObj gridlns = new LineObj(0, 0, radius * Math.Cos((i * 10.0 * Math.PI) / 180.0), radius * Math.Sin((i * 10.0 * Math.PI) / 180.0));
myPane.GraphObjList.Add(gridlbs);
myPane.GraphObjList.Add(gridlns);
}
// Draw circular grid, 5 should look okay
for (double i = (radius / 5.0); i <= radius; i += (radius / 5.0))
{
EllipseObj gridcrl = new EllipseObj(-i, i, 2.0 * i, 2.0 * i);
gridcrl.ZOrder = ZOrder.E_BehindCurves;
myPane.GraphObjList.Add(gridcrl);
}
// Make sure the pane is big enough to fit the labels around the polar plot
myPane.XAxis.Scale.Min = -(radius + 20.0);
myPane.XAxis.Scale.Max = (radius + 20.0);
myPane.YAxis.Scale.Min = -(radius + 20.0);
myPane.YAxis.Scale.Max = (radius + 20.0);
_selectedRadius = radius;
// Keep X & Y axis in the correct ratio to avoid distorting polar circle
myZg_Resize((object)"Startup", EventArgs.Empty);
myZg.Resize += new EventHandler(myZg_Resize);
myZg.ZoomEvent += new ZedGraphControl.ZoomEventHandler(myZg_ZoomEvent2);
// Draw snailly curves (example)
for (int i = 0; i < 360; i++)
{
double r = (double)i/360.0 * radius;
PointPair pt = new PointPair(PointPair.Missing, r, null);
dseries1.Add(pt);
PointPair pt2 = new PointPair(PointPair.Missing, radius - r, null);
dseries2.Add(pt2);
}
// Curves are somple LineItem
FirstCurve = myPane.AddCurve("Snail", dseries1, Color.Blue, SymbolType.None);
SecondCurve = myPane.AddCurve("antiSnail", dseries2, Color.Red, SymbolType.None);
// Rotate the lists to aling with labels
dseries1.Rotation = 0;
dseries2.Rotation = 0;
I had to make sure that the graph is not distorted when the form/control resizes, so I added this in the Resize Event:
protected void myZg_Resize(object sender, EventArgs e)
{
GraphPane pane = myZg.GraphPane;
myZg.AxisChange();
bool IsXMin = ( pane.Rect.Width < pane.Rect.Height ) ? true : false;
if (IsXMin)
{
// Scale based on X (width)
pane.XAxis.Scale.Max = (radius + 20.0); pane.XAxis.Scale.Min = -(radius + 20.0);
double xPixPerUnit = (double)pane.Chart.Rect.Width / (pane.XAxis.Scale.Max - pane.XAxis.Scale.Min);
pane.YAxis.Scale.Max = (double)pane.Chart.Rect.Height / xPixPerUnit / 2.0;
pane.YAxis.Scale.Min = -pane.YAxis.Scale.Max;
myZg.AxisChange();
}
else
{
// Scale based on Y (height)
pane.YAxis.Scale.Max = (radius + 20.0); pane.YAxis.Scale.Min = -(radius + 20.0);
double yPixPerUnit = (double)pane.Chart.Rect.Height / (pane.YAxis.Scale.Max - pane.YAxis.Scale.Min);
pane.XAxis.Scale.Max = (double)pane.Chart.Rect.Width / yPixPerUnit / 2.0;
pane.XAxis.Scale.Min = -pane.XAxis.Scale.Max;
myZg.AxisChange();
}
}
Also, I decided to block the user from any zooming actions:
protected void myZg_ZoomEvent2(ZedGraphControl sender, ZoomState oldState, ZoomState newState)
{
myZg_Resize("zoomevent", EventArgs.Empty);
}
The output looks like the picture below:
Suggestions always welcome!

How to transform coordinates from WPF Image control to its Source and back?

How to accomplish this simple functionality (simple in Winforms) in WPF?
Image is displayed with Stretch = "Uniform". After clicking on the image the coordinates (with respect to the source image) are saved and the clicking point is shown (small rectangle) over the image.
In winforms I did it by finding zoom and offsets of the sourceimage within PictureBox and than easily converted the image coordinates.
Next thing is in winforms I used GetGraphics() function so the marks were not persistent and could have been redrawn from the saved ones on every resize, the rectangles added in WPF stay ot their locations.
What is the best way to do this? Or is it better to use a WinForm control within the WPF window?
Edit:
Scale computing - copied from Winforms and updated
private void ComputeScale ()
{
if (image1.Source == null)
{
this.imageScale = 1;
this.offsetX = 0;
this.offsetY = 0;
return;
}
//todo: picture has to be bigger than PictureBox
decimal imW = (decimal)image1.Source.Width;
decimal imH = (decimal)image1.Source.Height;
decimal pbW = (decimal)image1.ActualWidth;
decimal pbH = (decimal)image1.ActualHeight;
decimal scaleX = pbW / imW;
decimal scaleY = pbH / imH;
decimal scale = Math.Min (scaleX, scaleY);
decimal offsetX = Math.Round ((pbW - Math.Round (imW * scale)) / 2);
decimal offsetY = Math.Round ((pbH - Math.Round (imH * scale)) / 2);
this.imageScale = scale;
this.offsetX = (int)offsetX;
this.offsetY = (int)offsetY;
}
Painting Rectangles
Point p = e.GetPosition(image1);
decimal x = ((decimal)(p.X - offsetX)) / imageScale;
decimal y = ((decimal)(p.Y - offsetY)) / imageScale;
System.Drawing.Point ClickedSample = new System.Drawing.Point((int)Math.Round(x), (int)Math.Round(y));
Samples.Add(ClickedSample);
//PaintSampleMark
Rectangle r = new Rectangle();
r.StrokeThickness=1;
r.Stroke= Brushes.Blue;
r.Width = sampleRadius*2;
r.Height= sampleRadius*2;
r.Margin = new Thickness ((double)(offsetX - sampleRadius + x), (double)(offsetY - sampleRadius + y), 0, 0);
canvas1.Children.Add(r);

Categories