Page 1 of 1

General Polygons (i_polygons.cfdg)

Posted: Fri May 06, 2005 12:42 pm
by chris
This took some annoying geometry, but I was inspired by the cool hex and octagon work buy you guys. This include covers all convex regular polygons with obtuse inner angles, up to 99. They're all drawn without recursive definitions, so they're fast. Each one fits exactly in the circle of the same size, as seen here:

Image

Here's the demo CFDG

Code: Select all

startshape seed

include i_polygons.cfdg

rule seed {
 CIRCLE {x -2 y 2 b 0.5}
 CIRCLE {x -2 y 0 b 0.5}
 polygon5sided {x 0 y 0}
 polygon6sided {x 2 y 0}
 polygon7sided {x 4 y 0}
 polygon8sided {x 6 y 0}
 polygon9sided {x 0 y 2}
 polygon10sided {x 2 y 2}
 polygon11sided {x 4 y 2}
 polygon12sided {x 6 y 2}
 CIRCLE {x 8 y 0 b 0.5}
 CIRCLE {x 8 y 2 b 0.5}
}
And here's the C++ program I hacked together to generate it:

Code: Select all

#include <iostream>
#include <sstream>
#include <cmath>

using namespace std;
const float PI = 3.14159265;

float cleanFloat(float f) {
    if (f < 0.001 && f > -0.001)
        return (0);
    else
        return (f);
}

int main () {

    float R = 1.0;

    for (int n = 5; n < 100; n++) {
        cout << "\n\nrule polygon" << n << "sided {";
        float angle = 360.0 / float(n) / 2.0;
        float side = 2 * R * abs(sin(PI * angle / 180.0));
        float inner_circle_radius =  R * cos(angle * PI / 180.0);
        float dist = inner_circle_radius - side/2;

        for (int k = 0; k < n; k++) {
            float theta = float(k)*360.0/float(n);
            float x = dist * cos(PI * theta / 180.0);
            float y = dist * sin(PI * theta / 180.0);

            cout << "\n  SQUARE {size "
                 << cleanFloat(side)
                 << " x "
                 << cleanFloat(x)
                 << " y "
                 << cleanFloat(y)
                 << " rotate "
                 << cleanFloat (theta)
                 << "}";
        }
        cout << "\n  CIRCLE {s " << cleanFloat(inner_circle_radius)  << "}";
        cout << "\n}";
    }
}
And most important, here's the i_polygons.cfdg It's a pretty big file! n+1 replacements for each polygon, so it's like 300kB.

http://chriscoyne.com/cfdg/i_polygons.cfdg

Enjoy!

cc

Posted: Fri May 06, 2005 1:14 pm
by David Spitzley
Hot damn! Well, I feel a little silly having spent so much time hacking together my octogon, but if it helped inspire that file, I'm fine with silly :)

Now, I just need to test out the triangle that was recently posted.

Posted: Fri May 06, 2005 1:20 pm
by chris
David Spitzley wrote:Hot damn! Well, I feel a little silly having spent so much time hacking together my octogon, but if it helped inspire that file, I'm fine with silly :)
Yeah, it was yours and Erik's work that made me try it in the first place.

Triangles ARE annoying, since it's pretty clear they have to be drawn with infinite parts.

Even worse: most curving shapes are in fact impossible. I'm pretty sure you can't draw any ellipse other than a circle, even with infinite replacements. I'd love to find out I'm wrong.

-cc

Posted: Fri May 06, 2005 1:20 pm
by David Spitzley
Ok, that's weird. I just now tried a test with the polygons, and they're much larger than the default CIRCLE{}, which flies in the face of your screenshot. When I run the following:

Code: Select all

startshape SANDWICH
include i_polygons.cfdg
rule SANDWICH{
	polygon8sided{b 0.5}
	polygon6sided{b 0.75}
	CIRCLE{x}
	CIRCLE{x 2}
}
the first circle should be appearing behind the other two polygons, but it is completely hidden. The second circle shows that the polygons are about three times as wide. I'm not sure how to square this with your sample image. Is it possible we're getting differences due to OS? I'm running on Windows XP.

