Monodroid DensityDpi to Int - c#

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:

Related

Text on image looks blurry after scaling image down using Aspose.Words.Saving.ImageSaveOptions

We have a problem in our system. We extract images from doc file and perform scaling up and down if the size of the extracted image is not as we want. Image looks good after scaling but the text that lies inside the image looks a little bit blurry or not in the same quality (sharpness) as in the image before scaling. Any ideas that can help to improve the text sharpness will be most appreciated.Thank you wonderful people!
Our scaling function looks like this:
const float highScalingFactor = 0.58F; // default scaling of large images - based on experience
const float lowScalingFactor = 0.44F; // default scaling of small images - based on experience
const int maxWidth = 1100;
const int maxHeight = 2500;
float formulaScale = 0.9F;
//calling scaling function here
var lImgStream = ScaleImage(shape, lowScalingFactor * formulaScale, maxWidth, maxHeight, "png");
private static MemoryStream ScaleImage(Shape shape, float scale, int maxWidth, int maxHeight, string extension)
{
var resolution = 300F;
ShapeRenderer r = new ShapeRenderer(shape);
var rect = r.GetBoundsInPixels(scale, resolution);
if (rect.Width > maxWidth)
{
scale = 1 - (rect.Width * scale - maxWidth) / rect.Width;
}
if (rect.Height > maxHeight)
{
scale = 1 - (rect.Height * scale - maxHeight) / rect.Height;
}
ImageSaveOptions imageOptions = new ImageSaveOptions(FileFormatUtil.ExtensionToSaveFormat(extension))
{
SaveFormat = SaveFormat.Png,
Scale = scale,
Resolution = resolution,
UseHighQualityRendering = true
};
// sharpen formulas
if (shape.ImageData.ImageType == ImageType.Wmf)
imageOptions.ImageContrast = 0.55f;
var output = new MemoryStream();
r.Save(output, imageOptions);
output.Seek(0, SeekOrigin.Begin);
return output;
}
We tried the above scaling algorithm with successful output in terms of image sharpness except text on the image. The text looks blurry.
Try using SaveOptions.UseAntiAliasing to improve the quality of a rendered image.

Map Is Zooming (Zoom In/Out) Automatically when i changed Latitude and Longitude To View different location (Please Go through the below Description)

I am using Gmap nuget package to load the map in my project. i have loaded the map, after that i want to draw the circle around the selected Lat Long.
i drawn the circles and those circles are in correct distance also (i have verified).
The issue is : as i am changing latitude and longitude to to view another location map, the map is zooming automatically.
As latitude number is increases the map is zooming in and as latitude number decreases zooming out is taking place.
I am not using any zoom in/out function only changing latitude is acting like this
Eg : Bangalore Latitude:13.095170176351234 and longitude : 77.59453327374854
For above lat long assume its in Default Zoom.
Now I am going Switch the lat long to Dhelhi Location to View Dhelhi Map
Latitude : 28.55635085552201 and Longitude : 77.09994706900083
while loading Dhelhi Map we can see the Map Zoom In taking place**
absorve Circle Width,Height and Map while loading To Dhelhi location we can see the Zoom In because latitude number is bigger than bangalore Latitude number
private static double localLatitude = 13.095170176351234;
private static double localLongitude = 77.59453327374854;
private void mapView_Loaded(object sender, RoutedEventArgs e)
{
GMaps.Instance.Mode = AccessMode.ServerAndCache;
mapView.MapProvider=GMap.NET.MapProviders.OpenStreetMapProvider.Instance;
mapView.MinZoom = 12;
mapView.MaxZoom = 17;
mapView.Zoom = 14;
mapView.MouseWheelZoomType = MouseWheelZoomType.ViewCenter;
mapView.CanDragMap = false;
mapView.DragButton = MouseButton.Left;
mapView.Position = new PointLatLng(localLatitude, localLongitude);
mapView.IsHitTestVisible = true;
mapView.ShowCenter = true;
CreateCircle(localLatitude, localLongitude, 30, 0.4, 4);
CreateCircle(localLatitude, localLongitude, 500, 0.4);
CreateCircle(localLatitude, localLongitude, 1000, 0.4);
CreateCircle(localLatitude, localLongitude, 1500, 0.4);
CreateCircle(localLatitude, localLongitude, 2000, 0.4);
CreateCircle(localLatitude, localLongitude, 2150, 0.4);
}
private void CreateCircle(double rLat, double rLon, double rangeRadius, double opacity, double ColorIndex = 1)
{
//double radius = 2150; // in mtr //todo get from erc
double radius = rangeRadius;
//int ColorIndex = 1;
PointLatLng point = new PointLatLng(rLat, rLon);
//GMapMarker markers = new GMapMarker(point);
int segments = 1080;
List<PointLatLng> pointillist = new List<PointLatLng>();
for (int i = 0; i < segments; i++)
{
pointillist.Add(FindPointAtDistanceFrom(point, i * (Math.PI / 180), radius / 1000));
}
var rangeCircles = new GMapPolygon(pointillist)
{
Tag = "RangeCircle"
};
mapView.RegenerateShape(rangeCircles);
switch (ColorIndex)
{
case 1:
((Path)rangeCircles.Shape).Fill = Brushes.LightGray;
break;
case 2:
((Path)rangeCircles.Shape).Fill = Brushes.Orange;
break;
case 3:
((Path)rangeCircles.Shape).Fill = Brushes.Aqua;
break;
case 4:
((Path)rangeCircles.Shape).Fill = Brushes.Red;
break;
default:
System.Windows.MessageBox.Show("No search zone found!");
break;
}
((Path)rangeCircles.Shape).Stroke = Brushes.Black;
((Path)rangeCircles.Shape).StrokeThickness = 1;
((Path)rangeCircles.Shape).Opacity = opacity;
mapView.Markers.Add(rangeCircles);
}
private static GMap.NET.PointLatLng FindPointAtDistanceFrom(GMap.NET.PointLatLng startPoint, double initialBearingRadians, double distanceKilometres)
{
const double radiusEarthKilometres = 6371.01;
var distRatio = distanceKilometres / radiusEarthKilometres;
var distRatioSine = Math.Sin(distRatio);
var distRatioCosine = Math.Cos(distRatio);
var startLatRad = DegreesToRadians(startPoint.Lat);
var startLonRad = DegreesToRadians(startPoint.Lng);
var startLatCos = Math.Cos(startLatRad);
var startLatSin = Math.Sin(startLatRad);
var endLatRads = Math.Asin((startLatSin * distRatioCosine) + (startLatCos * distRatioSine * Math.Cos(initialBearingRadians)));
var endLonRads = startLonRad + Math.Atan2(Math.Sin(initialBearingRadians) * distRatioSine * startLatCos, distRatioCosine - startLatSin * Math.Sin(endLatRads));
return new GMap.NET.PointLatLng(RadiansToDegrees(endLatRads), RadiansToDegrees(endLonRads));
}
private static double DegreesToRadians(double degrees)
{
const double degToRadFactor = Math.PI / 180;
return degrees * degToRadFactor;
}
private static double RadiansToDegrees(double radians)
{
const double radToDegFactor = 180 / Math.PI;
return radians * radToDegFactor;
}
It might be the mapView.ShowCenter = true; property that is causing the automatic zoom adjustments. Requiring the center point to always be visible probably causes your map to zoom to try to show both the new marker and the center in the same visible map window.

