How to check if two wkb geometries form an arc of a circle instead of an S shape? - geometry

I have two wkb geometries.
geometry1:
010200000044000000B4493437958B0E4019D69EA39F59494023B1EE69988B0E4031467FC39F5949407307FBC09F8B0E402B9DB415A05949400A9A3B9FA68B0E400DB21B6CA05949404E76D8E9AC8B0E40D784B4C6A05949408D953DAEB28B0E408A157F25A159494078FEFEDEB78B0E40FBE4CD86A1594940C3B7B06EBC8B0E4054724EECA1594940BBBABE6AC08B0E40D77E7C53A2594940C61451B8C38B0E4018CA2EBDA25949402FBFD364C68B0E4018546529A3594940ABC0DA62C88B0E40AC9D7296A35949408712D2BFC98B0E406B662D05A459494075BB4D6ECA8B0E40292FE873A459494075BB4D6ECA8B0E40E7F7A2E2A45949408712D2BFC98B0E403A803452A5594940ABC0DA62C88B0E40648918C0A55949402FBFD364C68B0E40F8D2252DA6594940C61451B8C38B0E40F85C5C99A6594940BBBABE6AC08B0E4039A80E03A7594940C3B7B06EBC8B0E405174136BA759494078FEFEDEB78B0E401542BDCFA75949408D953DAEB28B0E401BD1E231A85949404E76D8E9AC8B0E40CD61AD90A85949400A9A3B9FA68B0E40983446EBA85949407307FBC09F8B0E407A49AD41A959494023B1EE69988B0E4074A0E293A9594940CE9DAA8C908B0E40F1790FE1A9594940C0C69A36888B0E40F0D53329AA594940951E97827F8B0E4073B44F6CAA594940FFAB3363768B0E40E4558CA9AA5949404B68DCE56C8B0E40D879C0E1AA594940C74CFD17638B0E4025A13E13AB594940C1520207598B0E40CCCB063EAB594940847357C04E8B0E4061B9EF62AB594940C5B59036448B0E40E469F981AB5949401E0C8684398B0E402B5E7699AB594940DC6FA3B72E8B0E40CC553DAAAB59494000E1E8CF238B0E40C6504EB4AB59494023522EE8188B0E40AE0E80B8AB594940F9C907F30D8B0E40C6504EB4AB5949401C3B4D0B038B0E40CC553DAAAB594940DA9E6A3EF88A0E402B5E7699AB59494033F55F8CED8A0E40E469F981AB594940C1300510E38A0E4061B9EF62AB5949403858EEBBD88A0E40CCCB063EAB594940315EF3AACE8A0E4025A13E13AB594940AD4214DDC48A0E40D879C0E1AA594940F9FEBC5FBB8A0E40E4558CA9AA594940638C5940B28A0E4073B44F6CAA59494038E4558CA98A0E40F0D53329AA5949407806B243A18A0E40F1790FE1A959494023F36D66998A0E4074A0E293A959494086A3F501928A0E407A49AD41A9594940EE10B5238B8A0E40983446EBA8594940AA3418D9848A0E40CD61AD90A85949406C15B3147F8A0E401BD1E231A859494080ACF1E3798A0E401542BDCFA759494035F33F54758A0E405174136BA75949408AE99D65718A0E4039A80E03A7594940808F0B186E8A0E40F85C5C99A659494016E5886B6B8A0E40F8D2252DA65949404DEA1560698A0E40648918C0A5594940BF918A10688A0E403A803452A5594940D1E80E62678A0E40E7F7A2E2A4594940D1E80E62678A0E40292FE873A4594940BF918A10688A0E406B662D05A45949404DEA1560698A0E40AC9D7296A3594940
geometry2:
0102000000070000004DEA1560698A0E40AC9D7296A359494016E5886B6B8A0E4018546529A3594940808F0B186E8A0E4018CA2EBDA25949408AE99D65718A0E40D77E7C53A259494035F33F54758A0E4054724EECA159494080ACF1E3798A0E40FBE4CD86A15949406C15B3147F8A0E408A157F25A1594940
I need to check whether they form an arc(C shape) instead of an S shape. How can I achieve this with only the wkb information.

Check that for all triplets of subsequent points P[i], P[i+1], P[i+2] polyline makes turn of the same direction (either all left, or all right turns).
For example, you can check sign of cross product of vectors P[i+1]- P[i] and P[i+2]- P[i+1].
In coordinates:
cp = (P[i+1].X-P[i].X)*(P[i+2].Y-P[i+1].Y)-(P[i+1].Y-P[i].Y)*(P[i+2].X-P[i+1].X)

Related

Making holes in GeoJson Shapes - clipperLib

