
 Forum  iziBasic
Warning: A nonnumeric value encountered in /web5/aldweb/www/aldweb_com/www/thread.php on line 257
Sujet n° 1413 
FilledIn Triangles 
le 21/05/2006 @ 10:14 par Garfield

Hi
I want to draw filledin triangles and I can't work out how to do it.
I can obviously draw outlined triangles using three LINETO statements, but how do you get a filledin triangle?
I'm sure once you tell me I'll kick myself, but right now I'm at a loss.
Thanks.



Warning: A nonnumeric value encountered in /web5/aldweb/www/aldweb_com/www/thread.php on line 497
Réponse n° 11  le 21/05/2006 @ 22:37 par aldweb
visiteur 
If Pythagore was able to read us, he would for sure be laughing a lot!
Cheers
@+ aldweb 


Warning: A nonnumeric value encountered in /web5/aldweb/www/aldweb_com/www/thread.php on line 497
Réponse n° 12  le 22/05/2006 @ 04:35 par Ktimaster
visiteur 
I Will Send Him an email... lol 


Warning: A nonnumeric value encountered in /web5/aldweb/www/aldweb_com/www/thread.php on line 497
Réponse n° 13  le 22/05/2006 @ 22:59 par Garfield
visiteur 
OK, I worked out a procedure to draw a filledin triangle with coordinates (A,B), (C,D) and (E,F) as follows:
A=30 : B=30 C=50 : D=150 E=150 : F=50
X=CE : V=ABS(X) Y=DF : W=ABS(Y) Z=MAX(V,W) X=X/Z : Y=Y/Z
FOR T = 0 TO Z V = T*X+E W = T*Y+F LINE A,B TO V,W NEXT
The only problem with this routine is that you get 'Moire' type patterns because of the way the Palm draws diagonal lines.
However, I've already worked out how to draw triangles with only horizontal (or vertical) lines that will fix this. I've just got to find some time to convert my process into an iziBasic program and I'll then post it here.
Watch this space!



Warning: A nonnumeric value encountered in /web5/aldweb/www/aldweb_com/www/thread.php on line 497
Réponse n° 14  le 26/05/2006 @ 16:02 par Garfield
visiteur 
OK, I've done it. Below is the program that will draw a completely filled in triangle without any gaps using horizontal lines only.
Feel free to modify the coordinates (variables A to F) or create a procedure to allow you to enter them within the program itself. The routine that actually draws the triangle is a subroutine that only requires the coordinates in variables A to F [or A(1) to A(6)], so it should be easy for you to do this. You can also set the colour to anything you want before you call the subroutine.
For those that want an explanation as to what the subroutine does, check out my next post. This one is getting too big!
BEGIN A=30 : B=30 ' Coordinate 1 C=150 : D=50 ' Coordinate 2 E=50 : F=150 ' Coordinate 3
' Call Draw Triangle Routine GOSUB _DrawFilledTriangle
' Pause so we can see our triangle! REPEAT : Z=WAITEVENT : UNTIL Z<0
END
_DrawFilledTriangle:
' Sort coordinates in order of height IF D<F SWAP C,E:SWAP D,F IF B<D SWAP A,C:SWAP B,D IF D<F SWAP C,E:SWAP D,F
' Calculate MidPoint G X=DF : Y=BF : Z=EA : Z=ABS(Z) G=Z*X/Y : G=ROUND(G) IF E>A THEN G=EG ELSE G=E+G ENDIF
' Jump to Fill Routines I=A : J=B GOSUB _DrawHalfTriangle ' Bottom Half I=E : J=F GOSUB _DrawHalfTriangle ' Top Half
' Draw Outline to tidy sharp corners LINE A,B TO C,D LINETO E,F LINETO A,B
RETURN
_DrawHalfTriangle: IF J=D RETURN ' Return if flat top or bottom
IF J>D THEN Z=JD : V=1 ' Bottom Half ELSE Z=DJ : V=1 ' Top Half ENDIF
X=IG : X=X/Z ' Calculate xaxis steps Y=IC : Y=Y/Z
FOR W=0 TO Z I=X*W+G : I=ROUND(I) J=Y*W+C : J=ROUND(J) H=W*V H=D+H LINE I,H TO J,H NEXT
RETURN



