Apologies if this is considered a repeat question, but the answers I've seen on here are too complex for my needs.
I simply need to find out if a line segment intersects a circle. I don't need to find the distance to the line from the circle center, I don't need to solve for the points of intersection.
The reason I need something simple is that I have to code this in SQL and am unable to call out to external libraries, and need to write this formula in a WHERE clause... basicaly it has to be done in a single statement that I can plug values in to.
Assuming 2 points A (Ax,Ay) and B (Bx,By) to describe the line segment, and a circle with center point C (Cx,Cy) and radius R, the formula I am currently using is:
( RR ( (Ax-Bx)(Ax-Bx) + (Ay-By)(Ay-By) ) )
-( ((Ax-Cx)(By-Cy))-((Bx-Cx)(Ay-Cy)) ) > 0
This formula is taken from link text, and is based on a 0,0 centered circle.
The reason I am posting is that I am getting weird results and I wondered if I did something stupid. :(
although this doesn't exactly answer your question: Do you really have to calculate this on the fly on a SQL-Select? This means that the DB-system has to calculate the formula for every single row in the table (or every single row for which the remaining where conditions hold, respectively) which might result in bad performance.
Instead, you might consider creating a separate boolean column and calculate its value in an on-insert/on-update trigger. There, in turn, you wouldn't even need to put the test in a single line formula. Using a separate column has another advantage: You can create an index on that column which allows you to get your set of intersecting/non-intersecting records very fast.
Related
I am trying to write a Minecraft Datapack, which will plot a full armorstand circle around whatever runs the particular command. I am using a 3rd party mathematics datapack to use Sin and Cos. However, when running the command, the resulting plot was... not good. As you can see here: 1. Broken Circle., rather than have each vertex evenly placed in a circular line, I find a strange mess instead.
I would have thought loosing precision in Cos and Sin would simply make the circle more angular, I didn't expect it to spiral. What confuses me, is that +z (the red square) and -x (the purple one) are all alone. You can see on the blue ring (Which was made with a smaller radius) the gap between them persists.
My main issue is; How did my maths go from making a circle to a shredded mushroom, and is there a way to calculate the vertices with a greater precision?
Going into the project I knew I could simply spin the centre entity, and summon an armorstand x blocks in front using ^5 ^ ^, however I wanted to avoid this, due to my desire to be able to change the radius without needing to edit the datapack. To solve this, I used the Sin and Cos components to plot a new point, using a radius defined with scoreboards.
I first tested this using Scratch, in order to check my maths. You can see my code here: 2. Scratch code.
With an addition of the pen blocks, I was able to produce a perfect circle, which you can see here:
. Scratch visual proof.
With my proof of concept working, I looked online and found a Mathematical Functions datapack by yosho27, since the Cos and Sin functions are not built into the game. However, due to how Minecraft scoreboards are only Integers, Yosho27 multiplied the result of Cos and Sin by 100 to preserve 2 decimal places.
To start with, I am using a central armorstand with the tag center, which is at x: 8.5 z: 8.5. The scoreboards built into yosho's datapack that I am using is math_in for the values I want converted and math_out, which is where the final value is dumped.
Using signs, I keep track of the important values I am working with, as seen here: 4. Sign maths.
As I was writing this, I decided to actually compare both numbers to find this: 5. Image comparison, which shows me that somewhere in this calculation process, the maths has gone wrong. I modified the scratch side to match the minecraft conditions as much as possible, such as x100 and adding 850 to the result. From this result, I can see a disparity between x and z, even though they should be equal. Where Minecraft says 1: x= 864 z= 1487, Scratch says 1: x= 862.21668448: z= 1549.89338664. I assume this means the datapack's Cos and Sin are not accurate enough?
In light of this , I looked in yosho's datapack, I found this: 6. Yosho's code., which I just modified to be *= 10 instead of divide, in the hope of getting more precision. Modifying the rest of my code to match, I couldn't see any improvement in the numbers, although the armorstand vertices were a few pixels off the original circle, although I couldn't find a discernible pattern to this shift.
While this doesn't answer your full question, I'd like to point out two different ways you can solve the original issue at hand, no need to rely on some foreign math library:
^ ^ ^
Use Math, but let the game do it for you.
You can use the fact that the game is doing those rotational conversions for you already when using local coordinates. So, if you (or any entity) go to 0 0 0 and look / rotate in the angle that you want to calculate, then move forward by ^ ^ ^1, the position you're at now is basically <sin> 0 <cos>.
You can now take those numbers with your desired precision using data get and continue using them in whatever way you see fit.
Use recursive functions to move in incremenets
You point out in your question that
Going into the project I knew I could simply spin the centre entity, and summon an armorstand x blocks in front using ^5 ^ ^, however I wanted to avoid this, due to my desire to be able to change the radius without needing to edit the datapack. To solve this, I used the Sin and Cos components to plot a new point, using a radius defined with scoreboards.
So, to go back to that original idea, you could fairly easily (at least easier than trying to calculate the SIN/COS manually) find a solution that works for (almost) arbitrary radii and steps: By making the datapack configurable through e.g. scores, you can set it up to for example move forward by ^^^0.1 blocks for every point in a score, that way you can change that score to 50 to get a distance of ^^^5 and to 15 to get a distance of ^^^1.5.
Similarly you could set the "minimum" rotation between summons to be 0.1 degrees, then repeating said rotation for however many times you desire.
Both of these things can be achieved with recursive functions. Here is a quick example where you can control the rotational angle using the #rot steps score and the distance using the #dist steps score as described above (you might want to limit how often this runs with a score, too, like 360/rotation or whatever if you want to do one full circle). This example technically recurses twice, as I'm not using an entity to store the rotation. If there is an entity, you don't need to call the forward function from the rotate function but can call it from step (at the entity).
step.mcfunction
# copy scores over so we can use them
scoreboard players operation #rot_steps steps = #rot steps
scoreboard players operation #dist_steps steps = #dist steps
execute rotated ~ ~0.1 function foo:rotate
rotate.mcfunction
scoreboard players remove #rot_steps steps 1
execute if score #rot_steps matches ..0 positioned ^ ^ ^.1 run function foo:forward
execute if score #rot_steps matches 1.. rotated ~ ~0.1 run function foo:rotate
forward.mcfunction
scoreboard players remove #dist_steps steps 1
execute if score #dist_steps matches ..0 run summon armor_stand
execute if score #dist_steps matches 1.. positioned ^ ^ ^.1 run function foo:forward
I'm working on a PyMEL script that allows the user to duplicate a selected object multiple times, using a CV curve and its points coordinates to transform & rotate each copy to a certain point in space.
In order to achieve this, Im using the adjacent 2 points of each CV (control vertex) to determine the rotation for the object.
I have managed to retrieve the coordinates of the curve's CVs
#Add all points of the curve to the cvDict dictionary
int=0
cvDict={}
while int<selSize:
pointName='point%s' % int
coords= pointPosition ('%s.cv[%s]' % (obj,int), w=1)
#Setup the key for the current point
cvDict[pointName]={}
#add coords to x,y,z subkeys to dict
cvDict[pointName]['x']= coords[0]
cvDict[pointName]['y']= coords[1]
cvDict[pointName]['z']= coords[2]
int += 1
Now the problem I'm having is figuring out how to get the angle for each CV.
I stumbled upon the angleBetween() function:
http://download.autodesk.com/us/maya/2010help/CommandsPython/angleBetween.html
In theory, this should be my solution, since I could find the "middle vector" (not sure if that's the mathematical term) of each of the curve's CVs (using the adjacent CVs' coordinates to find a fourth point) and use the above mentioned function to determine how much I'd have to rotate the object using a reference vector, for example on the z axis.
At least theoretically - the issue is that the function only takes 1 set of coords for each vector and I have absolutely no Idea how to convert my point coords to that format (since I always have at least 2 sets of coordinates, one for each point).
Thanks.
If you wanna go the long way and not grab the world transforms of the curve, definitely make use of pymel's datatypes module. It has everything that python's native math module does and a few others that are Maya specific. Also the math you would require to do this based on CVs can be found here.
Hope that puts you in the right direction.
If you're going to skip the math, maybe you should just create a locator, path-animate it along the curve, and then sample the result. That would allow you to get completely continuous orientations along the curve. The midpoint-constraint method you've outlined above is limited to 1 valid sample per curve segment -- if you wanted 1/4 of the way or 3/4 of the way between two cv's your orientation would be off. Plus you don't have to reinvent all of the manu different options for deciding on the secondary axis of rotation, reading curves with funky parameterization, and so forth.
I'm trying to take an array of 3D points and a plane and divide the points up into 2 arrays based on which side of the plane they are on. Before I get to heavily into debugging I wanted to post what I'm planning on doing to make sure my understanding of how to do this will work.
Basically I have the plane with 3 points and I use (pseudo code):
var v1 = new vector(plane.b.x-plane.a.x, plane.b.y-plane.a.y, plane.b.z-plane.a.z);
var v2 = new vector(plane.c.x-plane.a.x, plane.c.y-plane.a.y, plane.c.z-plane.a.z);
I take the cross product of these two vectors to get the normal vector.
Then I loop through my array of points and turn them into vectors and calculate the dot product against the normal.
Then i use the dot product to determine the side that the point is on.
Does this sound like it would work?
Let a*x+b*y+c*z+d=0 be the equation determining your plane.
Substitute the [x,y,z] coordinates of a point into the left hand side of the equation (I mean the a*x+b*y+c*z+d) and look at the sign of the result.
The points having the same sign are on the same side of the plane.
Honestly, I did not examine the details of what you wrote. I guess you agree that what I propose is simpler.
Following the 'put points into the plane's equation and check the sign' approach given previously. The equation can be easily obtained using SymPy. I used it to find location of points (saved as numpy arrays) in a list of points.
from sympy import Point3D, Plane
plane=Plane(Point3D(point1), Point3D(point2), Point3D(point3))
for point in pointList:
if plane.equation(x=point[0], y=point[1],z=point[2]) > 0:
print "point is on side A"
else:
print "point is on side B"
I haven't tested its speed compared to other methods mentioned above but is definitely the easiest method.
Your approach sounds good. However, when you say "and turn them into vectors", it might not be good (depending on the meaning of your sentence).
You should "turn your points into vector" by computing the difference in terms of coordinates between the current point and one of the points in the plane (for example, one of the 3 points defining the plane). As you wrote it, it sounds like you might have misunderstood that ; but apart from that, it's ok!
take into account the normal vector of the plane
example: for the point A=[-243.815437431962, -41.7407630281635, 10.0]
equation= -2663.1860000000006*Z +21305.488000000005=0
RESULt POSITIVE
but if equation= 2663.1860000000006*Z -21305.488000000005=0
RESULT NEGATIVE
I'm making a program that selects an area within a canvas by clicking a sequence of points. The points clicked are linked by some lines this way: every new point is linked with the first and the last ones. I'm looking for an algorithm that computes the area of the resulting polygon.
Intersections are allowed, and here is the complexity, so the algorithm must manage this case by finding the polygon according to the ordered sequence of points clicked and calculating its area.
After many searches, the best I've found is this http://sigbjorn.vik.name/projects/Triangulation.pdf, but I would need something easier to implement in Processing.js.
First cut the line segments where they intersect. If the input set is small, you can simply check every pair. Otherwise use an R-Tree. Then compute a constrained (Delaunay) Triangulation. Then determine the inner triangles using rayshooting and sum up their areas.
hth
This is just a LARGE generalized question regarding rays (and/or line segments or edges etc) and their place in a software rendered 3d engine that is/not performing raytracing operations. I'm learning the basics and I'm the first to admit that I don't know much about this stuff so please be kind. :)
I wondered why a parameterized line is not used instead of a ray(or are they??). I have looked around at a few cpp files around the internet and seen a couple of resources define a Ray.cpp object, one with a vertex and a vector, another used a point and a vector. I'm pretty sure that you can define an infinate line with only a normal or a vector and then define intersecting points along that line to create a line segment as a subset of that infinate line. Are there any current engines implementing lines in this way, or is there a better way to go about this?
To add further complication (or simplicity?) Wikipedia says that in vector space, the end points of a line segment are often vectors, notably u -> u + v, which makes alot of sence if defining a line by vectors in space rather than intersecting an already defined, infinate line, but I cannot find any implementation of this either which makes me wonder about the validity of my thoughts when applying this in a 3d engine and even further complication is created when looking at the Flash 3D engine, Papervision, I looked at the Ray class and it takes 6 individual number values as it's parameters and then returns them as 2 different Number3D, (the Papervision equivalent of a Vector), data types?!?
I'd be very interested to see an implementation of something which actually uses the CORRECT way of implementing these low level parts as per their true definitions.
I'm pretty sure that you can define an infinate line with only a normal or a vector
No, you can't. A vector would define a direction of the line, but all the parallel lines share the same direction, so to pick one, you need to pin it down using a specific point that the line passes through.
Lines are typically defined in Origin + Direction*K form, where K would take any real value, because that form is easy for other math. You could as well use two points on the line.