POV-Ray : Newsgroups : povray.general : Fitting a gothic trefoil into an equilateral triangle : Re: Fitting a gothic trefoil into an equilateral triangle Server Time
4 Aug 2024 14:23:07 EDT (-0400)
  Re: Fitting a gothic trefoil into an equilateral triangle  
From: David Wallace
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

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