Warning: A nonnumeric value encountered in /web5/aldweb/www/aldweb_com/www/thread.php on line 497
Réponse n° 15  le 26/05/2006 @ 17:01 par bh77a
visiteur 
Hi Garfield,
Very good work. I hope that you don't mind, but I modified your original code slightly to accomplish the same thing. I will use it in a library for graphics if you give permission :).
Anyways, here is the change that I made...
... start code here ' Triangletest.ibas {CREATORID "Tri1"}
REM original code by "Garfield" REM mod by bh77a REM now draws from second & third vertices to opposing segments (legs) REM this eliminates "moire"
BEGIN REM vertices A=30:B=30 'one C=50:D=150 'two E=150:F=50 'three
GOSUB _Draw_Filled_Triangle
REM event loop REPEAT E=DOEVENTS UNTIL E=1 END
_Draw_Filled_Triangle: REM calculate slope REM C,D to E,F X=CE:V=ABS(X) Y=DF:W=ABS(Y) Z=MAX(V,W) X=X/Z:Y=Y/Z
REM draw line from vertex to opposing segment REM A,B to segment C,D/E.F FOR T=0 TO Z V=T*X+E W=T*Y+F LINE A,B TO V,W NEXT
REM MOD STARTS HERE  REM calculate slope REM A,B to C,D X=AC:V=ABS(X) Y=BD:W=ABS(Y) Z=MAX(V,W) X=X/Z:Y=Y/Z
REM draw line from vertex to opposing segment REM E,F to segment A,B/C,D FOR T=0 TO Z V=T*X+C W=T*Y+D LINE E,F TO V,W NEXT
REM calculate slope REM A,B to E,F X=EA:V=ABS(X) Y=FB:W=ABS(Y) Z=MAX(V,W) X=X/Z:Y=Y/Z
REM draw line from vertex to opposing segment REM C,D to segment A,B/E.F FOR T=0 TO Z V=T*X+A W=T*Y+B LINE C,D TO V,W NEXT REM END MOD HERE RETURN 


Warning: A nonnumeric value encountered in /web5/aldweb/www/aldweb_com/www/thread.php on line 497
Réponse n° 16  le 26/05/2006 @ 17:45 par Garfield
visiteur 
Hi bh77a
I don't mind you using my code in your library. However, I thought of doing what you have done, but as screen resolutions get bigger then even drawing from all three vertices may not eliminate the moire effect. I assume we will eventually have a Palm device with a 640x480 screen, and I wonder if a triangle that fills most of that screen will not suffer from moire patterns, even if you do draw from all three vertices. Also you are drawing the triangle three times which is not efficient.
If you look at the latest code I have posted it is more efficient as it eliminates the possibility of moire effects by only using horizontal lines. I'd love you to use this new code rather than my old code if possible.
Check it out! if you look at the latest code I have posted it is more efficient as it eliminates the possibility of moire effects by only using horizontal lines.
Check it out!