Zoom an object in viewport to fill the screen

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?

How to enable zoom in and zoom out on a contentpage in xamarin forms?

How can I enable zoom on a contentpage in xamarin forms? Is it possible to enable it on the entire contentpage? Or is it only possible to zoom in on images?
You can use the pinch gesture inside a ContentPage, here is the official page:
https://developer.xamarin.com/guides/xamarin-forms/user-interface/gestures/pinch/
and for the entire project sample:
https://github.com/xamarin/xamarin-forms-samples/tree/master/WorkingWithGestures/PinchGesture
Here is an example of what you can achieve:
Xamarin.Forms Pinch Example
Try this Class , this solution do not scroll when you zoom .
Source found here:
Source Code
public class PinchToZoomContainer : ContentView {
double currentScale = 1;
double startScale = 1;
double xOffset = 0;
double yOffset = 0;
public PinchToZoomContainer ()
{
var pinchGesture = new PinchGestureRecognizer ();
pinchGesture.PinchUpdated += OnPinchUpdated;
GestureRecognizers.Add (pinchGesture);
}
void OnPinchUpdated (object sender, PinchGestureUpdatedEventArgs e)
{
if (e.Status == GestureStatus.Started) {
// Store the current scale factor applied to the wrapped user interface element,
// and zero the components for the center point of the translate transform.
startScale = Content.Scale;
Content.AnchorX = 0;
Content.AnchorY = 0;
}
if (e.Status == GestureStatus.Running) {
// Calculate the scale factor to be applied.
currentScale += (e.Scale - 1) * startScale;
currentScale = Math.Max (1, currentScale);
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the X pixel coordinate.
double renderedX = Content.X + xOffset;
double deltaX = renderedX / Width;
double deltaWidth = Width / (Content.Width * startScale);
double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the Y pixel coordinate.
double renderedY = Content.Y + yOffset;
double deltaY = renderedY / Height;
double deltaHeight = Height / (Content.Height * startScale);
double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
// Calculate the transformed element pixel coordinates.
double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);
// Apply translation based on the change in origin.
Content.TranslationX = targetX.Clamp (-Content.Width * (currentScale - 1), 0);
Content.TranslationY = targetY.Clamp (-Content.Height * (currentScale - 1), 0);
// Apply scale factor
Content.Scale = currentScale;
}
if (e.Status == GestureStatus.Completed) {
// Store the translation delta's of the wrapped user interface element.
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
}
}
}
Helper DoubleExtensions
public static class DoubleExtensions
{
public static double Clamp (this double self, double min, double max)
{
return Math.Min (max, Math.Max (self, min));
}
}
You can try using the Scale Api on the Content page. This seemed to work for me on a small test app.
public App ()
{
// The root page of your application
var scaleUp = new Button {
Text = "Scale Up"
};
scaleUp.Clicked += (sender, e) => {
this.MainPage.Scale += 1;
};
var scaleDown = new Button {
Text = "Scale Down"
};
scaleDown.Clicked += (object sender, EventArgs e) => {
this.MainPage.Scale -= 1;
};
MainPage = new ContentPage {
Content = new StackLayout {
VerticalOptions = LayoutOptions.Center,
Children = {
scaleUp,
scaleDown
}
}
};
}
Trying to use this in conjunction with other controls that take the Pan/scroll gesture seems to fail. ScrollView and ListView for example grab the Pinch gesture even though they themselves don't Pinch but they do scroll/pan. So it seems like Pinch inherits/uses that gesture so it is grabbed by the wrapped control. This seems to make Pinch a very niche feature that can only work on very static views of Label and Image for example, but nothing more complex.
You can use gestures.
Sample here : http://arteksoftware.com/gesture-recognizers-with-xamarin-forms/

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