POV-Ray : Newsgroups : povray.general : Fitting a gothic trefoil into an equilateral triangle Server Time
4 Aug 2024 12:16:56 EDT (-0400)
  Fitting a gothic trefoil into an equilateral triangle (Message 19 to 28 of 28)  
<<< Previous 10 Messages Goto Initial 10 Messages
From: LibraryMan
Subject: Re: Fitting a gothic trefoil into an equilateral triangle
Date: 2 Jul 2003 15:05:01
Message: <web.3f032ba9a1d38d6b738e706a0@news.povray.org>
INVALID_ADDRESS wrote:
>
>Next tasks :)
The trick of omitting the closing "}" of the object created by Ring will
help (look at the end of the Trefoil macro where I used this trick).
>

Yes, that closing "}" really confused me.  I didn't really understand why it
was necessary, especially when I couldn't find the opening "{".
(Did it have anything to do with your commented-out statement about the
closing "}" being omitted for to allow for translations? )
I'd never before noticed any other examples of macro calling with {}'s.
()'s, yes!

I suppose I'd better go study macros some more.  (But then, that's part of
my problem about slow progress:  Every scene component I attempt to add
involves an episode of "that doesn't do AT ALL what I wanted/expected," and
I have to reverse myself and do so much doc-reading (which introduces me to
yet more confusing concepts, spawning yet more tangents..)

--Mark


Post a reply to this message

From:
Subject: Re: Fitting a gothic trefoil into an equilateral triangle
Date: 2 Jul 2003 21:54:10
Message: <3f038cc2$1@news.povray.org>
Hi Mark,

I suggested to clip with a "center cylinder" to get rid of the sharp "inner
spikes", just for aesthetical reasons.


> >   - create your *own* stone texture
>
> jaw drops, mouth goes dry, limbs gradually go numb... ;-)

Why this?
Experiment with some stone textures from stones1.inc and stones2.inc, modify
the colors in the color_map (and convert the color_maps to the new syntax!)
use other wave_types, play around with different patterns, scaling (even and
uneven) and rotation, modify the modifiers. Then finish, normal, layered
textures, ...
A perfect stone texture is difficult, but an acceptable stone texture isn't.


> I went thorough a lot of trouble to get the vault ribbing to look like it
> was composed of individual component pieces

Why "look like"? You could use truly individual components! (Don't forget
the mortar between them!)


Now I reveal: The trick of the missing "}"
Assume you want a macro for a simple ring:

    #macro Ring(Size)
      difference {
        cylinder { -0.05*y, 0.05*y, 0.5 }
        cylinder { -0.051*y, 0.051*y, 0.4 }
        scale Size
        }
      #end//of macro Ring

Now you can use this macro to create a ring at the origin with the default
texture:

    Ring(3)

This is equivalent to the body of the macro with parameter names replaced
by the supplied value, i.e. this represents a complete difference statement.
But if you want to apply a texture, translate it or such, you have to write

    object { Ring(3) texture { MyRingTex } translate <1, 2, 3> }

I prefer to leave out the line with the single "}" in the macro. (It is
legal to have unmatched parentheses in a macro.) Now Ring(3) delivers

    difference {
        cylinder { -0.1*y, 0.1*y, 0.5 }
        cylinder { -0.11*y, 0.11*y, 0.4 }
        scale 3

and you can append whatever is possible with a difference. At the end the
matching "}" for the "difference {" must be supplied. So for example

    Ring(3) texture { MyRingTex } translate <1, 2, 3> }

is the same as

    difference {
        cylinder { -0.1*y, 0.1*y, 0.5 }
        cylinder { -0.11*y, 0.11*y, 0.4 }
        scale 3
        texture { MyRingTex } translate <1, 2, 3> }

In short: the "}" is not supplied in the macro, but in the SDL after the
invocation of the macro.

Don't worry about slow progress: this only means your work is improving
your POV-Ray expertise instead of your scene -- you should be happy
about this!

   Sputnik


Post a reply to this message

From: LinuxLibrarian
Subject: Re: Fitting a gothic trefoil into an equilateral triangle
Date: 6 Jul 2003 18:55:08
Message: <3F08A8D9.4090905@att.net>


> Don't worry about slow progress: this only means your work is improving
> your POV-Ray expertise instead of your scene -- you should be happy
> about this!
> 
>    Sputnik
> 
> 
I look at things like 
http://www.irtc.org/ftp/pub/stills/2003-04-30/mtdomine.jpg
and I just think "never mind, forget it..."

