is there possible for uploaded rotated image and rendered with some wrong resolution or extents using static image source in open layer 6 - gis

I am using open layers 6 lib for map rendering and events.
my application needed same like this example http://viglino.github.io/ol-ext/examples/layer/map.geoimage.html i.e. Example have ol.source.GeoImage..
I have tried
i am using affine transformation above lib and returns scaling, rotation and center of image transformation..
its giving the values
scaling : 327.805670381418,327.805670381418
rotation : -0.1310210334156003
transformation : 7179251.8557908312,6022627.228704552
now I have calculated extent and image projection & image static source is in ol 6
and
rotated image projection in this link (https://codesandbox.io/s/reprojection-image-z0uit)
// center of image from affine
const translationX = transformation.getTranslation()[0];
const translationY = transformation.getTranslation()[1];
extent = transformExtent([translationX - (xScale * this.imageData.width / 2),
translationY - (yScale * this.imageData.height / 2),
translationX + (xScale * this.imageData.width / 2),
translationY + (yScale * this.imageData.height / 2)],
get('EPSG:3857'), get('EPSG:4326'));
const imageProjection = this.returnRotateProjection(
viewProjection,
fromLonLat([transformation.getTranslation()[0], transformation.getTranslation()[1]], 'EPSG:4326'),
transformation.getRotation(),
extent
);
const imgSource = new Static({
url: this.imgURL,
projection: imageProjection,
imageExtent: extent,
imageSize: [this.imageData.width, this.imageData.height],
imageLoadFunction : (image) => {
image.getImage().src = this.imgURL;
if (image.resolution === undefined) {
image.resolution = (image.extent[3] - image.extent[1]) / image.image_.height;
}
image.state = 2; // ImageState.LOADED;
image.unlistenImage_();
image.changed();
}
});
here issue is image resolution is very bad like image displaying like curve shape
is there any possibles for finding 4 corners(bounding box using center of image and rotated image center point and width, height, scalling)
suggest or help on this.. thanks in advance.. and save my days..
gis

Related

Gesture Zoom and Pan in a VCL Windows application

I'm trying to zoom and pan an image (TImage) with an object (TShape) on it in a VCL Windows application running on an all-in-one pc with touch display.
I put the image in a panel (TPanel) so when I zoom it, it remains always inside the panel.
Then I put a shape (TShape) on the image.
What I would like to get is to zoom and pan the image and the shape should zoom and move with the image.
I started from the Embarcadero sample "Mobile Snippets - InteractiveGestures - ImageZoom" and with the following code I managed to do image zoom and pan with two fingers:
void __fastcall TForm1::Image1Gesture(TObject *Sender, const TGestureEventInfo &EventInfo, bool &Handled) {
TPointF LImageCenter;
double expance;
TPointF movement;
try {
if (EventInfo.GestureID == static_cast<short>(Vcl::Controls::igiZoom)) {
if (!EventInfo.Flags.Contains(TInteractiveGestureFlag::gfBegin) &&
!EventInfo.Flags.Contains(TInteractiveGestureFlag::gfEnd)) {
// zoom the image
TImage * LImage = dynamic_cast<TImage*>(Image1);
LImageCenter.x = LImage->Left + (LImage->Width / 2);
LImageCenter.y = LImage->Top + (LImage->Height / 2);
expance = EventInfo.Distance - FLastDistance;
if (((LImage->Width + (expance * AR))> MIN_DIM) &&
((LImage->Height + (expance))> MIN_DIM)) {
LImage->Width = (int)(LImage->Width + (expance * AR));
LImage->Height = (int)(LImage->Width / AR );
}
LImage->Left = LImageCenter.X - LImage->Width / 2;
LImage->Top = LImageCenter.Y - LImage->Height / 2;
}
FLastDistance = EventInfo.Distance;
}
else if (EventInfo.GestureID == static_cast<short>(Vcl::Controls::igiPan)) {
if (!EventInfo.Flags.Contains(TInteractiveGestureFlag::gfBegin) &&
!EventInfo.Flags.Contains(TInteractiveGestureFlag::gfEnd)) {
// move the image
TImage * LImage = dynamic_cast<TImage*>(Image1);
movement.x = EventInfo.Location.X - FLastLocation.x;
movement.y = EventInfo.Location.Y - FLastLocation.y;
LImage->Left += movement.x;
LImage->Top += movement.y;
}
FLastLocation.x = EventInfo.Location.X;
FLastLocation.y = EventInfo.Location.Y;
}
} catch (Exception &e) {
ShowMessage(e.Message);
} }
AR is the image aspect ratio and MIN_DIM is a define to set the minimum image dimensions for the zoom.
The pan movement is not so great...
I don't know how to make the shape to behave in accordance with the image zoom and move.
The shape parent is the panel under the image, not the image, so the shape is completely independent from the image changes.
I can't set the image as the shape parent.
Whatever suggestion to get the desired result will be appreciated.
The pan movement is not smooth because EventInfo.Location.X and EventInfo.Location.Y do not vary in a smooth way.
If I start the pan movement and I stop, even if fingers are still EventInfo.Location continues to change.
Is there a way to avoid this behavior?

`Autodesk.Viewing.ScreenShot.getScreenShotWithBounds` uses viewer's default camera dimensions instead of bounds

Following this advice I am trying to replace our usage of viewer::getScreenshot with Autodesk.Viewing.ScreenShot.getScreenShotWithBounds which calls Autodesk.Viewing.ScreenShot.getScreenShot to support larger screenshots. However, the bounds are ignored. The behaviour seems to be that it makes a screenshot of the viewer's default camera or corresponding to its dimensions. Then it stretches the image to fit the given width and height. I expected the function to return a screenshot of the elements inside the given bounding box.
Is the function getScreenShotWithBounds supposed to do something different from what I am assuming?
Example code (LMV 7.40.0):
const bbounds: THREE.Bbox3; // calculated for some elements I want to screenshot
Autodesk.Viewing.ScreenShot.getScreenShotWithBounds(NOP_VIEWER, Math.ceil(bbounds.size().x * 4), Math.ceil(bbounds.size().y* 4), (blob) => window.open(blob), {bounds: bbounds, margin: 0});
Manual screenshot of the viewer
Returned image of getScreenShotWithBounds
Update:
I misunderstood the function. Autodesk.Viewing.ScreenShot.getScreenShotWithBounds just fits the bounds into the camera view. The bounds are not used for any cropping. See my more detailed answer.
The given width and height of Autodesk.Viewing.ScreenShot.getScreenShotWithBounds must be of the same aspect ratio as the viewer (see Adam Nagy's answer), i.e.:
getScreenShotWithBounds(NOP_VIEWER, NOP_VIEWER.getDimensions().width * 4, NOP_VIEWER.getDimensions().height * 4, options);
getScreenShotWithBounds just fits the bounds into the camera view (internally it calls viewer.navigation.fitBounds(true, bounds, false);). The bounds are not used for any kind of cropping / pixel calculation or otherwise.
To get a specific aspect ratio by cropping, you have to provide getCropBounds in the options parameter.
For example to force a aspect ratio by cropping:
getCropBounds: function(viewer: Autodesk.Viewing.Viewer3D, camera: Autodesk.Viewing.UnifiedCamera, bounds: THREE.Box3): THREE.Box2 {
// calculate the crop bounds in pixels
// if the crop bounds are larger the screenshot's width / height is taken
const aspectRatio = new THREE.Vector2(4, 3);
const viewerBoundsWidthRatio = width / aspectRatio.x;
const viewerBoundsHeightRatio = height / aspectRatio.y;
const cropToHeight = viewerBoundsWidthRatio > viewerBoundsHeightRatio;
const smallerScaleRatio = cropToHeight ? viewerBoundsHeightRatio : viewerBoundsWidthRatio;
const cropBoundsSize = aspectRatio.clone().multiplyScalar(smallerScaleRatio);
const cropBounds = new THREE.Box2(new THREE.Vector2(0, 0), new THREE.Vector2(cropBoundsSize.x, cropBoundsSize.y));
const offset = cropToHeight ? new THREE.Vector2((width - cropBoundsSize.x) / 2, 0) : new THREE.Vector2(0, (height - cropBoundsSize.y) / 2);
cropBounds.min.add(offset);
cropBounds.max.add(offset);
return cropBounds;
}
The squashed image you are getting is suggesting it, but it's not clear from the comments in the source code, that you should keep the ratio of the Viewer for the width and height input parameters. So you should only scale them depending on your needs: getScreenShotWithBounds(NOP_VIEWER, viewer_width * x, viewer_height * x, etc
Then the bounds in the options should take care of the cropping.

Scaling points to match background. Actionscript 3

Using some code I found online has helped me create a zoom function for a program I am attempting to make. It is to make a map that allows a user to mark points. Currently the code scales in on the map image alone but I cant get the point icons to realign to where they originally where. I cant workout the maths of it.
Code to zoom in and out
if (mev.shiftKey) {
image.scaleX = Math.max(scaleFactor*image.scaleX, minScale);
image.scaleY = Math.max(scaleFactor*image.scaleY, minScale);
}
if (mev.ctrlKey) {
image.scaleX = Math.min(1/scaleFactor*image.scaleX, maxScale);
image.scaleY = Math.min(1/scaleFactor*image.scaleY, maxScale);
mat = image.transform.matrix.clone();
MatrixTransformer.matchInternalPointWithExternal(mat,internalCenter,externalCenter);
image.transform.matrix=mat;
This allows the image to scale up with the following factors
public var scaleFactor:Number = 0.8;
public var minScale:Number = 0.25;
public var maxScale:Number = 2.0;
The problem occurs when I try to move the pointer icons that are overlaid on this image. They are not to grow or shrink at the moment but they I cant get the maths to get them to move the correct number of pixels away from the mouse location so that they are still in line. Currently I am using the following formulas
//decrease zoom
stage.getChildAt(i).x = stage.getChildAt(i).x * scaleFactor;
//increase zoom
stage.getChildAt(i2).x = stage.getChildAt(i2).x / scaleFactor;
Any thoughts ? Code I am using came from
http://www.flashandmath.com/howtos/zoom/
Quite a few elements missing from the question like the moving map underneath. Anyway now that it's sorted out ...
If you are not a math genius and can't tackle 2 math formulas at the same time then don't and tackle them one by one then combine them. Once again don't use the x,y property of point for calculation but create specific property (like in a custom class for example). I will name them here origin for convenience.
Given a point with origin property of x:100, y:200, its position on the map is (assuming map is top left coordinate, if not adapt accordingly):
point.x = map.x + point.origin.x;
point.y = map.y + point.origin.y;
the positioning is solved now you need to solve for scale which is easy:
point.x = point.origin.x * scaleFactor;
point.y = point.origin.y * scaleFactor;
Both systems are solved now you can combine the two:
point.x = map.x + (point.origin.x * scaleFactor);
point.y = map.y + (point.origin.y * scaleFactor);

Another AR SDK like GART SDK on Windows Phone

I'm developing a Windows Phone 8 application with GART SDK.
But I don't like because it overlaps the places' names and all has the same font size. I was using ARToolkit for iPhone and it changes the font size it the places are near or far, and it doesn't overlap them.
Do you know another SDK like GART for Windows Phone 8?
I encountered the same problem a while ago, and I solved it by modifying OnAttitudeChanged method of WorldView class.
This is the code I have inside the else block of that method:
else
{
// In range so show
wvItem.Visibility = Visibility.Visible;
// Create a CompositeTransform to position and scale the WorldViewItem
CompositeTransform ct = new CompositeTransform();
// Offset by half of the WorldViewItems size to center it on the point
ct.TranslateX = projected.X - (wvItem.ActualWidth / 2);
ct.TranslateY = projected.Y - (wvItem.ActualHeight / 2);
// Scale should be 100% at near clipping plane and 10% at far clipping plane
//double scale = (double)(MathHelper.Lerp(0.1f, 1.0f, (FarClippingPlane - Math.Abs(arItem.WorldLocation.Z)) / FarClippingPlane));
// Added to use distance
double scale = (double)(MathHelper.Lerp(0.1f, 1.0f, (FarClippingPlane - (float)Math.Round(arItem.GeoLocation.GetDistanceTo(this.Location))) / FarClippingPlane));
// This makes the items that are far to appear higher on screen. Values are that best fit my project, so, it should be calibrated.
ct.TranslateY = ct.TranslateY - (int)((1-scale) * 63);
ct.ScaleX = scale;
ct.ScaleY = scale;
// Set the transform, which moves the item
wvItem.RenderTransform = ct;
// Set the items z-index so that the closest item is always rendered on top
Canvas.SetZIndex(wvItem, (int)(scale * 255));
}

Scaling tile grid

I'm working on my own tile bliting engine, this one is using hexagonal tiles - but I think it doesn't differ much from regular tiles.
I have huge x,y array of tiles and they have their x,y coordinates for rendering on canvas, I iterate only the ones that should be visible on canvas in current camera position.
So I'm stuck with scaling and cant resolve this on my own.
Here is my code for drawing tiles on canvas:
public function draw():Void{
clearCanvas(); //Clear canvas (bitmapData)
var _m:Matrix;
iterateTiles(function(_tile:HexTile):Void{ // loop every tile that is visible on screen
_m = new Matrix();
_m.translate(_tile.x + cameraPoint.x,_tile.y + cameraPoint.y);//Get pre calculated tile x,y and add camera x,y
_m.scale(matrixScale, matrixScale);
drawToCanvas(_tile,_m);//Send to draw tile on canvas using Matrix
},true);
}
This works nice and fast but only problem is it scales tiles from left top corner (like regular scale would work)
Before scale
After scale
My question is how to transform tiles to always scale from center. So if tile 10:10 is in center of screen before scaling, then it should
stay there after scaling.
Sorry, I misunderstood the question, but I think I've got it now:
// Scale the distance from the original point to the center of the canvas
var xDistance:Number = ((_tile.x + cameraPoint.x) - xCenter) * matrixScale;
var yDistance:Number = ((_tile.y + cameraPoint.y) - yCenter) * matrixScale;
// Add the distances to the center of the canvas. This is where you want the tile
// to appear.
var x:Number = xCenter + xDistance;
var y:Number = yCenter + yDistance;
// Because the coordinate is going to be scaled, you need to increase it first.
x = (1 / matrixScale) * x;
y = (1 / matrixScale) * y;
_m.translate(x, y);
I have not tested this, I've just drawn it out on graph paper. Let me know if it works.