Warning: A nonnumeric value encountered in /web5/aldweb/www/aldweb_com/www/thread.php on line 497
Réponse n° 17  le 26/05/2006 @ 17:48 par Garfield
visiteur 
Hi
This post will hopefully explain my subroutine in my previous post for those that are interested. If you're not interested or don't care then I suggest you stop reading now!
It's hard to explain my procedure without diagrams, etc, so I hope you can understand what I'm trying to explain.
I realised that it was not very hard to write a routine to draw a triangle that had a horizontal top or bottom. My subroutine _DrawHalfTriangle does this.
Take a triangle with coordinates (A,B), (C,D), and (E,D). Note that using 'D' twice is not a mistake  (C,D) and (E,D) form the horizontal side and their ycoordinate is therefore the same.
All you have to do is the following:
1. count the number of pixels from the horizontal side to the opposite corner (in other words, the height of the triangle in pixels). In my procedure this height is stored in 'Z'. Therefore:
Z = ABS(BD)
2. work out the xcoordinate at each value of Z from each corner of the horizontal side to the opposite corner. We want to do a loop from 0 to Z and we want to draw a horizontal line at each step. We therefore need to calculate the coordinates of the horizontal line at each step. The ycoordinate is easy  it's the step value between 0 and Z. We need to calculate the xcoordinates of each end of the line. To do this we simply take the difference of the xcoordinates [(CA) and (EA)] and divide by Z. These values are stored in 'X' and 'Y' in my subroutine. We then multiply this value by the step value between 0 and Z and add it back to the starting coordinate (C or E).
3. draw a horizontal line at each value of Z using the calculated xcoordinates. In my procedure 'I' and 'J' are used to store the new value and the line is drawn.
And that's it.
Now, that's very good for a triangle with a horizontal side, but not all triangles have horizontal sides. However, having said that, all triangles can be divided into two triangles, each one having a horizontal side at which point they join together to form the complete triangle.
If you think about it, take any triangle (that doesn't have a horizontal side) and draw a horizontal line through the middle point (the corner that is neither the highest corner nor the lowest corner). This horizontal line you have drawn will have divided your triangle into two triangles, each with a horizontal top or bottom where they join each other.
So, all we have to do is calculate that horizontal line and then draw both triangles using the above procedure.
This is what my procedure _DrawFilledTriangle does before calling _DrawHalfTriangle twice.
The first thing the procedure does is sort the coordinates out so that (A,B) is the lowest corner, (C,D) is the middle corner, and (E,F) is the highest corner.
The dividing horizontal line therefore cuts through (C,D), and (C,D) would be one of the coordinates of the flat side. We have to calculate the coordinate where the horizontal line cuts through the opposite side of the triangle. In my procedure this is stored in variable 'G'.
We then have two triangles with coordinates as follows:
(A,B), (C,D), (G,D) (E,F), (C,D), (G,D)
In my subroutine, variables I and J are used to store the opposite corner [(A,B) and then (E,F)] so that the same procedure can be used for both triangles.
Finally I draw the outline to finish it off. This is important as triangles with sharp, pointy corners will not be drawn correctly without drawing the outline.
Note that my _DrawHalfTriangle subroutine has protection so that if you actually want to draw a triangle with a horizontal side which therefore has no top (or bottom) triangle it will exit and do nothing when called.
I've noticed an issue with my procedure. If you draw the outline of the triangle in a different colour to the fill you may notice that my fill does not fit in exactly. There are some sides where the fill seems to stick out beyond the line slightly (by one pixel). This is due to the routine for drawing lines using a different algorithm to the one I have used and it would be difficult for me to get it exactly right, but it's currently fairly accurate.
And that's pretty much it. I hope it made sense.
If anyone wants to improve on it or convert it into an applet that can be called then please be my guest. As I said previously, drawing triangles is very important when dealing with graphics, so I would welcome this.



Warning: A nonnumeric value encountered in /web5/aldweb/www/aldweb_com/www/thread.php on line 497
Réponse n° 18  le 26/05/2006 @ 18:33 par Garfield
visiteur 
I'm already modifying my own code!
I've discovered you get a better result if you remove the following code which can be found on the second line after ' Calculate MidPoint G:
: G=ROUND(G)
Rounding off G is not a good idea at this point. It causes some triangles to have a slight bend in their side, so please leave it out.
Thanks.



Warning: A nonnumeric value encountered in /web5/aldweb/www/aldweb_com/www/thread.php on line 497
Réponse n° 19  le 26/05/2006 @ 21:18 par aldweb
visiteur 
I will use it in a library for graphics if you give permission :).
This is a good idea and good initiative.
Cheers, aldweb



Warning: A nonnumeric value encountered in /web5/aldweb/www/aldweb_com/www/thread.php on line 497
Réponse n° 20  le 26/05/2006 @ 22:03 par Ktimaster
visiteur 
Will iziBasic ever support External Libraries... Hopefully 


sujet actif
sujet clos
Important!
Nouveau message 
Rectifier message
Clôturer sujet
Remonter