--Mark


Post a reply to this message

From:
Subject: Re: Fitting a gothic trefoil into an equilateral triangle
Date: 6 Jul 2003 22:37:10
Message: <3f08dcd6$1@news.povray.org>
/*
Hi Mark,

did you recognize that the picture of your link has only a small number
of *different* elements? The rest is repetition: a task for POV-Ray's
#while-statement.

> I have thus far a floor, columns & footings, empty windows waiting for
> inspired "glass" (maybe just borrowed images converted to a format that
> will allow me to play with the transparency/translucency).  I also have the
> nave ceiling ribbing and vaulting, piers at the 'crossing', a west wall &
> portal.

Fine -- repeat them, put them together, apply your stone texture, post in
p.b.i, improve after you've read the comments and suggestions, then post
again, ...
If you can't create a complete building, make a ruin! :-))

Here is some inspiration for you: "The power of repetition"
The scene consists almost entirely of repetitions of one simple box!

   Sputnik

*/
//=== BEGIN ==============================================================

// +SP8 +EP8 -A +W800 +H600 -FN
// +SP8 +EP8 +A0.001 +AM2 +R3 +W800 +H600 -FN

#declare oClock = 360/12; // for direction as ... o'clock
#declare PicHeight = 21;
#declare PicWidth = 4/3*PicHeight;
#declare PicDist = 1.5*PicWidth;
#declare Focus = 0;
#declare FocusDist = 2000;
#declare CamDirection = 5*oClock; // horizontal position of cam,
                                  // looking in opposite direction
#declare CamHeight = 33; // degrees
#declare CamRollLeft = 0; // degrees

camera {
  location -FocusDist*z
  right PicWidth/2*x
  up PicHeight/2*y
  sky y
  direction PicDist/2*z
  look_at 0
  rotate CamRollLeft*z
  rotate <CamHeight, CamDirection-180, 0>
  translate Focus
  }

light_source { <-1, 4, -2>*10000, rgb 1 }

#declare VerySimpleStoneTex = texture {
  pigment { granite scale 3 }
  finish { ambient .3 diffuse .7 }
  }

#declare StairWidth   = 300;
#declare StairHeight  =  15;
#declare StairDepth   =  20;
#declare StairOverlap =  10;

#macro Stair ()
  box { 0, <StairDepth+StairOverlap, StairHeight, StairWidth>
    // no "}" for "box {" as usual ...
  #end//macro Stair

#macro Stairs (Steps)
  union {
    #declare Step = 0;
    #while (Step<Steps)
      Stair () translate Step*<StairDepth, StairHeight, 0> }
      #declare Step = Step+1;
      #end//while Step
    texture { VerySimpleStoneTex }
    // "}" for "union {" omitted
  #end//macro Stairs

Stairs (25) rotate -80*y translate <450, 0, -400> }

#declare S = 8;
union {
  Stairs (S) }
  union {
    box { 0, <StairWidth, StairHeight, StairWidth>
      texture { VerySimpleStoneTex }
      }
    Stairs (4)
      rotate 90*y
      translate <0, StairHeight, StairOverlap>
      }
    Stairs (6)
      translate -StairWidth*z
      rotate -90*y
      translate <0, StairHeight, StairWidth-StairOverlap>
      }
    translate S*<StairDepth, StairHeight, 0>
    }
  rotate -130*y
  translate <-150, 0, 100>
  }

#declare S = 5;
union {
  Stairs (S-1) }
  Stairs (S)
    scale <-1, 1, 1>
    translate ((2*S-1)*StairDepth+StairOverlap)*x
    }
  rotate -60*y
  translate <-50, 0, -600>
  }

plane { y, 0
  texture { checker
    texture { VerySimpleStoneTex scale 1/50 },
    texture { pigment { color rgb .8 } finish { ambient .3 diffuse .7 } }
    scale 50
    }
  }


//=== END ================================================================


Post a reply to this message

From: LibraryMan
Subject: Re: Fitting a gothic trefoil into an equilateral triangle
Date: 16 Jul 2003 14:30:01
Message: <web.3f15996aa1d38d6b738e706a0@news.povray.org>
INVALID_ADDRESS wrote:

