POV-Ray : Newsgroups : povray.binaries.images : True catenary : True catenary Server Time
5 Nov 2024 12:36:57 EST (-0500)
  True catenary  
From: PM 2Ring
Date: 1 Aug 2005 06:15:01
Message: <web.42edf3bf208413009143b5c90@news.povray.org>
The catenary is the curve formed by a homogeneous chain suspended between
two points in a uniform gravity field. It looks like a parabola, but it's
mathematically quite different. The equation of a parabola is just
 y = a*x*x, a simple quadratic, whereas a catenary is
 y = a*cosh(x/a), a transcendental equation.

I had occasion to look at Chris Colefax's chain building code in "Linc.inc",
after referring a new user to it, and was dismayed to discover that Chris
used quadratics to build his chains. :(

The Chain() macro below constructs a true catenary. This is a preliminary
draft, so there are no docs as yet, sorry. Read the comments for hints. :)

Any questions and comments are most welcome. Have fun!

//-------------------------------------------------------------------------

// Persistence of Vision Ray Tracer Include File
// File: Catenary.inc
// Vers: 3.6
// Desc: Proper catenary chain.
// Date: 2005.07.30
// Auth: PM 2Ring
//
// Catenary parameter calculations thanks to Zdislav V. Kovarik. See below
//
//-------------------------------------------------------------------------

#ifndef(Catenary_Inc_Temp)
#declare Catenary_Inc_Temp=version;
#version 3.5;

#ifdef(View_POV_Include_Stack)
    #debug "including Catenary.incn"
#end

//-------------------------------------------------------------------------
//
// From: kov### [at] mcmailcisMcMasterCA (Zdislav V. Kovarik)
// Subject: Re: Catenary
// Date: 5 Nov 1999 14:33:22 -0500
// Newsgroups: sci.math
// Keywords: fitting a catenary to match a suspended cable
//
// Upright catenary:  y - y_0 = a * cosh((x - x_0)/a) ,  a > 0.
// The vertex is (x_0, y_0+a).
// The parameter a turns out to be the radius of curvature at the vertex.
// Remark: The radius of curvature at a point above x is
//   a * (cosh((x-x_0)/a)^2.
//
// Problem: Parameters a, x_0, y_0 to be found so that the catenary arc
passes
// through (x_1, y_1), (x_2, y_2) and has length L between these points
// (provided L > sqrt((x_2 - x_1)^2 + (y_2 - y_1)^2) )
//
// The equations to be solved are (after some symmetrizing manipulation
// of the arclength integral)
//
//   y_1 - y_0 = a * cosh ((x_1 - x_0)/a)
//   y_2 - y_0 = a * cosh ((x_2 - x_0)/a)
//   2*a * cosh((x_1 + x_2 - 2*x_0)/(2*a)) * sinh((x_2 - x_1)/(2*a)) = L
//
// and it can be reduced to solving for one unknown at a time.
//
// First, we introduce an auxiliary unknown z which is to satisfy
//
//   sinh(z) / z = sqrt(L^2 - (y_2 - y_1)^2) / abs(x_2 - x_1)  ,   z > 0
//
// (the only transcendental non-elementary equation)
// and then the unknowns pop out:
//
//     a = abs(x_2 - x_1) / (2*z)
//   x_0 = (1/2)*(x_1 + x_2 - a * ln ((L + (y_2 - y_1)) / (L - (y_2 - y_1)))
//   y_0 =  (y_1 + y_2)/2 - (L/2) * coth(z).
//
//-------------------------------------------------------------------------

//Find B such that A=sinh(B)/B. Named in parallel to sinc()
#macro asinch(A)
  #local B = sqrt(6*max(1e-4,A-1));   //1st approx, from sinh(B) = B +
B^3/3! + ...
  #local B = asinh(A*B);              //2nd approx, from sinh(B) = A*B

  #local I = 0;
  #while(I<8)                         //Newton's method
    #local S = sinh(B);
    #local C = B * cosh(B);
    #local M = (A*B + C - 2*S) / (C - S);
    #local B = B * M;
    #local I = I + 1;
    #if(abs(M-1)<1e-12)               //bailout
      #local I=8;
    #end
  #end
  B                                   //return value
#end

//Find width of an object's bounding box
#macro BBWidth(A) (max_extent(A) - min_extent(A)).x #end

//Make a catenary. Parameters: Link object, Start point,End Point,
//Slackness of the chain >1, Link overlap, Extra twist on whole cable
#macro Chain(Link, StartA, EndA, Slack, Overlap, Twist)
  //Temporarily translate to origin & work in XY plane
  #local End = EndA - StartA;
  #local TH = degrees(atan2(End.z, End.x));
  #local End = vrotate(End, y*TH);              //Rotate to positive x-axis

  //Find required chain length and number of links
  #local Len = vlength(End) * Slack;            //Basic chain length
  #local LL = BBWidth(Link) / Overlap;          //Link Length adjusted for