I have several overlapping shapes. I want to be able to make holes in the biggest shape that contains all the smaller shapes. the holes will represent the smaller shapes within the bigger shape.
sample image:
I am using the C# version of ClipperLib:
const double precisionFactor = 1000000000000000.0;
//precondition: all your polygons have the same orientation
//(ie either clockwise or counter clockwise)
Polygons polys = new Polygons();
multiPolygon.ForEach(x =>
{
Polygon polygon = x.First().Select( y => new IntPoint()
{
X = (long)(y[0] * precisionFactor),
Y = (long)(y[1] * precisionFactor)
}).ToList();
polys.Add(polygon);
});
Polygons solution = new Polygons();
Clipper c = new Clipper();
c.AddPaths(polys, PolyType.ptSubject,true);
c.Execute(ClipType.ctDifference, solution,
PolyFillType.pftNonZero, PolyFillType.pftNonZero);
var coordinates = solution.SelectMany(x => x.Select(y=> (IList<double>)new List<double>()
{
y.X / precisionFactor,
y.Y / precisionFactor
}).ToList()) .ToList();
return coordinates;
but the shape that gets returned is the biggest shape in the above picture.
GeoJson File:
http://s000.tinyupload.com/download.php?file_id=62259172894067221043&t=6225917289406722104327028
When you state that you "want to be able to make holes in the biggest shape", I think you're misunderstanding the way the Clipper library manages/defines polygon regions. In Clipper, polygons are defined by a series of closed paths together with a specified polygon filling rule - most commonly either EvenOdd or NonZero filling. (Polygons are almost always defined in this way in graphics display libraries.)
Hence with your data above, since you're using NonZero filling, the 'hole' paths must be orientated in the opposite direction to the orientation of the container outer path. If the inner paths have the same orientation as the outer container, then performing a 'difference' clipping operation using NonZero filling will correctly ignore the inner paths.
As a side note, when performing a clipping operation on a single set of polygons (ie when there are no clipping paths) it's more intuitive to perform a 'union' operation since subject paths are 'union'-ed (as are clip paths) before any clipping op between subject and clip regions.

Align shape to vector using Dgame framework and D language

I've been using Dgame framework for simple simulations.
I need moving object to be aligned to their velocity vectors.
How is it possible to do that using Dgame?
I see that shape object has setRotation and setRotationCenter. Not sure how to use these to achieve the effect. I realize that default is rotation around origin. This causes objects to drift over time.
Sample code
struct GameObject {
Point **position;
// array of pointers to object points
Point *acceleration;
Point *velocity;
double max_speed;
double max_force;
}
shape = new Shape(Geometry.Quads,
Vertex(object.position[0].x, object.position[0].y),
Vertex(object.position[1].x, object.position[1].y),
Vertex(object.position[2].x, object.position[2].y),
Vertex(object.position[3].x, object.position[3].y))
// rotate shape to face velocity here
shape.move(object.velocity.x, object.velocity.y);
You can achieve this using atan2. Depending on the orientation of the texture you might need to change the values a bit or add 90/-90 degrees.
For textures that face up:
rotation = atan2(-velocity.x, velocity.y);
For textures that face right:
rotation = atan2(-velocity.y, -velocity.x);
You might need to convert the result from radians to degrees or the other way around.

How can I detect and remove unneeded points in cubic bezier

Here is example image of what I want to do:
I want to calculate Path 1 from Path 2.
Screenshot made from Inkscape, where I'm, at first, create Path 1, then add p3 to the original path. This is didn't change the original path at all, because new point actually unneeded. So, how can I detect this point(p3) using Path 2 SVG path representation and calculate Path 1 from Path 2?
Basically, I search for the math formulas, which can help me to convert(also checking that whether it is possible):
C 200,300 300,250 400,250 C 500,250 600,300 600,400
to
C 200,200 600,200 600,400
You're solving a constraint problem. Taking your first compound curve, and using four explicit coordinates for each subcurve, we have:
points1 = point[8];
points2 = point[4];
with the following correspondences:
points1[0] == points2[0];
points1[7] == points2[3];
direction(points1[0],points1[1]) == direction(points2[0], points2[1]);
direction(points1[6],points1[7]) == direction(points2[2], points2[3]);
we also have a constraint on the relative placement for points2[1] and points2[2] due to the tangent of the center point in your compound curve:
direction(points1[2],points[4]) == direction(points2[1],points2[2]);
and lastly, we have a general constraint on where on- and off-curve points can be for cubic curves if we want the curve to pass through a point, which is described over at http://pomax.github.io/bezierinfo/#moulding
Taking the "abc" ratio from that section, we can check whether your compound curve parameters fit a cubic curve: if we construct a new cubic curve with points
A = points1[0];
B = points1[3];
C = points1[7];
with B at t=0.5 (in this case), then we can verify whether the resulting curve fits the constraints that must hold for this to be a legal simplification.
The main problem here is that we, in general, don't know whether the "in between start and end" point should fall on t=0.5, or whether it's a different t value. The easiest solution is to see how far that point is along the total curve (using arc length: distance = arclength(c1) / arclength(c1)+arclength(c2) will tell us) and use that as initial guess for t, iterating outward on either side for a few values.
The second option is to solve a generic cubic equation for the tangent vector at your "in between" point. We form a cubic curve with points
points3 = [ points1[0], points1[1], points1[6], points1[7] ];
and then solve its derivative equations to find one or more t values that have the same tangent direction (but not magnitude!) as our in-between point. Once we have those (and we might have more than 2), we evaluate whether we can create a curve through our three points of interest with the middle point set to each of those found t values. Either one or zero of the found t values will yield a legal curve. If we have one: perfect, we found a simplification. If we find none, then the compound curve cannot be simplified into a single cubic curve.

