Xamarin.Forms.GoogleMaps Polyline points - xamarin

I'm using https://github.com/amay077/Xamarin.Forms.GoogleMaps and https://github.com/nuitsjp/Xamarin.Forms.GoogleMaps.Bindings (for binding polyline) libraries for map in my project. I have polyline with 99000 positions. This polyline don't put to the map. And I don't have an error. Has the maximum count positions polyline? Maybe there is a way around this?
ObservableCollection<Polyline> Polylines = new ObservableCollection<Polyline>();
Polyline polyline = new Polyline()
{
Tag = tag,
StrokeWidth = strokeWidth,
StrokeColor = strokeColor,
ZIndex = zIndex
};
foreach(var position in positions)
{
polyline.Positions.Add(position);
}
Polylines.Add(polyline);

Related

3D three.js Create the ground surface of a 3D building

Following my post last week three.js How to programatically produce a plane from dataset I come back to the community to solve a problem of definition of surface occupied on the ground by a 3D building.
The solution proposed in comments in this post works for this building but is not universal.
To make it universal I chose the following method: when the walls are built I create their clone in another group (see this previous post for walls creation)
// prepare the clones
var clones = new THREE.Group();
scene.add(clones);
var num=0;
// drawing the real walls
var wallGeometry = new THREE.PlaneGeometry(size,(hstair*batims[i][1]));
val = 0xFFFFFF;
opa = 0.5;
if(deltaX > deltaY){val = 0x000000; opa = 0.05;} // shaded wall
var wallMaterial = new THREE.MeshBasicMaterial({color:val,transparent:true, opacity:opa, side:THREE.DoubleSide});
var walls = new THREE.Mesh(wallGeometry, wallMaterial);
walls.position.set((startleft+endleft)/2,(hstair*batims[i][1])/2,(startop+endtop)/2);
walls.rotation.y = -rads;
scene.add(walls);
// add the pseudo-walls to scene
var cloneGeometry=new THREE.PlaneGeometry(long,3);
var cloneMaterial=new THREE.MeshBasicMaterial({color:0xff0000,transparent:true,opacity:0.5,side:THREE.DoubleSide});
var clone=new THREE.Mesh(pseudomursGeometry,pseudomursMaterial);
clone.position.set((startleft+endleft)/2,3,(startop+endtop)/2);
clone.rotation.y=-rads;
clones.add(clone);
num++;
The idea is now to rotate this pseudo-building so that the longest wall is vertical, which allows me to determine the exact floor area occupied with its boundingBox:
var angle=turn=0;
for(i=0; i<dists.length; i++) { // dists is the array of wall lengths
if(dists[i]==longs[0]){ // longs is the reordered lengths array
angle=angles[i][1]; // angle of the longest wall
}
}
// we can now rotate the whole group to put the longest wall vertical
if(angle>0){
turn = angle*-1+(Math.PI/2);
}
else {
turn = angle+(Math.PI/2);
}
clones.rotation.y=turn;
It works perfectly as long as the building has a right angle, whatever its shape: triangle, rectangle, bevel, right angle polygons,
var boundingBox = new THREE.Box3().setFromObject(clones);
var thisarea = boundingBox.getSize();
// area size gives the expected result
console.log('AREA SIZE = '+thisarea.x+' '+thisarea.y+' '+thisarea.z);
...but not when there are no more right angles, for example a trapezoid
The reason is that we rotate the group, and not the cloned walls. I can access and rotate each wall by
for(n=0;n<num;n++){
thisangle = clones.children[n].rotation.y;
clones.children[n].rotation.y = turn-thisangle;
}
But the result is wrong for the others pseudo-walls:
So the question is: how to turn each red pseudo-wall so that the longest one is vertical and the others remain correctly positioned in relation to it? In this way, any building with any shape can be reproduced in 3D with its internal equipment. Any idea on how to achieve this result?
A weird & ugly but well-working solution:
// 1. determines which is the longest side
for(i=0; i<dists.length; i++) {
if(dists[i]==longs[0]){
longest=i;
break; // avoid 2 values if rectangle
}
}
// 2. the group is rotated until the longest side has an angle in degrees
// close to 0 or 180
var letsturn = setInterval(function() {
clones.rotation.y += 0.01;
var group_rotation = THREE.Math.radToDeg(clones.rotation.y); // degrees
var stop = Math.round(angles[longest][0] - group_rotation);
// 3. stop when longest wall is vertical
if( (stop>=179 && stop<=181) || (stop>=-1 && stop<=1) ) {
clearInterval(letsturn);
createPlane() // we can now use boundingBox in reliability
}
}, 1);
et voilĂ .