link overlap
  #local Steps = 2*floor(.5*(.5+Len/LL));       //Round up to an even
integer number of links
  #local Len = Steps * LL;                      //Adjusted chain length

  //Find vertex of catenary that connects <0,0,0> & End, with length Len.
  #local P = sqrt(Len*Len - End.y*End.y) / End.x;
  #local Q = asinch(P);
  #local A = End.x / (2*Q);                     //Catenary curvature
parameter.
  #local X = A * ln((Len + End.y) / (Len - End.y));
  #local Y = Len/tanh(Q);
  #local V = (End - <X, Y, 0>)*.5;              //Vertex
  #local S1 = A*sinh(V.x/A);                    //Arclength at vertex

  //Step evenly along catenary parametrized by arclength.
  union {
    #local I=1;
    #while (I<Steps)
      #local S = LL * I - S1;                   //Arclength from Vertex
      #local M = S / A;                         //Slope of tangent
      #local X = asinh(M);
      #local Y = sqrt(1 + M*M);

      object{
        Link
        rotate (90*mod(I+1,2) + Twist*360*(I-1)/(Steps-2))*x
        rotate z*degrees(atan(M))               //Rotate parallel to tangent
        translate V + A*<X, Y, 0>
      }
      #local I=I+1;
    #end

    //Transform back
    rotate -y*TH
    translate StartA
  }
#end

#version Catenary_Inc_Temp;
#end

//-------------------------------------------------------------------------



//-------------------------------------------------------------------------

// Persistence of Vision Ray Tracer Scene Description File
// File: Catenary.pov
// Vers: 3.6
// Desc: Test Catenary include file
// Date: 2005.07.30
// Auth: PM 2Ring
//
// Catenary parameter calculations thanks to Zdislav V. Kovarik
// See Catenary.inc for details.
//
//-------------------------------------------------------------------------
//
// -f -A0.4 +AM2 +R1
// -d +A0.05 +AM2 +R3
//

#include "finish.inc"
#include "metals.inc"

//Chain making macro
#include "Catenary.inc"

global_settings {
  assumed_gamma 1.0
  max_trace_level 25
}

//-------------------------------------------------------------------------

//Simple chain macro. Parameters: Start point,End Point. Make sure other
items are declared before calling!
#macro ChainQ(Start, End) Chain(Link, Start, End, Slack, Overlap, Twist)
#end

//Chain terminal post
#macro Terminal(Pos)
union{
  sphere{Pos, PostRad*1.6}
  cylinder{Pos*<1,0,1>, Pos-0.35*PostRad*y, PostRad}

  pigment{rgb <.2, .5, 1>}
  finish{Glossy}
}
#end

//Chain, with terminal at start
#macro TermChain(Start, End)
  Terminal(Start)
  ChainQ(Start, End)
#end

//Link objects
#declare Torus = torus {.75, .175 scale 0.075*<1, 1, .65> }
#declare Torus1 = object {Torus scale 2 texture{T_Gold_2E} rotate 0*45*x}

//--- The scene -----------------------------------------------------------

#declare Rad = 2.0;               //Scene size control
#declare PostRad= 0.150;          //Post radius

//Chain parameters
#declare Link = Torus1;           //Link object
#declare Slack = 1.12;            //Slackness of the chain. (Length of
chain) / (straight distance between points)
#declare Overlap = 1.65;          //Link overlap
#declare Twist = 0;               //Chain twist (in cycles)

//Points to connect
#declare V1 = < 1.5*Rad, 0.75*Rad, 1>;
#declare V2 = <-1.5*Rad, 1.25*Rad, 3>;

//Do it!
TermChain(V1, V2)
Terminal(V2)

//Simple room with checkered floor
#declare WS = 5*Rad;
box{<-1, -2/WS, -2>, <1, 3, 2> scale WS inverse pigment{gradient y scale
3.001*WS}finish{Shiny}}
box{<-1, -1/WS, -2>, <1, 0, 2> scale WS pigment{checker rgb 1,rgb
....05}finish{Glossy diffuse 0.80}}

camera {
  location <-0.5, 3.5, -5.5> * 0.93 * Rad
  look_at  y*2

  right x*image_width/image_height up y
  direction z

  angle 30
}

light_source {<1, 9, -3>*Rad rgb 1 spotlight point_at z*2 falloff 16 radius
5 }

//-------------------------------------------------------------------------


Post a reply to this message


Attachments:
Download 'catenaryf2.jpg' (100 KB)

Preview of image 'catenaryf2.jpg'
catenaryf2.jpg


 

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