Consider the n-cube (defined here) with n>3. Suppose that it centered at the origin of the Cartesian plane and each edge has length 10.
I would like to write a piece of code in Matlab that allows me to randomly draw one point (with n coordinates) from this hypercube. Is there a way to do it without pre-defining a n-dimensional grid? In my particular application n=11.
To draw 1 point from the volume of an n-dimensional hypercube with side s, with all points having equal probability, you call
s = 10;
point = (rand(1,n)-0.5)*s;
Replace the 1 with a larger number if you want to draw many points at once.
Extending Jonas' answer, if you want to specify a center, do this:
center = [1.0 -1.0 2.0 -2.0 ...];
s = 10;
point = (rand(1,n)-0.5)*s + center;
Related
My binary image has rectangular rotated objects of known size on it. I'd like to get the object inclination using axis-aligned bounding box that MATLAB's regionprops returns. What are my suggestions:
Let bounding box width be W, side of rectangle be C and inclination alpha
Then
Using Weierstrass substitution
After some simplification:
Solving the equation for tan(alpha/2) with
For any nonzero inclination discriminant is positive.
Logic seems to be OK, so as math. Could you please point where I make a mistake, or what is a better way to get inclination?
Here is corresponding MATLAB code:
img = false(25,25);
img(5:16,5:16) = true;
rot_img = imrotate(img, 30, 'crop');
props = regionprops(bwlabel(rot_img),'BoundingBox');
bbox = cat(1,props.BoundingBox);
w = bbox(3);
h = 12;
a = -1*(1+w/h); b = 2; c = 1 - w/h;
D = b^2 - 4*a*c;
alpha = 2*atand((-b + sqrt(D))/(2*a));
%alpha = 25.5288
EDIT Thank you for trigonometry hints. They significantly simplify the calculations, but they give wrong answer. As I now understand, the question is asked in wrong way. The thing I really need is finding inclination of short lines (10-50 pixels) with high accuracy (+/- 0.5 deg), the lines' position is out of interest.
The approach used in the question and answers show better accuracy for long lines, for c = 100 error is less than 0.1 degree. That means we're into rasterization error here, and need subpixel accuracy. At the moment I have only one algorithm that solves the problem - Radon transform, but I hope you can recommend something else.
p = bwperim(rot_img);
theta=0:0.1:179.9;
[R,xp] = radon(p,theta); %Radon transform of contours
a=imregionalmax(R,true(3,3)); %Regional maxima of the transform
[r,c]=find(a); idx=sub2ind(size(a),r,c); maxvals=R(idx);
[val,midx]=sort(maxvals,'descend'); %Choose 4 highest maxima
mean(rem(theta(c(midx(1:4))),90)) %And average corresponding angles
%29.85
If rectangle is square:
w/c=sin(a)+cos(a)
(w/c)^2=1+sin(2a)
sin(2a)=(w/c)^2-1
a=0.5*arcsin((w/c)^2-1)
May be use regionprops function with 'Orientation' option...
I have this 3D image generated from the simple code below.
% Input Image size
imageSizeY = 200;
imageSizeX = 120;
imageSizeZ = 100;
%# create coordinates
[rowsInImage, columnsInImage, pagesInImage] = meshgrid(1:imageSizeY, 1:imageSizeX, 1:imageSizeZ);
%# get coordinate array of vertices
vertexCoords = [rowsInImage(:), columnsInImage(:), pagesInImage(:)];
centerY = imageSizeY/2;
centerX = imageSizeX/2;
centerZ = imageSizeZ/2;
radius = 28;
%# calculate distance from center of the cube
sphereVoxels = (rowsInImage - centerY).^2 + (columnsInImage - centerX).^2 + (pagesInImage - centerZ).^2 <= radius.^2;
%# Now, display it using an isosurface and a patch
fv = isosurface(sphereVoxels,0);
patch(fv,'FaceColor',[0 0 .7],'EdgeColor',[0 0 1]); title('Binary volume of a sphere');
view(45,45);
axis equal;
grid on;
xlabel('x-axis [pixels]'); ylabel('y-axis [pixels]'); zlabel('z-axis [pixels]')
I have tried plotting the image with isosurface and some other volume visualization tools, but there remains quite a few surprises for me from the plots.
The code has been written to conform to the image coordinate system (eg. see: vertexCoords) which is a left-handed coordinate system I presume. Nonetheless, the image is displayed in the Cartesian (right-handed) coordinate system. I have tried to see this displayed as the figure below, but that’s simply not happening.
I am wondering if the visualization functions have been written to display the image the way they do.
Image coordinate system:
Going forward, there are other aspects of the code I am to write for example if I have an input image sphereVoxels as in above, in addition to visualizing it, I would want to find north, south east, west, top and bottom locations in the image, as well as number and count the coordinates of the vertices, plus more.
I foresee this would likely become confusing for me if I don’t stick to one coordinate system, and considering that the visualization tools predominantly use the right-hand coordinate system, I would want to stick with that from the onset. However, I really do not know how to go about this.
Right-hand coordinate system:
Any suggestions to get through this?
When you call meshgrid, the dimensions x and y axes are switched (contrary to ndgrid). For example, in your case, it means that rowsInImage is a [120x100x200] = [x,y,z] array and not a [100x120x200] = [y,x,z] array even if meshgrid was called with arguments in the y,x,z order. I would change those two lines to be in the classical x,y,z order :
[columnsInImage, rowsInImage, pagesInImage] = meshgrid(1:imageSizeX, 1:imageSizeY, 1:imageSizeZ);
vertexCoords = [columnsInImage(:), rowsInImage(:), pagesInImage(:)];
I cannot find exactly what I'm looking for or reading google documentation I missed it, I just need a function or whatever to submit 2 point, start and end, and get X waypoint in between.
Is there some api like "www.somesite.com/api.php?start=43.12,12.23&end=44.12,12.23&number_of_waypoints=5" that return some json?
thank you!
First of all, this will require working with geodesics, which are the shortest lines passing through two points around the Earth, assuming the Earth is an ellipsoid. WGS84 is the standard coordinate system you will see most widely used for "latitude + longitude" coordinates, and this assumes the Earth is an ellipsoid.
To solve this problem, you first need to find the azimuth (bearing angle from north) and distance between two coordinates. The way to calculate this is by solving the inverse geodesic problem.
Once we have this distance (let's say in metres), we can divide it by n, where n - 1 is the number of waypoints we want in between the line. This gives us the distance d metres between each waypoint.
Now, we need to plot points at intervals of d metres along this line. To do this, we can solve the direct geodesic problem. This gives us a new set of coordinates after moving a given distance from a given point with a given azimuth. We can do this repeatedly to get new points moving d metres from the previous point each time. One thing to note with this is that the resultant azimuth to the end of the line from different points within the line will vary, so the destination azimuth must be obtained after each stage and used for calculating the next point.
Solving the direct and inverse geodesic problems requires mathematical formulas, of which multiple are available. However, for your PHP application, you are probably best not trying to implement these yourself, but instead use a library which can do this for you. One popular library for PHP which does this is called phpgeo.
Here's an example of how this might be implemented with phpgeo:
<?php
use Location\Coordinate;
use Location\Distance\Vincenty;
use Location\Bearing\BearingEllipsoidal;
$numPoints = 5;
$coordsA = new Coordinate(50.0, 0.0);
$coordsB = new Coordinate(51.0, 1.0);
$bearingCalculator = new BearingEllipsoidal();
$distanceCalculator = new Vincenty();
// Inverse geodesic problem
// Calculate total length of line between coords
$totalDistance = $distanceCalculator->getDistance($coordsA, $coordsB);
$intervalDistance = $totalDistance / ($numPoints + 1);
// Inverse geodesic problem
// Calculate angle to destination
$currentBearing = $bearingCalculator->calculateBearing($coordsA, $coordsB);
$currentCoords = $coordsA;
$points = [];
for ($i = 0; $i < $numPoints; $i++) {
// Direct geodesic problem
// Calculate new point along line
$currentCoords =
$bearingCalculator->calculateDestination($currentCoords,
$currentBearing,
$intervalDistance);
// Add these new coordinates to the list
array_push($points, $currentCoords);
// Inverse geodesic problem
// Recalculate angle to destination
$currentBearing =
$bearingCalculator->calculateBearing($currentCoords,
$coordsB);
}
// Print out the list of points
foreach ($points as $point) {
echo "{$point->getLat()}, {$point->getLng()}\n";
}
I am trying to draw the lines or the edges of a cone using plot3 in matlab. Any help please? I do not need the surface. I need the edges only. SO that I can patch something on it. A useful link. But i need the circle at the bottom:
https://patentimages.storage.googleapis.com/US8514658B2/US08514658-20130820-D00021.png
Few horizontal lines are fine. But no tilted line as i need to patch something inside.
cylinder is your friend here...
You just need to pass it a vector of radii* and transpose the output*...
* negative radii tending to zero will flip the order so the apex is on top...
* so it draws rings not lines from the base to the apex
numRings = 10;
numPointsAround = 100;
[x,y,z] = cylinder(linspace(-1,0,nlines),numPointsAround);
plot3(y.',x.',z.','-k')
I think this is what you want. Most of the answer is directly taken from the above answer by #RTL.
numRings = 2;
numPointsAround = 100;
[x,y,z] = cylinder(linspace(-1,0,numRings),numPointsAround);
plot3(y.',x.',z.','-k')
hold on;line([-0.5878;0], [0.809;0],[0;1]);
hold on;line([0.9511;0], [-0.309;0],[0;1]);
axis square
i am working on some camera data. I have some points which consist of azimuth, angle, distance, and of course coordinate field attributes. In postgresql postgis I want to draw shapes like this with functions.
how can i draw this pink range shape?
at first should i draw 360 degree circle then extracting out of my shape... i dont know how?
I would create a circle around the point(x,y) with your radius distance, then use the info below to create a triangle that has a larger height than the radius.
Then using those two polygons do an ST_Intersection between the two geometries.
NOTE: This method only works if the angle is less than 180 degrees.
Note, that if you extend the outer edges and meet it with a 90 degree angle from the midpoint of your arc, you have a an angle, and an adjacent side. Now you can SOH CAH TOA!
Get Points B and C
Let point A = (x,y)
To get the top point:
point B = (x + radius, y + (r * tan(angle)))
to get the bottom point:
point C = (x + radius, y - (r * tan(angle)))
Rotate your triangle to you azimouth
Now that you have the triangle, you need to rotate it to your azimuth, with a pivot point of A. This means you need point A at the origin when you do the rotation. The rotation is the trickiest part. Its used in computer graphics all the time. (Actually, if you know OpenGL you could get it to do the rotation for you.)
NOTE: This method rotates counter-clockwise through an angle (theta) around the origin. You might have to adjust your azimuth accordingly.
First step: translate your triangle so that A (your original x,y) is at 0,0. Whatever you added/subtracted to x and y, do the same for the other two points.
(You need to translate it because you need point A to be at the origin)
Second step: Then rotate points B and C using a rotation matrix. More info here, but I'll give you the formula:
Your new point is (x', y')
Do this for points B and C.
Third step: Translate them back to the original place by adding or subtracting. If you subtracted x last time, add it this time.
Finally, use points {A,B,C} to create a triangle.
And then do a ST_Intersection(geom_circle,geom_triangle);
Because this takes a lot of calculations, it would be best to write a program that does all these calculations and then populates a table.
PostGIS supports curves, so one way to achieve this that might require less math on your behalf would be to do something like:
SELECT ST_GeomFromText('COMPOUNDCURVE((0 0, 0 10), CIRCULARSTRING(0 10, 7.071 7.071, 10 0), (10 0, 0 0))')
This describes a sector with an origin at 0,0, a radius of 10 degrees (geographic coordinates), and an opening angle of 45°.
Wrapping that with additional functions to convert it from a true curve into a LINESTRING, reduce the coordinate precision, and to transform it into WKT:
SELECT ST_AsText(ST_SnapToGrid(ST_CurveToLine(ST_GeomFromText('COMPOUNDCURVE((0 0, 0 10), CIRCULARSTRING(0 10, 7.071 7.071, 10 0), (10 0, 0 0))')), 0.01))
Gives:
This requires a few pieces of pre-computed information (the position of the centre, and the two adjacent vertices, and one other point on the edge of the segment) but it has the distinct advantage of actually producing a truly curved geometry. It also works with segments with opening angles greater than 180°.
A tip: the 7.071 x and y positions used in the example can be computed like this:
x = {radius} cos {angle} = 10 cos 45 ≈ 7.0171
y = {radius} sin {angle} = 10 sin 45 ≈ 7.0171
Corner cases: at the antimeridian, and at the poles.