Area of Triangles

Blitz3D Forums/Blitz3D Programming/Area of Triangles

_PJ_(Posted 2013) [#1]
Does anybody know how I might go about calculating the surface Area of a mesh?

(Fortunately, these meshes arte single-surface and there's no issues with transparency either)

I figured iterating through the Triangles and calculating each of their areas would be the way to go, however, I'm a little stuck on the trig since these Triangles can be oriented to planes on any axis at any angle.

Here's as far as I've gotten with this approach:
Function CalculateSurfaceArea(Ship.SHIPS)
	Local ShipMesh=Ship\Mesh
	
	;Local IterSurface
	Local Surface
	Local IterTriangle
	Local v0
	Local v1
	Local v2
	
	Local X0#
	Local Y0#
	Local Z0#
	
	Local X1#
	Local Y1#
	Local Z1#
	
	Local X2#
	Local Y2#
	Local Z2#
	
        Local Area#

	;For IterSurface=1 To CountSurfaces(ShipMesh)
	;	Surface=GetSurface(ShipMesh,IterSurface)
	
	;ONLY 1 SURFACE FOR TEST
	Surface=GetSurface(ShipMesh,1)
	For IterTriangle=1 To CountTriangles(Surface)
		v0=TriangleVertex(Surface,IterTriangle,0)
		X0#=VertexX(Surface,v0)
		Y0#=VertexY(Surface,v0)
		Z0#=VertexZ(Surface,v0)
		
		v1=TriangleVertex(Surface,IterTriangle,1)
		X1#=VertexX(Surface,v1)
		Y1#=VertexY(Surface,v1)
		Z1#=VertexZ(Surface,v1)
		
		v2=TriangleVertex(Surface,IterTriangle,2)
		X2#=VertexX(Surface,v2)
		Y2#=VertexY(Surface,v2)
		Z2#=VertexZ(Surface,v2)
                
                Area;=?????
                
	Next
    Return Area#
End Function

		



MCP(Posted 2013) [#2]
The area of a triangle is 0.5 x base x height. After that just add the areas of all the triangles in the mesh together.

Using vertex variables from your code sample...


Someone may know of a faster way of doing this but it works for me :)


Floyd(Posted 2013) [#3]
Calculate the lengths of the three sides. Let's call those lengths a,b,c.
Then the semiperimeter is s = (a+b+c)/2.

Heron's formula for the area is Sqr( s*(s-a)*(s-b)*(s-c) ).

Remarkably, this has been known for more than two thousand years.

Another reasonable approach is to use two sides as vectors. Calculate the cross product. The area is half the length of the cross product.

Neither of these methods is difficult to implement. But without any built-in vector operations they are a bit lengthy.


_PJ_(Posted 2013) [#4]

The area of a triangle is 0.5 x base x height.


Yeah I knew that, but the rotation of triangles in 3D confused me, but thank you for the code :)


Calculate the lengths of the three sides. Let's call those lengths a,b,c.
Then the semiperimeter is s = (a+b+c)/2.

Heron's formula for the area is Sqr( s*(s-a)*(s-b)*(s-c) ).


That's neat - But I'm still unsure even how to calculate the length of each side!

Another reasonable approach is to use two sides as vectors. Calculate the cross product. The area is half the length of the cross product.


Which, I believe is pretty much what MCP has shown above? Which seems to work just finer, so I'll stick with that but thanks for the info and if I ever have a moment of genius insight maybe I'll try to work on a Heron's Formula method :)


Floyd(Posted 2013) [#5]
Here's something from the Code Archives. The function accepts x,y,z for three points. It calculates the three side lengths and the area.

Just ignore the final "Return (2.0 * (area/ab))" and return the area instead.

;-----------------------------------------------------------------------------------------------------
;												PointDistToLine()
;-----------------------------------------------------------------------------------------------------
; ID: 1870
; Author: Danny
; Date: 2006-11-24 19:01:55
; Title: Point distance to a Line
; Description: Calculates the shortest distance between a point P and a line

Function PointDistanceToLine#( ax#,ay#,az#, bx#,by#,bz#, px#,py#,pz# )
;| Calculates the shortest distance between a point P(xyz) and a line segment defined by A(xyz) and B(xyz) - danny.

	;get the length of each side of the triangle ABP
	ab# = Sqr( (bx-ax)*(bx-ax) + (by-ay)*(by-ay) + (bz-az)*(bz-az) )
	bp# = Sqr( (px-bx)*(px-bx) + (py-by)*(py-by) + (pz-bz)*(pz-bz) )
	pa# = Sqr( (ax-px)*(ax-px) + (ay-py)*(ay-py) + (az-pz)*(az-pz) )

	;get the triangle's semiperimeter
	semi# = (ab+bp+pa) / 2.0
	
	;get the triangle's area
	area# = Sqr( semi * (semi-ab) * (semi-bp) * (semi-pa) )
	
	;return closest distance P to AB
	Return (2.0 * (area/ab))
	
End Function



Rroff(Posted 2013) [#6]
EDIT: Ignore covered above


_PJ_(Posted 2013) [#7]
Great find, thanks so much, Floyd!


Kryzon(Posted 2013) [#8]
That's neat - But I'm still unsure even how to calculate the length of each side!

As shown in that archive entry, you can calculate the euclidean distance between each pair of vertices like this: distance = Sqr( (X2 - X1)^2 + (Y2 - Y1)^2 + (Z2 - Z1)^2 )

(Doesn't really matter the order of the subtractions - that is, if you do X2-X1 or X1-X2 for instance - since you're squaring them they'll always become positive values.)

Another reasonable approach is to use two sides as vectors. Calculate the cross product. The area is half the length of the cross product.

Is there a name for this method? I didn't know about that half cross = area, it's a nice piece of info.


Floyd(Posted 2013) [#9]
Is there a name for this method? I didn't know about that half cross = area, it's a nice piece of info.

When I learned calculus the cross product was actually defined this way. The cross product of U and V was a vector W such that:

1. W is perpendicular to the plane determined by U and V.
2. The magnitude of W is equal the area of the parallelogram with sides U and V.
3. U,V,W is a right handed system.

Note the parallelogram consists of two congruent triangles.

Starting from the definition and working with the basis vectors i,j,k the usual formula for cross product was then derived.

You can read the same thing at cross product. The "Definitions" and "Computing the cross product" sections are the relevant ones.


Kryzon(Posted 2013) [#10]
Understood, thanks.