>
>#macro Stairs (Steps)
>  union {
>    #declare Step = 0;
>    #while (Step<Steps)
>      Stair () translate Step*<StairDepth, StairHeight, 0> }
>      #declare Step = Step+1;
>      #end//while Step
>    texture { VerySimpleStoneTex }
>    // "}" for "union {" omitted
>  #end//macro Stairs
>

(This thread is probably now so old you're ignoring it and may not get this,
unless you sort your news by date or something)

Here's yet another boneheaded question:
In the above macro, the variable "Step" is declared, and given a integer or
float value.  I don't understand at what point it could ever change its
value to "Steps," which is a string.  Just to be sure, I parsed through the
message looking for buried occurrences of "Steps," in case I missed where
you may have put something like
#declare Steps = Some number greater than 0

Excuse my cranial density...


Post a reply to this message

From:
Subject: Re: Fitting a gothic trefoil into an equilateral triangle
Date: 17 Jul 2003 21:25:36
Message: <3f174c90$1@news.povray.org>
Hi Mark!

(This thread isn't old: my last post is only 10 days ago! For me "old"
means "months ago" if it's a thread I've started or replied to.)

Steps is neither a string nor a "normal" variable: it is a macro parameter.
When POV-Ray sees, for example,

   Stairs (4) /* some transformations */ }

then Stairs is recognized as the name of a macro because it was defined by

   #macro Stairs (Steps)
     // rest of macro skipped here

This tells POV-Ray to create a new variable named Steps which is local
to the macro (i.e. destroyed at exit of the macro) and to store the
parameter value (in this example 4) in it. The effect is the same as
if the line

   #local Steps = 4;

were executed at entry into the macro. Now the loop

   #declare Step = 0;
   #while (Step<Steps)
     Stair () translate Step*<StairDepth, StairHeight, 0> }
     #declare Step = Step+1;
     #end//while Step

starts with Step=0, which is <Steps (=4 here), so makes a Stair,
increments Step to 1, this is <Steps, so makes another Stair,
increments Step to 2, this is <Steps, so makes another Stair,
increments Step to 3, this is <Steps, so makes another Stair,
increments Step to 4, this is  not <Steps, so exits.

At the next invocation of Stairs the old value of Steps is forgotten;
a new Steps variable is created containing the new parameter value.

More generally, a macro defined by, for example,

   #macro MyMacro (A_Number, A_String, An_Object)
     // ...
     #end

and invoked by

   MyMacro ( 42, "Whoa!", sphere { <1,2,3>, 4 } )

will create new variables

   A_Number with value 42
   A_String with value "Whoa!"
   An_Object with value sphere { <1,2,3>, 4 }

as if

   #local A_Number = 42;
   #local A_String = "Whoa!"
   #local An_Object= sphere { <1,2,3>, 4 }