Posted: Fri May 06, 2005 1:28 pm
by David Spitzley
Ok, I just did a little poking around in i_polygons.cfdg file, and it appears to me that your size parameters are twice what they should be. The hexagon is using unit squares, when they actually need to be size .5, and your octogon is using size 0.765367, in contrast with the 0.38 that I worked up. Mine definitely fit inside a unit CIRCLE.

Is it possible your code used diameter in a place where it actually needed a radius? If you sized your sides based on calculating chord lengths using a central angle of 360/n, then I could easily see myself forgetting to add the factor of .5 for radial length.

<CHECKS CODE> Ok, yip, you've got R=1, should be 0.5

Posted: Fri May 06, 2005 1:36 pm
by chris
That's exactly it. I've updated the i_polygons.cfdg - let me know if it works for you, now.

http://www.chriscoyne.com/cfdg/i_polygons.cfdg

The problem was that the unix/windows/mac versions of Context Free had a different relative definition of size (square/circles, relative to each other) than I did in the original CFDG. I think the new way is better, so we'll call it a bug on my part. The new C++ program is this (I had to adjust a couple lines because of the implication of the radius change):

Code: Select all

#include <iostream>
#include <sstream>
#include <cmath>

using namespace std;
const float PI = 3.14159265;

float cleanFloat(float f) {
    if (f < 0.001 && f > -0.001)
        return (0);
    else
        return (f);
}

int main () {

    float R = 0.5;

    for (int n = 5; n < 100; n++) {
        cout << "\n\nrule polygon" << n << "sided {";
        float angle = 360.0 / float(n) / 2.0;
        float side = 2 * R * abs(sin(PI * angle / 180.0));
        float inner_circle_radius =  2 * R * cos(angle * PI / 180.0);
        float dist = inner_circle_radius/2 - side/2;

        for (int k = 0; k < n; k++) {
            float theta = float(k)*360.0/float(n);
            float x = dist * cos(PI * theta / 180.0);
            float y = dist * sin(PI * theta / 180.0);

            cout << "\n  SQUARE {size "
                 << cleanFloat(side)
                 << " x "
                 << cleanFloat(x)
                 << " y "
                 << cleanFloat(y)
                 << " rotate "
                 << cleanFloat (theta)
                 << "}";
        }
        cout << "\n  CIRCLE {s " << cleanFloat(inner_circle_radius)  << "}";
        cout << "\n}";
    }
}
-cc

Posted: Fri May 06, 2005 1:49 pm
by David Spitzley
WE HAVE A WINNER! :)

Yeah, that works really well. Ok, so now we've got pretty much arbitrary polygons. If we can get some wizard to develop triangles, we're set for pretty much anything.

Triangles

Posted: Fri May 06, 2005 2:07 pm
by emrainey
yes but what types? isosceles? Right angle? you can easily make a right angle triangle, conceptually, by rendering a black square (b=1) of side length x and then diagonally bisecting it with a white square (b=0) of length on side of the black triangle of side length sqrt(2*pow(x,2)). I don't know that this will work right off since I'm at work, but it's somethign to try. An isosceles trianlge conceptually can be done similarly but with 2 white squares.

croppping with white

Posted: Fri May 06, 2005 2:22 pm
by chris
Cropping with white squares doesn't really work as a solution, because it'll screw up tilings. There's definitely a difference between "whitespace" and "nospace".

Re: Triangles

Posted: Fri May 06, 2005 2:56 pm
by mtnviewmark
emrainey wrote:yes but what types? isosceles? Right angle? you can easily make a right angle triangle, conceptually, by.
Try this:

Code: Select all

startshape TRIANGLE 

rule TRIANGLE{ 
	ARM { r 0 }
	ARM { r 120 }
	ARM { r -120 }
} 

rule ARM {
	CIRCLE { }
	ARM { y 0.1 s 0.9 }
}
This was my first guess and it looks pretty right! Now, I don't know if the values of 0.1 and 0.9 are "correct" for a perfect triangle... I didn't do the math (but I probably will tonight...).

I do know that if you play with those values you get all sorts of nice things. And, of course, adding in a little rotation does wonders...

Triangles

Posted: Wed May 11, 2005 9:02 pm
by buckyboy314
Well, I cobbled together an Eigenmath program to create an arbitrary angle with relatively few polygons using the straight edge made by a row of squares. It looks really nice, and I will soon work on making a complete triangle program. My design is, in my opinion, a little obnoxious to program, but the result is nice, IMNSHO.
Here's the source:

