Anyways, Triangles are cool, they are COOL! Well today i was trying to write a little proc that you could pass 5 arguments to, and would display a triangle onto the screen.
example:
proc
showtriangle(atom/O as obj,a as num,b as num,c as num,duration as num)
//O: the atom to make up the triangle
//A: the first length, or angle of the triangle
//B: the second length, or angle of the triangle
//C: the third length, or angle of the triangle
//Duration: Length of time to display the triangle
I was trying to figure out the best method, either declaring the lenghts of each side, or the degree's of each angle. I couldnt make up my mind, so i decided to do something like this...
proc
showtriangle(atom/O as obj,atom/a,atom/b,atom/c,duration as num)
//O: the atom type to make up the triangle
//A: an atom on the map, using locate(x,y,z)
//B: "" ""
//C: "" ""
//Duration: Length in time to display the triangle
This turned out to be much better, since all we have to do is declare three spots on the map using the locate() proc for our arguments in the proc call!
I figured i would need some of the following things to happen within the proc:
1. Determine the distance between each point
2. Determine the mid point of each side of the triangle
3. Determine the center of the triangle
all three of those things could easily be done by the following:
#1:
var/dist1 = get_dist(a,b)
var/dist2 = get_dist(a,c)
var/dist3 = get_dist(b,c)
#2:
var/half1 = round(dist1/2)
var/half2 = round(dist2/2)
var/half3 = round(dist3/2)
#3:
I had a little trouble with this, and I havent quite come up with a perfect method.
One major problem that i was concerned with during the entire designing of this, was the fact that some triangles could not be correctly displayed due to byond's tile based system. This was because you would sometimes need an object to be displayed "between" the lines....
I thought about making some proc, that uses missile some how, that just shoots a line from point a to b and so on. But that didnt turn out so well :(
So, im considering also making a crap load of icon states of each possible situation, or using the new icon datum to handle it via sliding and etc....
Then I was thinking about the next possible situations to include into the proc:
1. Determine (somehow) if the sum of the angles equal 180. This is true of all triangles.
< stands for angle sign
2. Determine if the sum of the lengths of any two sides added together is greater than the other remaining side. This is true of all triangles.
_ stands for line segment sign
A + B > C
A + C > B
B + C > A
3. Determine if any one of the sides is 90 degress, to make some of the processing easier on us(we know that one of the angles is 90 degress, and that two of the points go direction straight out from the 90 angle.)
These things would be considered for later, since they are basically checks to see if the user hasnt tried inputing an invalid triangle.
I was hoping that someone could send me even further down the line of understanding on this topic, so that i may learn how to show objects "between" the lines simpler, and so that my damn triangle effect will work!
FIREking
Using the points of the triangle is definately the way to go. If you used the lengths or angles, you could be describing a triangle of the same shape anywhere in your world skewed at any angle.
In DM, get_dist() doesn't return the true geometric distance between two points. You'll have to define a new proc for true distance:
proc/true_distance(atom/A, atom/B)
return sqrt((A.x-B.x)**2+(A.y-B.y)**2+(A.z-B.z)**2)
That will tell you half the distance, but it won't tell you anything useful about the midpoint. Here is an example proc that returns the turf halfway between two atoms:
proc/midpoint(atom/A, atom/B)
return locate(round((A.x+B.x)/2,1), round((A.y+B.y)/2,1), round((A.z+B.z)/2,1))
(The round(*,1) is very important so that it rounds instead of simply truncating the decimal.)
I don't recall ever calculating the "center" of a triangle. Do you have a definition for it?
Off hand, I would think you could find the center by cacluating the line from each angle to the midpoint of the opposite side, then find the intersection of the three lines. I don't know if they will all intersect in the same point, and I really don't feel like doing a proof for it if you have the information available.
Given the points, you can calculate the line for each side. To see if something is inside the triangle, cycle through each line and test if the object is on the same side of the line as the opposite angle. If the object fails any of the three tests, it's outside the triangle.
If you want to fill the triangle, get a block() the include the triangle (by getting the lowest and highest x and y values from the points given) and test each turf in the block to see if it's inside the triangle.
Perhaps you could make a partially black/partially mask block, then turn() and shift() it to the right location and use icon addition to add it to the triangle icon. That way your triangle proc can use any icon without requiring ridiculous numbers of icon_states.
If you define the triangle by the atomic points, you'll never have have to worry about either of these. You can't input an invalid triangle because any three (non-colinear) points defines a triangle. If the points are colinear, these rules are stile valid, but your triangle just became a line segment.
It would only make it easier if the angles correspond to the x and y axis. If I have a 90 degree angle that is 15 degrees clockwise from the x axis, knowing it's a right angle won't help draw it.
Well, hope it helped. The notes above on checking something inside the triangle should probably be limited to checking it if the triangle is all on one z level. If not, you'll have to see if the object is even in the same plane with the triangle!
As you can probably tell. I enjoyed geometry too. ;)