were executed, then the macro body (everything between
"#macro MyMacro (A_Number, A_String, An_Object)" and the "#end" that
belongs to #macro, indicated by "// ..." above) will be parsed by POV-Ray,
then the local variables A_Number, A_String, An_Object are destroyed, and
parsing continues after the invocation. A macro without parameters is
sort of "copy and paste" operation (like my Stair()-macro which simply
delivers a box). Parameters allow introduction of varying elements
(everything that is allowed on the right side of the "=" of a #local
statement is allowed as parameter).


<ADVANCED STUFF>

The macro body may even modify the parameters, and when a macro invocation
gives a single declared (or "#local"ed) variable (not an expression) as
parameter value, then this variable gets the value of its associated local
parameter variable at exit of the macro. If for example the above macro is
invoked as

   MyMacro (MyNumber, MyString, MyObject)

then the variables MyNumber, MyString, MyObject reflect the values of
A_Number, A_String, An_Object just before exit of the macro as if

   #declare MyNumber = A_Number;
   #declare MyString = A_String
   #declare MyObject = An_Object

were executed just before exit of the macro.

A simple example:

   #macro Add (Value, Sum)
     #local Sum = Sum+Value;
     #end

   #declare Result = 0; // start with 0 as current value of Result
   Add (5, Result) // add 5 to the current value of Result, giving 5
   Add (7, Result) // add 7 to the current value of Result, giving 12
   Add (3, Result) // add 3 to the current value of Result, giving 15

   #debug str(Result, 5, 0) // output Result to message window
   #debug "\n" // start a new line in message window

The invocation "Add (5, Result)" is replaced by POV-Ray by

   #local Value = 5; // get first parameter, store it in local variable
   #local Sum = Result; // get second parameter, store it in local variable

   #local Sum = Sum+Value; // body of macro, uses the local variables
                           // associated to the parameters

   #declare Result = Sum; // return the value of the second parameter's
                        // local variable to the variable given for
                        // this second parameter

   // The first parameter "5" is not a variable, so nothing is returned
   // ( "#declare 5 = Value;" is nonsense )

   #undef Value // the local variable Value is destroyed
   #undef Sum // the local variable Sum is destroyed

In short: 5 is used for Value, Result is used for Sum. 5 can't get a new
value, but Result can.
Similar with the other invocations.
Of course,

   #declare A_different_Result = 1762345;
   Add (76235, A_different_Result)
   Add (87656, A_different_Result)

also is possible, even intermixed with the above invocations of Add,
because Add is "told" which variable to use.

<END OF ADVANCED STUFF>


I hope this helps in understanding my macros (and macros in general).
You might want to read "6.2.8  User Defined Macros" for more information
(or ask again!).

   Sputnik


P.S. Why did you think Steps is a string?

P.P.S. You meant   "Steps"  , not   "Steps,"  , didn't you?

P.P.P.S. String comparison is not possible with "<" etc., look for
         strcmp in "6.1.3.6  Float Functions".


Post a reply to this message

From: LibraryMan
Subject: Re: Fitting a gothic trefoil into an equilateral triangle
Date: 19 Jul 2003 11:40:02
Message: <web.3f196555a1d38d6b738e706a0@news.povray.org>
INVALID_ADDRESS wrote:

>
>P.S. Why did you think Steps is a string?\

I guess I thought all variable identifiers *had* to be strings.

>
>P.P.S. You meant   "Steps"  , not   "Steps,"  , didn't you?

Probably.  I no longer remember what I wrote!

I understand the logic of all you explained -- it helped me to re-examine
your code.  THEN,
I finally realized, as the cranial density began to lessen, that "Steps"
didn't *have* to have a value pre-assigned to it *until the macro was
actually called*.
As I looked farther down your code, I saw:
Stairs (S) (after S was declared to = 8)
then
Stairs (4), then
Stairs (8)

At that point the fog { } began to lift. :-)  THanks!
--Mark

P. S. You're a very patient person.  Are you a teacher, by any chance?
Perhaps you should be!


Post a reply to this message

From:
Subject: Re: Fitting a gothic trefoil into an equilateral triangle
Date: 22 Jul 2003 22:54:26
Message: <3f1df8e2$1@news.povray.org>
> Are you a teacher, by any chance?

Formally: No. In practice: Yes, sometimes.
I'm working for a computer museum (actually only a collection);
currently only sort of hobby, presenting old computers and explaining
the principles of their operation. A glimpse at a small fraction of
this collection (text currently only in german):
http://www.computermuseum.fh-kiel.de/images/medium_zuse_rundblick.jpg
http://www.computermuseum.fh-kiel.de/besichtigungen/info.htm

> Perhaps you should be!
I am! Look at "Fitting a gothic trefoil into an equilateral triangle"
in povray.general! :-D

   Sputnik


Post a reply to this message

From: David Wallace
Subject: Re: Fitting a gothic trefoil into an equilateral triangle
Date: 2 Aug 2003 08:53:47
Message: <3f2bb45b@news.povray.org>

