need some help with maths (vectors)

Community Forums/General Help/need some help with maths (vectors)

RemiD(Posted 2016) [#1]
Hello,

Let's assume that i know the position of a point in 3d space (or in 2d space), and i know 2 3d vectors (or 2d vectors) which starts/ends at this point.

I want to calculate another vector which would be "perpendicular" to the combination of the 2 vectors.

the formula can be for 2d points and 2d vectors since there is no depth variation (on the z axis)

An illustration to better understand what i mean :


magenta : 3d point (or 2d point)
red : 3d vectorA (or 2d vectorA)
green : 3d vectorB (or 2d vectorB)
blue : 3d vectorC (or 2d vectorC) (<- what i want to find, considering the point and the vectorA and the vectorB)

any magic formula ?

Thanks,


Bobysait(Posted 2016) [#2]
It's the definition of the Cross Product.
-> a third vector z perpendicular to the plane xy

you can get the sens of your vector if you observe a simple rule :
X goes to Y
Y goes to Z
Z goes to X
X = Y.cross (Z)
Y = Z.cross (X)
Z = X.cross (Y)

so:
if you want the x axis -> y.z
xx# = yy# * zz# - yz# * zy#
xy# = yz# * zx# - yx# * zz#
xz# = yx# * zy# - yy# * zx#

if you want the y axis -> z.x
yx# = zy# * xz# - zz# * xy#
yy# = zz# * xx# - zx# * xz#
yz# = zx# * xy# - zy# * xx#

and if you want the z axis -> x.y
zx# = xy# * yz# - xz# * yy#
zy# = xz# * yx# - xx# * yz#
zz# = xx# * yy# - xy# * yx#

here you probably search the Y axis (the plane, ZX)
if you want for 2d space, just "0" the third axis and the equations becomes very clear ;)


RemiD(Posted 2016) [#3]
@Bobysait>>what do you mean by "if i want the x axis ? or y axis ? or z axis ?"
On the illustration, the point, the vectorA, the vectorB, are 3d points/vectors, but they always have the same z coordinate, so they can be considered 2d points/vectors (with different x,y coordinates).

i want to find the blue vector which must have x,y properties not only x or not only y...

can you please clarify what you mean ?

Thanks,


col(Posted 2016) [#4]
RemiD,
You need to calculate the normal of the polygon by calculating the cross product of the 2 vectors that you already have.

There are many coordinate systems used in 3d. You have the local polygon space, texture space, model space, world space plus many many more.

For you to achieve your goal here you need to understand that the polygon has its own local x,y and z axis in relation to the polygon face. No matter what direction the polygon is facing within the 3d world this local polygon space doesn't change.


I'll repeat a lot of what you already know ( as your'e almost there ) for the sake of others that maybe don't know the terms and what/how they relate...

To keep things simple use triangles.
You'll have 3 vertices, which we'll call A B and C. It doesn't matter which vertex you name as what, the point is to identify the 3 different vertices.

Choose any 2 of the vertices, lets choose A and B.
Using some simple math take the x,y,z coord of vertex A from the x,y,z coord of vertice B. If vertex A is at 2,2,0 and vertex B is at 6,4,0 then do 6-2 = 4, 4-2 = 2, 0-0 = 0. This new 4,2,0 is called a vector, which is the vector from vertex A to vertex B.

Now do the same for A to C.

Now you have 2 vectors, A to B and A to C, these can be thought of ( but inaccurately termed ) as the X,Y vectors. To find the Z vector, ie the direction the polygon is facing ( the polygon normal that's perpendicular to the other 2 vectors ) you need to use the standard Cross Product algo.

Heres some blitz style pseudo code to help out
' Calculate the cross product of 2 3d vertices

' Three vertices
Local Ax, Ay, Az
Local Bx, By, Bz
Local Cx, Cy, Cz

Local ABx,ABy,ABz    ' This will be a vector from A to B ( B - A )
Local ACx,ACy,ACz    ' This will be a vector from A to C ( C - A )

Local Nx,Ny,Nz       ' This will be the Z ( axis in relation the polygon face ) in other words the 'normal'

ABx = Bx - Ax
ABy = By - Ay
ABz = Bz - Az

ACx = Cx - Ax
ACy = Cy - Ay
ACz = Cz - Az

Nx = ABy * ACz - ABz * ACy
Ny = ABz * ACx - ABx * ACz
Nz = ABx * ACy - ABy * ACx



RemiD(Posted 2016) [#5]
@col>>i don't understand why you call the resulting vector (perpendicular to the 2 others vectors) the "normal" of the polygon, because in 3d the normal is a vector perpendicular to a triangle, but after some thought there is also a normal for each vertex which can be calculated by taking into account the normals of the triangles which use this vertex, so it is similar, but this time in 2d.

Ok i will try the formula, thanks for the explanations !


RemiD(Posted 2016) [#6]
the resulting vector seems incorrect (or maybe there is an error in my code ?)
see :
;removed useless code


col(Posted 2016) [#7]
why you call the resulting vector (perpendicular to the 2 others vectors) the "normal" of the polygon


Yes, I can understand the confusion, sorry about that.
In this situation the poly normal and vertex normal are exactly the same thing, as this will calculate the vector that's perpendicular to the other 2 vectors. Using that algo, and providing that you don't change the winding order of the vertices in the calculations, then you will get the same result for each vertex if you move the vertices around in the calculation, as long as you don't change their winding order. This is why I referred to it as a polygon normal. All 3 vertices will have the same Z vector. Again, sorry for the confusion.

there is also a normal for each vertex which can be calculated by taking into account the normals of the triangles which use this vertex

If you wanted smooth shading across the faces then yes.
In the case of a box which would have hard edges then you calculate the vertex normals using the cross product as above.


col(Posted 2016) [#8]
My Blitz3D is very rusty nowadays and I struggled with your example so I just downloaded the ole champion and threw together this working example to hopefully help visualize things...

Graphics3D 800,600,32,2

Local cam = CreateCamera()
PositionEntity cam, 0, 0, -50

Local light = CreateLight()
PositionEntity light, 0, 0, -30

Local pivot = CreatePivot()

Local Ax# = 0.0 : Ay# = 0.0 : Az# = 0.0
Local Bx# = 0.0 : By# = 10.0 : Bz# = 0.0
Local Cx# = 10.0 : Cy# = 0.0 : Cz# = 0.0

Local p0 = CreateSphere(20)
Local p1 = CreateSphere(20)
Local p2 = CreateSphere(20)

PositionEntity p0, Ax, Ay, Az
PositionEntity p1, Bx, By, Bz
PositionEntity p2, Cx, Cy, Cy

EntityParent p0, pivot
EntityParent p1, pivot
EntityParent p2, pivot

; the xaxis bar
Local xaxis = CreateCylinder(16)
ScaleMesh xaxis, 0.2, 5, 0.2
PositionMesh xaxis, 0, 5, 0
EntityColor xaxis, 255, 0, 0

; the yaxis bar
Local yaxis = CreateCylinder(16)
ScaleMesh yaxis, 0.2, 5, 0.2
PositionMesh yaxis, 0, 5, 0
EntityColor yaxis, 0, 255, 0

; the zaxis bar
Local zaxis = CreateCylinder(16)
ScaleMesh zaxis, 0.2, 5, 0.2
PositionMesh zaxis, 0, 5, 0
EntityColor zaxis, 0, 0, 255


Local ang# = 0.0
While Not KeyDown(1)
	Cls
	
	; xaxis bar
	Local CAx# = EntityX( p2, 1 ) - EntityX( p0, 1 )
	Local CAy# = EntityY( p2, 1 ) - EntityY( p0, 1 )
	Local CAz# = EntityZ( p2, 1 ) - EntityZ( p0, 1 )
	AlignToVector xaxis, CAx, CAy, CAz, 2
	
	; yaxis bar
	Local BAx# = EntityX( p1, 1 ) - EntityX( p0, 1 )
	Local BAy# = EntityY( p1, 1 ) - EntityY( p0, 1 )
	Local BAz# = EntityZ( p1, 1 ) - EntityZ( p0, 1 )
	AlignToVector yaxis, BAx, BAy, BAz, 2

	; zaxis bar
	Local Nx# = BAy * CAz - BAz * CAy
	Local Ny# = BAz * CAx - BAx * CAz
	Local Nz# = BAx * CAy - BAy * CAx
	AlignToVector zaxis, Nx, Ny, Nz, 2
	
	
	ang = ang + 1
	RotateEntity pivot, ang * 0.5, ang * 0.75, ang * 0.15
	
	RenderWorld
	Flip
Wend
End



RemiD(Posted 2016) [#9]
@col>>it seems that your example produces the same result (normal vector) than my example, and if so, that's not the vector that i want to calculate ! and by looking at my illustration i think that you misunderstood (or i badly expressed) what i want.

i want to calculate a vector which starts at the point where 2 vectors starts/ends and which is at the middle of the angle between the 2 vectors and start at the point and ends away from the the point. (it can be 2d points/vectors or 3d points/vectors, whatever)

here is the new illustration :


i already have a formula to calculate the angle between 2 3d vectors, but i need a way to calculate the properties of the vector which would be in the middle and pointing away from the point (starts at the point and ends away from the point)

but even if i find a way to calculate the properties of this vector, i see another problem : how to determine if the vector points on one side of the 2 others vectors or on the other side... (inside the triangle ABC or outside the triangle ABC)


well, maybe there is an easiest way to get vertices normals pointing in the direction that i want by using a premade mesh ? i will try... (maybe with the above shape but with front faces and back faces on a closed welded surface ?)


Bobysait(Posted 2016) [#10]
Well, you're not looking for a "perpendicular" vector, or you have so hardness to read 3D (there is actually a majority of people that can't deal with perspective view ... maybe you're one of them).

In the demo, the blue vector is perpendicular to the plane of the red and green.

Now, I think you should tell us what you want to do instead of a way to do it.
-> on your screenshot above, is it the problem you encounter while trying to do a perpendicular vector ? or is it what you're looking for ?
(if it's what you're looking for, then it's absolutely not a perpendicular vector but a Vector bisector (in french -> bissectrice), which is obtained by just adding the two vectors and divide by 2.0)


[EDIT]

Ok, you posted another one while I was typing this one.
Definitely, you're not looking for a perpendicular vector, but the bisector.

V' = (V1+V2)/2
Then if it's the opposite of the angle, then multiply by "-1"


Ax = -(Bx + Cx)/2
Ay = -(By + Cy)/2
Az = -(Bz + Cz)/2 <- this one is "0" in 2D


RemiD(Posted 2016) [#11]

maybe with the above shape but with front faces and back faces on a closed welded surface ?)


no !


RemiD(Posted 2016) [#12]

Definitely, you're not looking for a perpendicular vector, but the bisector.


oh sorry, i tried to explain but the terms i used where what i thought it was not necessarily what they mean in maths...


@Bobysait>>thanks, i will try this formula.


Bobysait(Posted 2016) [#13]
If you're doing it with triangles, then there is no need to check for the sens if you always use the TriangleVertex order to get your vectors.

For t = 0 To CountTriangles(surf)-1
 v0 = TriangleVertex(surf, t, 0)
 v1 = TriangleVertex(surf, t, 1)
 v2 = TriangleVertex(surf, t, 2)
 ; v1 is probably the point to "project"
 ax# = VertexX(surf, v0)
 ay# = VertexY(surf, v0)
 az# = VertexZ(surf, v0)
 bx# = VertexX(surf, v1)
 by# = VertexY(surf, v1)
 bz# = VertexZ(surf, v1)
 cx# = VertexX(surf, v2)
 cy# = VertexY(surf, v2)
 cz# = VertexZ(surf, v2)
 ; AB = A to B
 abx# = bx-ax
 aby# = by-ay
 abz# = bz-az
 ; CB = C to B
 cbx# = bx-cx
 cby# = by-cy
 cbz# = bz-cz
 ; the "projected" vector
 vx# = (abx+bcx) * 0.5
 vy# = (aby+bcy) * 0.5
 vz# = (abz+bcz) * 0.5
 ; if you want the projected "point" and not only the "vector", add the position of v1
 px# = bx+vx
 py# = by+vy
 pz# = bz+vz
Next



Matty(Posted 2016) [#14]
Okay...I'm late to the party but let me try and visualise what you are describing (I looked at the diagram above to get an idea)...

You have a vector AB and a vector CB and you want to find a vector of any length that is in the direction midway between the two vectors.

So basically what you should do is this:

normalize vectors AB and CB to get two unit vectors (pure direction, magnitude 1).

Add the two unit vectors together and call it D

normalize vector D....it is now also a unit vector pointing in the direction midway between vectors AB and CB but with length 1.

scalar multiply unit vector D to the length you wish it to be.

Note - this will work for all vectors as long as the two vectors are not 180 degrees apart (ie opposite directions) as that will return a zero result for direction as the vectors cancel each other out.

Edit: Additional:
I recognise that you may or may not know the terms for vector mathematics (I studied it at university in the mid 90s) so I will describe in simple terms some of the words I used in case you have different understandings:

'normalize a vector' - divide it by its length
'unit vector' - a vector of length 1 unit - this may be considered to be a vector which is purely directional as it has a magnitude of 1.

'scalar multiply' - multiply all coefficients (x,y,z) of the vector by a single number - this has the effect of changing the magnitude of the vector but not changing the direction.

Edit 2 - bobysait is right about what you want - you want to bisect the angle between two vectors not find the perpendicular vector. perpendicular suggests that the angle is 90 degrees between the vectors and may be found by either using the cross product between two vectors and/or finding a pair of vectors for which the dot product is zero.

'cross product' = a cross b = c, typically equals this:
cx = ay*bz - by*az
cy = - ax*bz + bx*az
cz = ax*by - bx * ay
Gives a vector which is perpendicular (ninety degrees) to the original two vectors of length |a||b| sin (theta)
Cross product is zero when the vectors have zero angle between them.


'dot product' = a dot b = scalar value
ax * bx + ay * by + az * cz
Gives a value which is equal to |a| |b| cos(theta)
Dot product is zero when the vectors have 90 degrees between them.
Note the dot product is very useful for determining if an object is ahead or behind of another object since cos(theta) is goes close to 1 when an object is ahead of it, close to -1 when an object is behind it, and close to zero when an object is at right angles to it.

where |a| = magnitude of a, |b| = magnitude of b, theta is the angle between them.


Flanker(Posted 2016) [#15]
If I understood well, it's very simple :



1 - Input vectors
2 - Normalize the vectors so they have the same lenght
3 - You have an isoceles triangle, so the point in the middle of the third side gives you two equals angles.
4 - Invert the blue vector to get you normal, and eventually you'll have to normalize it.


RemiD(Posted 2016) [#16]
@Flanker>>
i think that i have found another simpler approach using the custom calculated vertices normals of a premade mesh.

however you method is smart ! thank you, i will try it !
(you can skip step 4 by directly calculating the normalised vector DA)


RemiD(Posted 2016) [#17]
my other approach with a procedure to custom calculate the vertices normals of a premade mesh depending on the normals of the triangles which use each vertex, partly produces correct normals and partly produces incorrect normals, and i have no idea what is the error or if there is any, because all seems correct...


ok, now i am going to try the method explained by Flanker... this should work...


Flanker(Posted 2016) [#18]
The bisector formula posted by bobysait should also work and is even simpler.


Floyd(Posted 2016) [#19]
Part of this is easy and part is difficult/impossible. I say impossible because the problem is still not clearly defined.

So let's try to nail this down. A closed polygon in 2d has an inside and an outside. The same is true in 3d if all points are restricted to some plane. But the general 3d case has no such easy distinction.

So let's concentrate on 2d. We have a point and two vectors, considered to be a point and two edges of some polygon. Looking only at the point and two edges we consider them to be a vertex and two edges of a triangle. The problem of an "angle bisector" was solved earlier in this thread. Orienting the vector to point to the outside of the triangle was also easily done.

But we still don't know if this points to the interior or exterior of the larger polygon. Farther up this page, in post #9, there is a polygon that looks like the grin on a Halloween pumpkin. If you try the triangle method on that you sometimes get a bisecting vector pointing into the polygon and other times pointing out.

But the edges should be oriented consistently. Imagine the polygon is drawn on the floor. And let's say the edge vectors are all oriented so that as you walk along the polygon the interior is on your left. That tells you how to orient the angle bisector. You want it to point to the outside, i.e. to your right.

There is a simple "dot product" test to tell if a point is to the left or right of a vector ( edge of 2d polygon ), which solves the problem.


RemiD(Posted 2016) [#20]
in any case, there will be too many vectors calculated... those who are oriented outwards the shape (what i want) and also those who are oriented inwards the shape (what i don't want)


i have another idea to achieve what i want, it is a ugly manual workaround but it should work well...


RemiD(Posted 2016) [#21]
Flanker's method in code : (seems to work well)

(press space to randomly position A,B,C and calculate the stuff)


RemiD(Posted 2016) [#22]
Matty's method in code : (seems to work well)

(press space to randomly position A,B,C and calculate the stuff)


Matty(Posted 2016) [#23]
Youve calculated middlelength wrongly in that implementation of mine.

Edit - fixed.


RemiD(Posted 2016) [#24]

Youve calculated middlelength wrongly in that implementation of mine.


oh ok i see the error thanks


Kryzon(Posted 2016) [#25]
Floyd wrote:
But we still don't know if this points to the interior or exterior of the larger polygon. Farther up this page, in post #9, there is a polygon that looks like the grin on a Halloween pumpkin. If you try the triangle method on that you sometimes get a bisecting vector pointing into the polygon and other times pointing out.

But the edges should be oriented consistently. Imagine the polygon is drawn on the floor. And let's say the edge vectors are all oriented so that as you walk along the polygon the interior is on your left. That tells you how to orient the angle bisector. You want it to point to the outside, i.e. to your right.

There is a simple "dot product" test to tell if a point is to the left or right of a vector ( edge of 2d polygon ), which solves the problem.

That's an interesting problem, to know what direction of the bisector is facing into the "outside" of the mesh.
Besides converting the mesh outer edges (the edges that are not shared between two triangles) into a closed line-segment polygon and doing an even-odd point inclusion test, I think you can also solve it with angles and some definitions of triangle meshes. This only works in 2D, though (or 3D restricted to a plane like you said):

- A vertex can have two connections (edges), like in the eyes of that face or the corners of the grin. In this case, the two edges\vectors from that vertex have to be joined themselves, always (they form a triangle in the mesh). In this case you know that the outside direction is the one opposite to that edge that joins the two edges of the vertex.

- Most of the time a vertex will have more than two connections. In this case you can take the two vectors and create two angle "regions".



The vertex that spawns the two edges\vectors has at least one more edge (but it could be more) that is connecting it to the rest of the mesh.
The region that represents 'outside' is the region that does not include absolutely any other mesh edges (shown in dashed red below) for that vertex. So the direction of the bisector that passes through the region that is not the one where all the mesh edges are, is the one that goes outside (the orange one).



You would use ATan2 a lot for this, but even though it uses trigonometry (can get imprecise) it should give the results needed. I do think the pre-determined edge ordering scheme you mentioned should be faster.


RemiD(Posted 2016) [#26]
here is the flat shape in question, to better see the vertices and triangles :


the good thing is that the shape is welded (there is only one vertex at each position and thus no vertices share the same position)

the problem is that each vertex is used by one or several triangles and the wanted pointing outwards vector can only be calculated by considering only the edges of the outline (not the edges at the inside of the shape).

so, a possible approach, would be for each vertex, to first identify which edges are on the outline of the shape (even if they do not form an existing triangle) and use these to calculate the pointing outwards vector.


RemiD(Posted 2016) [#27]
for the moment i have this :
;removed because of errors



RemiD(Posted 2016) [#28]
it seems that the procedure that i described in my previous post works, but it seems that there is a bug somewhere in my code :

i will try to debug it later...


RemiD(Posted 2016) [#29]
done :


here is the final procedure :
;for each triangle
 ;get the points and edges properties
 ;for each edge which composes this triangle (0->1, 1->0, 1->2, 2->1, 2->0, 0->2)
 ;add a new edge (with its properties) to the edges list
 ;0->1
 ;1->0
 ;1->2
 ;2->1
 ;2->0 
 ;0->2

;for each edge
 ;check if there are others edges with these properties
 ;if yes (it means that it is used by another triangle, therefore inside the shape)
  ;
 ;if no (it means that it is not used by another triangle, therefore on the outline of the shape)
  ;add a new outlineedge (with its properties) to the outlineedge list

;for each vertex
 ;for each outlineedge which uses this vertex as the start point (there should be 2)
  ;keep the properties of this outlineedge
 ;using the properties of the 2 outlineedges which use this vertex as the start point
 ;determine the points A,B,C of the triangle
 ;calculate the vector AB
 ;calculate the length AB
 ;calculate the normalised vector AB
 ;calculate the vector AC
 ;calculate the length AC
 ;calculate the normalised vector AC
 ;calculate the middle vector
 ;calculate the middle length
 ;calculate the middle normalised vector
 ;project a point along the middle normalised vector (0.01 with a slight random offset on the xaxis and on the y axis to not have the point positionned on the edge of a triangle with straight edges))
 ;check if point is inside one of the triangles of the shape
 ;if no (it means the middle normalised vector points outward the shape)
  ;keep the middle normalised vector
 ;if yes (it means the middle normalised vector points inward the shape)
  ;invert the middle normalised vector
 ;debug the middle outward normalised vector with a marker


thanks Flanker and Matty !


Kryzon(Posted 2016) [#30]
I know the thread is done by now but I like the brain puzzle. Here's some more on the method that Floyd mentioned in post #19.

---------------------------
You have a vertex on the outline of the mesh. That vertex has two outline edges, from which you can form vectors a and b. You can find the bisector of these two vectors by normalising their sum like it's already been discussed:


Important to make sure the vectors are formed from one end of the edge to the vertex, and then from the vertex to the other end (like the arrows indicate). This means the bisector needs to be calculated the old way (both vectors going away from the vertex), and for the rest below, use the vectors going to and from the vertex as illustrated.

---------------------------
We need to find which directions of the bisector represent the "outside" and the "inside".
To do this we need a few things. You need to find vectors that are normal (perpendicular) to vectors a and b. You can find these by using cross products -- you do a cross product (a x b) to get a vector c which is perpendicular to both a and b, and then do cross products (c x a) and (c x b) (important to use this same order of c x edge for both) to get a new vector perpendicular to a and another perpendicular to b. These will be shown as the purple lines on the last image. They still don't tell what is outside or inside.

---------------------------
Next we need a vector that we know points inside the mesh so we can project it onto the perpendicular vectors of a or b and find out which direction goes inside the mesh.
A good vector to use is the one that goes from the vertex to centre of the triangle that is formed by edge a or edge b. These are outline edges, by definition each outline edge is a part of only a single triangle of the mesh. You can choose the triangle that edge a is a part of, for example, and calculate the centre of that -- it's the average of its vertices, or (v1+v2+v3)/3. This vector is shown as the red arrow below.


---------------------------
With the vector perpendicular to edge 'a' (the purple line of the green vector) and another vector that we know goes inside the mesh (red vector), we can project the red vector onto the purple line and find out what direction of that purple line means "inside" the mesh -- we check this with the sign of the dot product (red . purple), if it's positive or negative. It's important to project the red arrow to the perpendicular vector of the same edge that is a part of the triangle that the red arrow was made from (the red arrow was made from the triangle formed by edge a, so we project it onto the purple line of edge a).
The bisector points in two directions, inside and outside the mesh. To know which direction is outside the mesh, you can make two vectors going in opposite directions along the bisector (shown with blue points, so the vectors are from the vertex to each blue point), and project these vectors onto the purple line of edge a. Based on the sign of this dot product you can know which direction along the bisector goes outside: it will be the sign opposite to what you got from the dot product with the red vector, which we know goes inside the mesh.



RemiD(Posted 2016) [#31]
i have tested my previous procedure with another arbitrary shape (another pumpkin carved areas), and it seems to work well :

:)

@Kryzon>>thanks for the explanations/illustrations, i will take a look


RemiD(Posted 2016) [#32]
using these "middle outwards" normalised vectors around the outline of the shape, it is possible to create 2 kinds of glow effects :
->a glow with rectangles (2triangles each) coming out from the outline of the shape and projected forward and slightly outwards (so that it has a -45° angle and is visible from the front and from the side) (using a combination of the vertices normals of the flat shape and the "middle outwards" normalised vectors of each vertex)
->a glow with a duplicated flat shape, with different flat layers around the shape, with each layer slightly bigger than the other and with its vertices uniformly positioned around the previous layer, with a decreasing alpha... (using the "middle outwards" normalised vectors of each vertex)


Kryzon(Posted 2016) [#33]
Unless I forgot something.

I did forget something, or rather didn't catch it at the time. I rewrote some of that post to correct it.