###Use either THIS (and comment the next block):
###(Where M is the slope of the angles right side)
# m = 1/2
###Change only the above value^
# theta = float(arctan(m))


###Or THIS (and comment the previous block):
###(Where A is the angle of elevation of the right side or the complement of the angle at the tip)
A = 30
###Change only the above value^
theta=(A*pi/180)
m=tan(theta)


print("startshape TRI")
x= float(-1 / (2m + 2))
s= float(1 - (1 / (m + 1)))
y= float(1 - (1 / (2m + 2)))

print("rule TriEdgeL{")
print("SQUARE{}")
print("TriEdgeL{x ",x, " y ",y, " s ",s,"}")
print("}")

x = float(1 / (2m + 2))
print("rule TriEdgeR{")
print("SQUARE{}")
print("TriEdgeR{x ",x, " y ",y, " s ",s,"}")
print("}")

x = float((1/tan(theta)+1)/2-.5)
s = float(1/sin(theta))
y = -x
r = float(90-theta*180/pi)

print("rule TRI{")
print("TriEdgeL{}")
print("TriEdgeR{x ",x," y ",y," s ",s," r ",r,"}")
print("}")

Re: Triangles

Posted: Thu May 12, 2005 7:25 am
by chris
buckyboy314 wrote:Well, I cobbled together an Eigenmath program to create an arbitrary angle with relatively few polygons using the straight edge made by a row of squares.
Hey, I'd never heard of eigenmath. Cool! Off to download it...

General acute triangle program

Posted: Sun May 15, 2005 7:55 pm
by buckyboy314
This makes an acute triangle with the current center at the triangle's incenter and an inscribed circle radius 1. (That basically means if instead of a triangle, you draw CIRCLE{}, it will touch each side of the triangle exactly.) You may want to lower all y factors slightly if you're on a Mac so antialiasing doesn't make lines through the triangle. Here's the Eigenmath program:

#A is the first angle (pointing up), B is the second (pointing right)
A = 130
B = 42
#Change only the above values^
C=180-A-B


print("startshape TRIANGLE")
print("rule TRIANGLE{")
print("triA{}")
print("triB{r",float(-180+(A+B)/2),"}")
print("triC{r",float(90+B/2),"}")
print("}")

print("rule triA{")
theta=(45-(90-A)/2)*pi/180
x= float(.5 (sin(theta)- cos(theta)))
y= float(.5 (sin(theta)+cos(theta)))
r= float(-theta*180/pi)
print("SQUARE{x ",x," y ",y," r ",r,"}")
r= -r
x= -x
print("SQUARE{x ",x," y ",y," r ",r,"}")
y=float(1/cos(theta))
s=float(1-tan(theta))
print("triA{y",y," s ",s,"}")
print("}")

print("rule triB{")
theta=(45-(90-B)/2)*pi/180
x= float(.5 (sin(theta)- cos(theta)))
y= float(.5 (sin(theta)+cos(theta)))
r= float(-theta*180/pi)
print("SQUARE{x ",x," y ",y," r ",r,"}")
r= -r
x= -x
print("SQUARE{x ",x," y ",y," r ",r,"}")
y=float(1/cos(theta))
s=float(1-tan(theta))
print("triB{y",y," s ",s,"}")
print("}")

print("rule triC{")
theta=(45-(90-C)/2)*pi/180
x= float(.5 (sin(theta)- cos(theta)))
y= float(.5 (sin(theta)+cos(theta)))
r= float(-theta*180/pi)
print("SQUARE{x ",x," y ",y," r ",r,"}")
r= -r
x= -x
print("SQUARE{x ",x," y ",y," r ",r,"}")
y=float(1/cos(theta))
s=float(1-tan(theta))
print("triC{y",y," s ",s,"}")
print("}")

Re: General acute triangle program

Posted: Sun May 15, 2005 10:46 pm
by mtnviewmark
buckyboy314 wrote: You may want to lower all y factors slightly if you're on a Mac so antialiasing doesn't make lines through the triangle.
This has been fixed in the next release. Abutting squares now have no gaps on all platforms. We spent time tweaking the rendering on each to get it just right.