news:3ef793d2$1@news.povray.org...
> Hi Mark,
>
> here is "The Making of '#macro Trefoil'"; names starting with an
> uppercase letter refer to variables in the code of my last post.
>
> (don't underestimate the importance of the first two of the following
> points!)
>
>
> 1. Find out the given and wanted elements (lengths, angles, ...)
>    and choose descriptive names for them
>
> You asked for inscribing circles into an equilateral triangle, so all
> of its angles are 60 degrees. The length of its sides is given; this
> length got the name 'Side'. Obviously the triangle is to be erected
> over a horizontal line, so it has a top corner ('Corner1'), a bottom
> left corner ('Corner2') and a bottom right corner ('Corner3').
> Because the problem has an infinite number of solutions, I decided
> to use the radius 'Radius' of the circles as independent variable
> and to calculate their midpoints 'Center1', ... , 'Center3'.
>
>
> 2. Choose a coordinate system
>
> Usually the math is easier when many coordinates are 0 or 1: multiplying
> by 1 is trivial, by 0 even more; adding of 0 is trivial; squaring 0 or 1
> is the same as doing nothing; and so on.
> If there is a mirror symmetry with respect to a line/point, then very
often
> (but not always) this line/point is well suited as coordinate axis/origin.
> Sometimes it is easier to solve a standard problem and then transform
> it to the required proportions; for example (in POV style): instead
> of sphere{C,R ... } use sphere{0,1 ... scale R translate C}.
>
> The trefoil is a problem in plane geometry, so I only use x- and y-
> coordinates and set all z=0 (I will leave them out here, but had written
> these zeros in the code).
> Because circles are to be put into the *corners* of the outer triangle,
> I decided to use a corner (Corner2) as origin, so
>    Corner2=<0,0>
> Corner3 sits on the x-axis, so
>    Corner3=<Side,0>.
>
>
> 3. Make a drawing of the geometric situation
>
> In most cases, an approximate scetch without large obvious errors will
> suffice. Use thick lines for every known element. Don't believe everything
> you see! The drawing can't prove anything, its sole purpose is to trigger
> the intuition and to keep track of the known and the not-yet-known
> elements. Do this even for very simple situations.
> (Please do this *now* to make it easy to follow the following
explanations!)
>
>
> 4. Look for properties that allow application of geometric theorems
>
> Very often symmetries, right angles, congruent triangles and parallels
> are the key for a solution. If you have none, create them by erecting
> perpendiculars, drawing parallels etc.
> This is the inspiration part of the solution of geometric problems.
>
>
> 5. Find out relevant elements (coordinates, lengths, angles, ...) until
all
>    wanted elements are known
>
> This is the transpiration part of the solution of geometric problems.
>
> [ top corner ]
> The first step in the trefoil problem is to find the top corner. Due to
> the triangle's mirror symmetry with respect to the perpendicular from
> the top corner,
>    Corner1.x=Side/2.
> The y-coordinate is the Height of the triangle, found by the law of
> pythagoras in the right-angled triangle
>    top point -- bottom left point -- midpoint of base line
> so we get
>    Height^2 + (Side/2)^2 = Side^2
> Solving for Height gives
>    Height = sqrt( Side^2 + Side^2/4 ) = sqrt(3)/2*Side
>
> [ centers ]
> Now look at the midpoint 'Center2' of a circle touching the sides
> emanating from Corner2. Due to symmetry of this circle and the triangle
> with respect to the line through Corner2 and Center2, the angle between
> this line and the x-axis is 30 degrees (60/2). Now imagine a new point:
> the mirror image 'M' of Center1 with respect to the x-axis. The triangle
>    Corner2 -- Center1 -- M
> has 30+30 degrees at Corner1 (x-axis symmetry), its other two angles are
> equal (same symmetry). So all angles are 60 degrees, i.e. this triangle
> is equilateral. The vertical side obviously has a length=2*Radius, and
> because of the equilaterality, the other sides have the same length. The
> part of the x-axis within this triangle is a height of this triangle, and
> as seen above with the outer triangle, height=sqrt(3)/2*length_of_side.
> But this height of the small triangle is the x-coordinate of Center2!
> So we have
>    Center2.x = sqrt(3)/2 * 2*Radius = sqrt(3)*Radius
> and obviously
>    Center2.y = Radius
> By symmetry with respect to the perpendicular from the top corner onto
> the x-axis:
>    Center3.x = Side - sqrt(3)*Radius
>    Center3.y = Radius
> As seen above,
>    distance between Center2 and Corner2
>    = length_of_side of the small triangle
>    = 2*Radius
> Because the three circles are equal,
>    distance between Center1 and Corner1 = 2*Radius
> I.e. Center1 is 2*Radius below Corner1, so we get
>    Center1 = <Side/2, Height-2*Radius>
>
> [ maximal Radius, minimal Radius ]
> Because all triangles should lie completely inside the outer triangle,
> the maximal Radius is the radius of the incircle. Then (symmetry!)
>    center2_for_max_Radius.x = Side/2
> Above we found
>    Center2.x = sqrt(3)*Radius
> For the maximal circle we get
>    center2_for_max_Radius.x = sqrt(3)*max_radius
> So
>    Side/2 = sqrt(3)*max_radius
> i.e.
>    max_Radius = Side/2/sqrt(3) = Side * sqrt(3)/6
> The minimal Radius obviously is zero, so all values in the range
>    0 .. Side*sqrt(3)/6
> are possible radii.
>
> [ Radius of mutually touching circles ]
> The circles are touching when the distance of their centers = 2*Radius.
> The situation is easily analyzed by looking at Center2 and Center3:
>    Center3.x - Center2.x = 2*touch_Radius [y-coordinates are equal!]
> The coordinates of these centers are known:
>    Side-sqrt(3)*touch_Radius - sqrt(3)*touch_Radius = 2*touch_Radius
> A little calculation solves this for touch_Radius:
>    Side = (2*sqrt(3)-2) * touch_Radius
>    touch_Radius = Side / (2*sqrt(3)-2) [now expand by (2*sqrt(3)+2):]
>    = Side * (sqrt(3)-1)/4
>
> [ center of triangle ]
> This point isn't needed for the problem, but I suggest to calculate
> almost everything you can: it often gives deeper insight in the
> problem, reveals unexpected relations and simplifies other steps.
> In the trefoil problem, it helps finding the "true gothic" Radius.
> Again because of symmetry,
>    Center.x = Side/2
> The bisectors of a triangle (which in this case also are angular
> bisectors and heights) intersect in its center of gravity and
> are divided by this point in a 2:1 ratio. This gives us
>    Center.y = Height/3
>
> [ "true gothic" Radius ]
> In a "true gothic" situation, all circles meet at the Center, so
> their distance from this Center = Radius. In this case, the situation
> at the top is most easy:
>    gothic_Center1.y - Center.y = gothic_Radius [x-coordinates are equal!]
> Because
>    Center1.y = Height-2*Radius
> we have the special case
>    gothic_Center1.y = Height-2*gothic_Radius =
sqrt(3)/2*Side-2*gothic_Radius
> We already found in the previous section
>    Center.y = Height/3 = sqrt(3)/6*Side
> Putting all this together and solving for gothic_Radius, we find
>    sqrt(3)/2*Side-2*gothic_Radius - sqrt(3)/6*Side = gothic_Radius
>    sqrt(3)/3*Side = 3*gothic_Radius
>    gothic_Radius = sqrt(3)/9*Side
>
>
> 6. During the paragraph 5 implement everything at once in POV-Ray
>
> This will reveal calculation errors and gives an exact drawing of the
> situation reached so far. And it's fun!
>
>
> .....
>
> I don't know your mathematical background, so maybe this was a little bit
> lengthy, but I hope this explanation will contribute to your ability to
> successfully attack similar (and more complex) problems.
>
>    Sputnik
>
>
> --
> ----------------------------

