POV-Ray : Newsgroups : povray.programming : "Clean" debugging : Re: "Clean" debugging Server Time
7 Nov 2025 13:38:15 EST (-0500)
  Re: "Clean" debugging  
From: Bald Eagle
Date: 30 Oct 2025 22:25:00
Message: <web.69041d9546e6a89d1f9dae3025979125@news.povray.org>
Worked it out by hand.
Tested.
Works for all but the edge cases where X and Z are 0.
Fair notice: There's a weird hack or two in there.

:)

#declare MA_Deg2Vector_RA_Offset = 180;
// Forward: (RA, Dec, Radius) -> <x, y, z>


#local E = 1E-6;

#macro Sign (N)
 select (N, -1, 0, 1)
#end

#macro MA_Deg2Vector (S_RA, S_Dec, S_Radius)
 #local S_RA = S_RA + MA_Deg2Vector_RA_Offset;
 #local S_Rect = radians(S_RA);

 #local S_Dec = S_Dec + 180;
 #local S_DecRad = radians(S_Dec);
 #local S_DecRad = S_DecRad/2;

 #local S_X = S_Radius * sin(S_DecRad) * cos(S_Rect);
 #local S_Y = S_Radius * cos(S_DecRad);
 #local S_Z = S_Radius * sin(S_DecRad) * sin(S_Rect);

 #local V_Out = <S_X, -S_Y, S_Z>;
 V_Out
#end

#macro MA_Vector2Deg (V_In)
 // Undo the original Y inversion
 #local S_X =  V_In.x;
 #local S_Y = -V_In.y;
 #local S_Z =  V_In.z;



 #local Radius = sqrt(S_X*S_X + S_Y*S_Y + S_Z*S_Z);

 // Handle the degenerate zero-length vector
 #if (Radius < 1e-12)
  #local Result = <0, 0, 0>;
 #else


 //#if (abs(S_Z) < E) S_Z = 0 #end

  #local PreDecRad = S_Y / Radius;

  // Clamp for numeric safety
  #local PreDecRad = max (min (PreDecRad, 1), -1);

  #local DecRad1 = acos (PreDecRad);
  #local DecRad = DecRad1 * 2;
  #local Dec = degrees (DecRad);
  #local Dec = Dec - 180;

  // Try to fix edge cases
  //====================================================
  #if (abs(S_X) < E)
   #local FF = E;
   #local S_X2 = FF*Sign(S_X);
   #local S_Y2 = S_Y + FF*Sign(S_X);
   #local S_Z2 = FF*Sign(S_X);
   #local PreDecRad = S_Y2 / Radius;
   #local PreDecRad = max (min (PreDecRad, 1), -1);
   #local DecRad1 = acos (PreDecRad);
  #else
   #local S_X2 = S_X;
   #local S_Y2 = S_Y;
   #local S_Z2 = S_Z;
  #end
  //====================================================

  #local SinDecRad1 = sin (DecRad1);


  #if (abs(SinDecRad1) < E)
   #local SinDecRad1 = 1;
  #end

  #local PreRect = S_Z2 / (Radius * SinDecRad1);
  #local PreRect = max (min (PreRect, 1), -1);
  #local Rect = asin (PreRect);
  #local RectDeg = degrees (Rect);
  #local RA = RectDeg - MA_Deg2Vector_RA_Offset;

  #if (abs(RA) < E) #local RA = 0; #end

  #while (RA < 0)
   #local RA = RA + 180;
  #end

  #if (S_X <= 0 & S_Z >=0)
   #local RA = 360 - RA;
  #end

  #if (S_X > 0  & S_Z >=0)
   #local RA = RA + 180;
  #end

  #if (S_X <= 0 & S_Z <=0)
   #local RA = 180 - RA;
  #end

  #if (S_X < 0 & S_Z =0)
   #local RA = 180 + RA;
  #end

  #local Result = <RA, Dec, Radius>;
 #end
 Result
#end


// Example round-trip test

#for (RA, 0, 360, 10)
 #for (Dec, -180, 180, 18)
  #local  V = <RA, Dec, 10>;
  #debug concat("RA = ", str(V.x,0,3), ", Dec = ", str(V.y,0,3), ", R = ",
str(V.z,0,3), "     ----->     ")

  #declare V1 = MA_Deg2Vector (V.x, V.y, V.z);
  #debug concat("X = ", str(V1.x,0,8), ", Y = ", str(V1.y,0,8), ", Z = ",
str(V1.z,0,3), "     ----->     ")

  #declare P1 = MA_Vector2Deg (V1); // P1 = <RA, Dec, R>
  #debug concat("RA = ", str(P1.x,0,3), ", Dec = ", str(P1.y,0,3), ", R = ",
str(P1.z,0,3),"\n")
 #end
 #debug "\n"
#end

#error "No objects in scene"


Post a reply to this message

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