Flip an SKPath using SkiaSharp

I'm using slightly modified resize code based on example I found. However, on resize the everything is flipped. I would like to either flip it back or prevent it from flipping in the first place.
Here is my resize code:
private static void ResizePath(SKPath buildingPath, IEnumerable<Room> rooms)
{
var info = new SKImageInfo(512, 600, SKImageInfo.PlatformColorType, SKAlphaType.Premul);
var drawSpaceRect = SKRect.Create(info.Size);
//I need to find the size of the path
var buildingPathRect = buildingPath.TightBounds;
//I want to find the largest rectangle that can fit on my canvas maintaining the path's aspect ratio
var sketchRect = drawSpaceRect.AspectFit(buildingPathRect.Size);
//Now I need to transform the path to draw within the sketchRect
//First translate original path to its own origin
var firstTranslateM = SKMatrix.MakeTranslation(-buildingPathRect.Left, -buildingPathRect.Top);
//Next handle scaling. Since I maintained aspect ratio, I should be able to use either
//width or height to figure out scaling factor
var scalingFactor = sketchRect.Width/buildingPathRect.Width;
var scaleM = SKMatrix.MakeScale(scalingFactor, scalingFactor);
//Next I need to handle translation so path is centered on canvas
var secondTranslateM = SKMatrix.MakeTranslation(sketchRect.Left, sketchRect.Top);
//Finally I need to handle transforming the path to rotate 180 degrees
var rotationMatrix = SKMatrix.MakeRotationDegrees(180, sketchRect.MidX, sketchRect.MidY);
//Now combine the translation, scaling, and rotation into a single matrix by matrix multiplication/concatentation
var transformM = SKMatrix.MakeIdentity();
SKMatrix.PostConcat(ref transformM, firstTranslateM);
SKMatrix.PostConcat(ref transformM, scaleM);
SKMatrix.PostConcat(ref transformM, secondTranslateM);
SKMatrix.PostConcat(ref transformM, rotationMatrix);
//Now apply the transform to the path
foreach (var r in rooms)
{
r.Path.Transform(transformM);
}
}
Here is an example of what I want (ignore the line numbers):
Flipped to:
Any help would be appreciated.
This transformation should do what you are looking for. The terminology would be flip horizontal or reflect horizontal.
var Ma = new SKMatrix {Values = new float[] {-1, 0, 0, 1, 0, 0, 0, 0, 0}};
pathToFlip.Transform(Ma);

Drawing lines between the Icosahedron vertices without wireframe material and with some line width using WEBGLRenderer