> fr### [at] computermuseumfh-kielde
> ----------------------------
>
>
I didn't get to see the original post, so I'm not sure what a gothic trefoil
is.  If you are looking for incircles, however:

#macro LineIntersect(p1, d1, p2, d2)
 #local pSep = p2-p1;
 #local pdCross = vcross(d1,d2);
 #local pdLen = vlength(pdCross);
 #local lDist = vdot(pSep,pdCross);
 #local dist = vdot(vcross(pSep,d2),pdCross)/(pdLen*pdLen);
 #local pnt = p1+d1*dist;
 pnt
#end

#macro TriangleNorm(p1, p2, p3)
 #local nrm = vnormalize(vcross(p2-p1,p3-p1));
 nrm
#end

#macro icRad(p1, p2, p3) // Inscribed circle radius
 #local ln1 = vlength(p2-p1);
 #local ln2 = vlength(p3-p1);
 #local ln3 = vlength(p3-p2);
 #local hPer = (ln1+ln2+ln3)*0.5;
 #local area = sqrt(hPer*(hPer-ln1)*(hPer-ln2)*(hPer-ln3));
 #declare rad = area/hPer;
 rad
#end

#macro icCen(p1, p2, p3) // Inscribed circle center
 #local dr1 = vnormalize(p3-p2);
 #local dr2 = vnormalize(p3-p1);
 #local dr3 = vnormalize(p2-p1);
 #local drb1 = vnormalize(-dr2-dr3); // Bisects angle through p1
 #local drb2 = vnormalize(dr3-dr1); // Bisects angle through p2
 #declare cen = LineIntersect(p1, drb1, p2, drb2);
 cen
#end