how to check if a solid rectangular box is a subset of solid ball

Suppose we have been given the coordinates of the centre of a solid rectangular box, the box's length, breadth, height and a solid ball with a given centre and radius.
Is there a fast way to check if the box is a subset of the ball? The only simple method that comes to my mind is to check if each of the 8 corner vertices lies inside the sphere. If yes, the box is indeed a subset of the ball (by convexity property of the ball).
If you expect that most of the time the box will not be inside the sphere, you can do some quick tests:
if (sphere.center.x+sphere.radius<box.center.x-box.size.x) return false;
if (sphere.center.x-sphere.radius>box.center.x+box.size.x) return false;
etc.
If you expect that the box will usually be far inside the sphere, you can do other quick tests:
bsx = box.size.x;
bsy = box.size.y;
bsz = box.size.z;
box_radius = sqrt(bsx*bsx+bsy*bsy+bsz*bsz)/2;
brx = box.center.x-sphere.center.x;
bry = box.center.y-sphere.center.y;
brz = box.center.z-sphere.center.z;
box_dist = sqrt(brx*brx+bry*bry+brz*brz);
if (box_radius+box_dist<sphere.radius) return true;
You will still need more precise tests if the quick tests fail though.
There are only 4 corners to check, but in fact you only need to check 2 which are diagonal to each other. This follows from the property of the rectangle having straight sides, while the circle is convex, as you state.
Alternatively, consider that if the left upper corner and right lower corner are both within the circle, then the rectangle they form is a boudning box. The circle is obviously not, and thus the rectangle must be a sub-region of the circle.
EDIT: You might be talking about a box and a sphere, in which case the same idea applies, you just have to choose points which have different x, y, and z values

How do I set a surf to one color (no gradient) in my matlab-plot?

My dataset consists of three vectors (x,y and z). I plot these values as dots in a 3d-plot with plot3(x,y,z), which is fine. I also want to show a plane in the same plot. To get the data of this plot I use linear regression on x and y to get a new z.
This is how it looks:
(source: bildr.no)
I want the surf to be filled with only one color (say light blue or gray) and set the opacity, to make it see-through. How can I do this?
The easiest way to create a surface that has just 1 color and a given transparency value is to set the 'FaceColor' and 'FaceAlpha' properties of the surface object:
hSurface = surf(...your arguments to create the surface object...);
set(hSurface,'FaceColor',[1 0 0],'FaceAlpha',0.5);
This example sets the surface color to be red and the transparency to 0.5. You can also set the edge properties too (with 'EdgeColor' and 'EdgeAlpha').
It is not clear to me what you want to do. When you say one color for the surf, do you mean exactly one color, or do you mean you want shades of gray?
Here is some code that will do a variety of things, you can choose which lines to use:
x = rand(1,20);
y = rand(1,20);
z = rand(1,20);
[X,Y] = meshgrid(linspace(0,1,10),linspace(0,1,10));
Z = rand(10)*0.1;
clf
plot3(x,y,z,'.');
hold on
h = surf(X,Y,Z)
hold off
%% This will change the color
colormap(copper)
%% This will remove colordata
set(h, 'cdata',zeros(10))
%% This will make transparent
alpha(0.5)
Completing the answer from gnovice, an extra ingredient in set(hsurface...) may be required (Matlab R2010b 64):
hSurface = surf(...your arguments to create the surface object...);
set(hSurface, 'FaceColor',[1 0 0], 'FaceAlpha',0.5, 'EdgeAlpha', 0);
to make invisible the point-to-point edges of the plotted surface
#matlabDoug has what you need, I think. The property cdata holds color data that gets a color map applied to it. Setting it to an array the same size as your surface data, with each element in that array having the same value, will make your surface one color. With the default color map, setting everything in cdata to zero will make your surface blue, and setting everything to 1 will make the surface red. Then you can play with the alpha to make it transparent.

Resources