I'm new to threejs
I need to draw a sphere connected with triangles. I use Icosahedron to construct the sphere in the following way
var material = new THREE.MeshPhongMaterial({
emissive : 0xffffff,
transparent: true,
opacity : 0.5,
wireframe : true
});
var icogeo = new THREE.IcosahedronGeometry(80,2);
var mesh = new THREE.Mesh(icogeo, material);
scean.add(mesh);
But i need the width of the line to be more but line width won't show up in windows so i taught of looping through the vertices and draw a cylinder/tube between the vertices. (I can't draw lines because the LineBasicMaterial was not responding to Light.)
for(i=0;i<icogeo.faces.length;i++){
var face = icogeo.faces[i];
//get vertices from face and draw cylinder/tube between the three vertices
}
Can some one please help on drawing the tube/cylinder between two vector3 vertices?
**the problem i'm facing with wireframe was it was not smooth and i can't increase width of it in windows.
If you really want to create a cylinder between two points one way to do is to create it in a unit space and then transform it to your line. But that is very mathy.
An intuitive way to create it is to think about how would you do it in a unit space? A circle around the z axis (in x,y) and another one a bit down z.
Creating a circle in 2d is easy: for ( angle(0,360,360/numsteps) ) (x,y)=(sin(angle),cos(angle))*radius. (see for example Calculating the position of points in a circle).
Now the two butt ends of your cylinder are not in x,y! But If you have two vectors dx,dy you can just multiply your x,y with them and get a 3d position!
So how to get dx, dy? One way is http://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process
which reads way more scary than it is. You start with your forward direction, which is your line. forward = normalize(end-start). Then you just pick a direction "up". Usually (0,1,0). Unless forward is already close to up, then pick another one like (1,0,0). Take their cross product. This gives you "left". Then take the cross product between "left" and "forward" to get "right". Now "left" and "right" are you dx and dy!
That way you can make two circles at the two ends of your line. Add triangles in between and you have a cylinder!
Even though I do believe it is an overkill for what you are trying to achieve, here is code that draws a capsule (cylinder with spheres at the end) between two endpoints.
/**
* Returns a THREE.Object3D cylinder and spheres going from top to bottom positions
* #param radius - the radius of the capsule's cylinder
* #param top, bottom - THREE.Vector3, top and bottom positions of cone
* #param radiusSegments - tessellation around equator
* #param openTop, openBottom - whether the end is given a sphere; true means they are not
* #param material - THREE.Material
*/
function createCapsule (radius, top, bottom, radiusSegments, openTop, openBottom, material)
{
radiusSegments = (radiusSegments === undefined) ? 32 : radiusSegments;
openTop = (openTop === undefined) ? false : openTop;
openBottom = (openBottom === undefined) ? false : openBottom;
var capsule = new THREE.Object3D();
var cylinderAxis = new THREE.Vector3();
cylinderAxis.subVectors (top, bottom); // get cylinder height
var cylinderGeom = new THREE.CylinderGeometry (radius, radius, cylinderAxis.length(), radiusSegments, 1, true); // open-ended
var cylinderMesh = new THREE.Mesh (cylinderGeom, material);
// get cylinder center for translation
var center = new THREE.Vector3();
center.addVectors (top, bottom);
center.divideScalar (2.0);
// pass in the cylinder itself, its desired axis, and the place to move the center.
makeLengthAngleAxisTransform (cylinderMesh, cylinderAxis, center);
capsule.add (cylinderMesh);
if (! openTop || ! openBottom)
{
// instance geometry
var hemisphGeom = new THREE.SphereGeometry (radius, radiusSegments, radiusSegments/2, 0, 2*Math.PI, 0, Math.PI/2);
// make a cap instance of hemisphGeom around 'center', looking into some 'direction'
var makeHemiCapMesh = function (direction, center)
{
var cap = new THREE.Mesh (hemisphGeom, material);
makeLengthAngleAxisTransform (cap, direction, center);
return cap;
};
// ================================================================================
if (! openTop)
capsule.add (makeHemiCapMesh (cylinderAxis, top));
// reverse the axis so that the hemiCaps would look the other way
cylinderAxis.negate();
if (! openBottom)
capsule.add (makeHemiCapMesh (cylinderAxis, bottom));
}
return capsule;
}
// Transform object to align with given axis and then move to center
function makeLengthAngleAxisTransform (obj, align_axis, center)
{
obj.matrixAutoUpdate = false;
// From left to right using frames: translate, then rotate; TR.
// So translate is first.
obj.matrix.makeTranslation (center.x, center.y, center.z);
// take cross product of axis and up vector to get axis of rotation
var yAxis = new THREE.Vector3 (0, 1, 0);
// Needed later for dot product, just do it now;
var axis = new THREE.Vector3();
axis.copy (align_axis);
axis.normalize();
var rotationAxis = new THREE.Vector3();
rotationAxis.crossVectors (axis, yAxis);
if (rotationAxis.length() < 0.000001)
{
// Special case: if rotationAxis is just about zero, set to X axis,
// so that the angle can be given as 0 or PI. This works ONLY
// because we know one of the two axes is +Y.
rotationAxis.set (1, 0, 0);
}
rotationAxis.normalize();
// take dot product of axis and up vector to get cosine of angle of rotation
var theta = -Math.acos (axis.dot (yAxis));
// obj.matrix.makeRotationAxis (rotationAxis, theta);
var rotMatrix = new THREE.Matrix4();
rotMatrix.makeRotationAxis (rotationAxis, theta);
obj.matrix.multiply (rotMatrix);
}

Emgu CV draw rotated rectangle