#macro ccRad(p1, p2, p3) // Circumscribed circle radius
 #local ln1 = vlength(p2-p1);
 #local ln2 = vlength(p3-p1);
 #local ln3 = vlength(p3-p2);
 #local hPer = (ln1+ln2+ln3)*0.5;
 #local area = sqrt(hPer*(hPer-ln1)*(hPer-ln2)*(hPer-ln3));
 #declare rad = ln1*ln2*ln3*0.25/area;
 rad
#end

#macro ccCen(p1, p2, p3) // Circumscribed circle center
 #local pNrm = TriangleNorm(p1, p2, p3); // Unit triangle plane normal
 #local mp1 = (p2+p3)*.5; // Midpoint of line opposite p1
 #local mp2 = (p1+p3)*.5; // Midpoint of line opposite p2
 #local dr1 = vnormalize(vcross(p3-p2,pNrm));  // Perpendicular to line opp.
p1
 #local dr2 = vnormalize(vcross(p3-p1,pNrm));  // Perpendicular to line opp.
p2
 #declare cen = LineIntersect(mp1, dr1, mp2, dr2);
 cen
#end

#macro Pythag(a,b)
 #local py = sqrt(a*a+b*b);
 py
#end

#macro odfRing(pos, nrm, rad, wid, thk) difference {
 cylinder { -nrm*wid, nrm*wid, rad }
 cylinder { -nrm*wid*2, nrm*wid*2, rad-thk }
 translate pos
} #end

#declare odfbSizIn = 2.85;
#declare odfbSizOut = 3.15;
#declare odfbSizEdge = 0.5*(odfbSizOut-odfbSizIn);
#declare odfbWid = 0.030;
#declare odfbWid2 = odfbWid*0.75;
#declare odfbThk = 0.01;

#declare odfbFrame = union {
 difference {
  box { <0, -odfbSizIn-odfbThk,-odfbWid>, <odfbSizIn+odfbThk, 0, odfbWid> }
  box { <odfbThk, -odfbSizIn,-odfbWid*2>, <odfbSizIn,-odfbThk, odfbWid*2> }
 }
 box { <0, -odfbSizOut-odfbThk,-odfbWid>, <odfbSizOut, -odfbSizOut,
odfbWid> }
 matrix <1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0>
  clipped_by { plane { y, 0 } }
}

// Primary incircle
#declare odfiP1 = < odfbThk,-odfbThk, 0>;
#declare odfiP2 = < odfbSizIn,-odfbThk, 0>;
#declare odfiP3 = < odfbThk,-odfbSizIn, 0>;
#declare odfiNrm = TriangleNorm( odfiP1, odfiP2, odfiP3 );
#declare odfiRad0 = icRad( odfiP1, odfiP2, odfiP3 );
#declare odfiRad0a = odfiRad0+odfbThk;
#declare odfiCen0 = icCen( odfiP1, odfiP2, odfiP3 );
#declare odfiRing0 = odfRing(odfiCen0, odfiNrm, odfiRad0+odfbThk, odfbWid2,
odfbThk)

// Secondary incircle at p1
#declare odfiDr1 = vnormalize(odfiP1-odfiCen0);
#declare odfiP1a = odfiCen0+odfiRad0a*odfiDr1;
#declare odfiDr1p = vnormalize(vcross(odfiDr1, odfiNrm));
#declare odfiP12 = LineIntersect(odfiP1a, odfiDr1p, odfiP1, odfiP2-odfiP1);
#declare odfiP13 = LineIntersect(odfiP1a, odfiDr1p, odfiP1, odfiP3-odfiP1);
#declare odfiRad1 = icRad( odfiP1, odfiP12, odfiP13 );
#declare odfiCen1 = icCen( odfiP1, odfiP12, odfiP13 );
#declare odfiRing1 = odfRing(odfiCen1, odfiNrm, odfiRad1+odfbThk, odfbWid*4,
odfbThk)

// Secondary incircle at p2
#declare odfiDr2 = vnormalize(odfiP2-odfiCen0);
#declare odfiP2a = odfiCen0+odfiRad0a*odfiDr2;
#declare odfiDr2p = vnormalize(vcross(odfiDr2, odfiNrm));
#declare odfiP21 = LineIntersect(odfiP2a, odfiDr2p, odfiP2, odfiP1-odfiP2);
#declare odfiP23 = LineIntersect(odfiP2a, odfiDr2p, odfiP2, odfiP3-odfiP2);
#declare odfiRad2 = icRad( odfiP2, odfiP21, odfiP23 );
#declare odfiCen2 = icCen( odfiP2, odfiP21, odfiP23 );
#declare odfiRing2 = odfRing(odfiCen2, odfiNrm, odfiRad2+odfbThk, odfbWid2,
odfbThk)

// Secondary incircle at p3
#declare odfiDr3 = vnormalize(odfiP3-odfiCen0);
#declare odfiP3a = odfiCen0+odfiRad0a*odfiDr3;
#declare odfiDr3p = vnormalize(vcross(odfiDr3, odfiNrm));
#declare odfiP31 = LineIntersect(odfiP3a, odfiDr3p, odfiP3, odfiP1-odfiP3);
#declare odfiP32 = LineIntersect(odfiP3a, odfiDr3p, odfiP3, odfiP2-odfiP3);
#declare odfiRad3 = icRad( odfiP3, odfiP31, odfiP32 );
#declare odfiCen3 = icCen( odfiP3, odfiP31, odfiP32 );
#declare odfiRing3 = odfRing(odfiCen3, odfiNrm, odfiRad3+odfbThk, odfbWid2,
odfbThk)

#declare odfbRingPos = 0.5*(odfbSizIn+odfbSizOut);
#declare odfrRad = odfbSizEdge*sqrt(0.5);
#declare odfbRadEdge = odfrRad*1.10;
#declare odfrDist = odfbSizEdge-odfbThk*.5;
#declare odfrStep = <odfrDist,odfrDist,0>;
#declare odfrNum = int(odfbRingPos/odfrDist)-1;
#declare odfrOrig = (<odfbRingPos,-odfbRingPos,0>-odfrStep*(odfrNum-1))*0.5;

#declare odfbMiniRing = odfRing(0, odfiNrm, odfrRad, odfbWid2, odfbThk)


#declare odfbEdge = union {
 difference {
  cylinder { -z*odfbWid, z*odfbWid, odfbRadEdge }
  cylinder { -z*odfbWid*2, z*odfbWid*2, odfbRadEdge-odfbThk }
  plane { x, 0 }
  translate y*(odfbSizEdge-odfbRadEdge)
 }
 box { <0,-odfbSizEdge,-odfbWid>, <odfbThk,
odfbSizEdge+odfbThk-odfbRadEdge*2, odfbWid> }
}

#declare odfBrace = union {
 object { odfbFrame }
 object { odfbEdge translate -y*odfbRingPos }
 object { odfbEdge rotate -z*90 rotate y*180 translate x*odfbRingPos }
 object { odfiRing0 }
 object { odfiRing1 }
 object { odfiRing2 }
 object { odfiRing3 }
 box { < 0.00,-odfbThk,-odfbWid>, < odfbSizIn+odfbThk, 0.00, odfbWid> }
 ObjLine( odfbMiniRing, odfrOrig, odfrStep, odfrNum )
 texture { colWLamp }
}


Post a reply to this message

From:
Subject: Re: Fitting a gothic trefoil into an equilateral triangle
Date: 3 Aug 2003 19:14:41
Message: <3f2d9761$1@news.povray.org>
Hi David,

a gothic trefoil is basically an equilateral triangle with circles
inscribed into the corners that meet in the triangle's midpoint.
Mark (aka LibraryMan aka LinuxLibrarian) asked for the construction
of these circles (thread started 12 June 2003). I described this
to him, so *I* know about incircles and all the other stuff :-)

In your macros you always create a variable to return the result --
this is not neccessary, simply return the expression that gives
the result. Enclose this expression in parentheses if neccessary
to avoid unwanted precedences. For example your

  #macro Pythag(a,b)
   #local py = sqrt(a*a+b*b);
   py
   #end

might be rewritten as

  #macro Pythag(a,b)
    sqrt(a*a+b*b)
    #end

Here parentheses are required:

  #macro Successor(N)
    (N+1)
    #end

else the expression 2*Successor(N) would result in 2*N+1 which is
interpreted as (2*N)+1 due to the priority of * over +.

Using all-lowercase identifiers is a bit dangerous. If you want
"future-proof" macros, no such variables should be used to avoid
conflicts with current or future keywords and with keywords of
unofficial versions of POV-Ray.

   Sputnik


Post a reply to this message

<<< Previous 10 Messages Goto Initial 10 Messages

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.