I'm looking for few days a solution to draw rectangle on image frame. Basically I'm using CvInvoke.cvRectangle method to draw rectangle on image because I need antialiased rect.
But problem is when I need to rotate a given shape for given angle. I can't find any good solution.
I have tryed to draw rectangle on separate frame then rotate hole frame and apply this new image on top of my base frame. But in this solution there is a problem with antialiasing. It's not working.
I'm working on simple application that should allow draw few kinds of shape, resize them and rotation for given angle.
Any idea how to achive this?
The best way I found to draw a minimum enclosing rectangle on the contour is using the Polylines() function which uses vertices that are returned from MinAreaRect() function. There are surely other ways to do it as well. Here is the code walk down:
// Find contours
var contours = new Emgu.CV.Util.VectorOfVectorOfPoint();
Mat hierarchy = new Mat();
CvInvoke.FindContours(image, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);
// According to your metric, get an index of the contour you want to find the min enclosing rectangle for
int index = 2; // Say, 2nd index works for you.
var rectangle = CvInvoke.MinAreaRect(contours[index]);
Point[] vertices = Array.ConvertAll(rectangle.GetVertices(), Point.Round);
CvInvoke.Polylines(image, vertices, true, new MCvScalar(0, 0, 255), 5);
The result can be visualized in the image below, in red is the minimum enclosing rectangle.
I use C# and EMGU.CV(4.1), and I think this code will not be difficult to transfer to any platform.
Add function in the in your helper:
public static Mat DrawRect(Mat input, RotatedRect rect, MCvScalar color = default(MCvScalar),
int thickness = 1, LineType lineType = LineType.EightConnected, int shift = 0)
{
var v = rect.GetVertices();
var prevPoint = v[0];
var firstPoint = prevPoint;
var nextPoint = prevPoint;
var lastPoint = nextPoint;
for (var i = 1; i < v.Length; i++)
{
nextPoint = v[i];
CvInvoke.Line(input, Point.Round(prevPoint), Point.Round(nextPoint), color, thickness, lineType, shift);
prevPoint = nextPoint;
lastPoint = prevPoint;
}
CvInvoke.Line(input, Point.Round(lastPoint), Point.Round(firstPoint), color, thickness, lineType, shift);
return input;
}
This draws roteted rectangle by points. Here used rounding points by method Point.Round becose RotatedRect has points in float coordinates and CvInvoke.Line takes points as integer.
Use:
var mat = Mat.Zeros(200, 200, DepthType.Cv8U, 3);
mat.GetValueRange();
var rRect = new RotatedRect(new PointF(100, 100), new SizeF(100, 50), 30);
DrawRect(mat, rRect,new MCvScalar(255,0,0));
var brect = CvInvoke.BoundingRectangle(new VectorOfPointF(rRect.GetVertices()));
CvInvoke.Rectangle(mat, brect, new MCvScalar(0,255,0), 1, LineType.EightConnected, 0);
Result:
You should read the OpenCV documentation.
There is a RotatedRectangle class that you can use for your task. You can specify the angle by which the rectangle will be rotated.
Here is a sample code (taken from the docs) for drawing a rotated rectangle:
Mat image(200, 200, CV_8UC3, Scalar(0));
RotatedRect rRect = RotatedRect(Point2f(100,100), Size2f(100,50), 30);
Point2f vertices[4];
rRect.points(vertices);
for (int i = 0; i < 4; i++)
line(image, vertices[i], vertices[(i+1)%4], Scalar(0,255,0));
Rect brect = rRect.boundingRect();
rectangle(image, brect, Scalar(255,0,0));
imshow("rectangles", image);
waitKey(0);
Here is the result:

How to change only width of path(rect, circle) while mouse drag using paper.js

I have stucked at resizing only width of an item in the canvas using paper.js
I have done in following ways to resize , but it results in resizing both left and right sides from the center of rectangle/circle.
function onMouseDrag(event){
(selectedItem.bounds.contains(event.point)) ?
selectedItem.scale(0.9871668311944719,1) : selectedItem.scale(1.013, 1);
}
above code resizes in both x-directions.
Help me to resize width only in one direction.
thanks,
suribabu.
You can center the scale operation at any point by using the form:
scale(hor, ver, point)
So in your case, if you want to scale from the left-center of your selected item, you could use:
function onMouseDrag(event){
(selectedItem.bounds.contains(event.point)) ?
selectedItem.scale(0.9871668311944719, 1, selectedItem.bounds.left) : selectedItem.scale(1.013, 1, selectedItem.bounds.left);
}
I am not sure what you mean with scale only the width. If you want to have thicker path than changing the strokeWidth instead might do what you want.
If you are wondering why the scaled path expands in both directions on the x-axis than you might check the location of the paths local center. If some nodes of the path have negative coordinates relative to this local center, scaling them with a positive value decreases their coordinates even more.
Perhaps you should normalize all the vertices, means move them directly so that the smallest x and y value of all vertices is 0.
Greetings and good luck
Try this:
function onMouseDown(e) {
var cx = e.point.x;
var cy = e.point.y;
var rectangle = new Rectangle(e.point, new Size(1,1));
path = new Path.Ellipse(rectangle);
path.strokeColor = 'red';
}
function onMouseDrag(e) {
path.remove();
var x = Math.min(e.point.x, cx),
y = Math.min(e.point.y, cy),
w = Math.abs(e.point.x -cx),
h = Math.abs(e.point.y -cy);
var rectangle = new Rectangle(x,y,w,h);
path = new Path.Ellipse(rectangle);
path.strokeColor = 'red'
}

Resources