/* * $Id: extension-tubes.c,v 1.4 2014/10/24 01:15:26 grog Exp $ * * Calculate focus range for zoom lenses and extension tubes. * * Near focus values for Olympus lenses: * * FT: * 8 0.135 m * 9-18 0.25 m * 12-60 0.25 m * 18-180 0.45 m * 50 0.24 m * 70-300 0.96 m * * mFT: * * * 12-40 0.20 m * 14-42 0.25 m (from 14-19 mm FL) * 0.30 m (from 20-42 mm FL) * 14-150 0.50 m * 17 0.20 m */ #include #include #include #include #include #include #include /* Define this for almost-useless focus distance display. */ #undef SHOW_FOCUS_DISTANCE void usage (char *me) { fprintf (stderr, "Usage:\n" "%s tube-length near-focus shortest-focal-length [longest-focal-length] [step]\n", me ); exit (1); } /* All lengths in metres */ /* This is u as well */ float focus_distance (float f, float v) { return 1.0 / (1.0 / f - 1.0 / v); } float magnification (float f, float v) { return v / focus_distance (f, v); } /* * Calculate the two solutions of the quadratic equation * * v**2 - nv + nf = 0 * * where n is the total distance from subject to sensor. * * There's no way to know which is u and which is v, but in the situation v < u, * so that's how I name the functions. */ float v (float f, float n) { return (n - sqrt ((n * n) - 4 * n * f)) / 2; } float u (float f, float n) { return (n + sqrt ((n * n) - 4 * n * f)) / 2; } /* * All length in this program are in metres internally, but the input and output * focal lengths, tube length and steps are in mm. */ int main (int argc, char *argv []) { float tube_length; float near_focus; float near_u; float shortest_focal_length; float longest_focal_length; float focal_length; float step = 0.001; /* metres */ float lens_v; /* extension of lens at minumum focus distance */ float total_v; /* total extension including tubes */ float closest_focus; /* min (u + v) */ char *format; if ((argc < 4) || (argc > 6) ) usage (argv [0]); tube_length = atof (argv [1]) / 1000.0; /* in metres */ near_focus = atof (argv [2]); shortest_focal_length = atof (argv [3]) / 1000.0; /* in metres */ if (argc > 4) { longest_focal_length = atof (argv [4]) / 1000.0; /* in metres */ if (argc == 6) step = atof (argv [5]) / 1000.0; } else longest_focal_length = shortest_focal_length; /* default to fixed focal length */ if ((tube_length < 0.0) || (near_focus <= 0.0) || (shortest_focal_length <= 0.0) || (longest_focal_length <= 0.0) || (shortest_focal_length > longest_focal_length) || (step <= 0.0) ) usage (argv [0]); #ifdef SHOW_FOCUS_DISTANCE /* * The focus distances are so inaccurate as to be useless. But here's part * of the code. */ format = "Tube extension:\t\t%3.0f mm\n" "Near focus:\t\t%6.2f m\n" "Shortest focal length:\t%3.0f mm\n" "Longest focal length:\t%3.0f mm\n\n" "Focal length\tNear limit\tExtension\tMagnification\tFar limit\tExtension\tMagnification\n", #else format = "Tube extension:\t\t%3.0f mm\n" "Near focus:\t\t%6.2f m\n" "Shortest focal length:\t%3.0f mm\n" "Longest focal length:\t%3.0f mm\n\n" "Focal length\tExtension\tMagnification\tExtension\tMagnification\n", #endif printf (format, tube_length * 1000.0, near_focus, shortest_focal_length * 1000.0, longest_focal_length * 1000.0 ); /* Fudge for floating point */ longest_focal_length += step * 0.1; for (focal_length = shortest_focal_length; focal_length <= longest_focal_length ; focal_length += step ) { /* * Paradocically, for a normal zoom lens, the "extension" at closest focus * depens on the focal length. */ lens_v = v (focal_length, near_focus); /* v for lens */ total_v = lens_v + tube_length; /* total v */ closest_focus = total_v + focus_distance (focal_length, total_v); /* real u + v */ if (0) /* debug */ printf ("%f %f %f\n", lens_v, total_v, focus_distance (focal_length, total_v) ); #ifdef SHOW_FOCUS_DISTANCE /* * The focus distances are so inaccurate as to be useless. But here's the rest * of the code. */ printf ("%7.0f %10.4f %10.4f %10.4f %10.4f %10.4f %10.4f\n", focal_length * 1000.0, /* focal length */ closest_focus, /* closest focus */ lens_v + tube_length, /* extension at closest focus */ magnification (focal_length, total_v), /* magnification at closest */ focus_distance (focal_length, focal_length + tube_length), /* furthest focus */ tube_length, /* extension at furthest focus */ magnification (focal_length, focal_length + tube_length) ); /* magnification at furthest focus */ #else printf ("%7.0f %10.4f %10.4f %10.4f %10.4f\n", focal_length * 1000.0, /* focal length */ lens_v + tube_length, /* extension at closest focus */ magnification (focal_length, total_v), /* magnification at closest */ tube_length, /* extension at furthest focus */ magnification (focal_length, focal_length + tube_length) ); /* magnification at furthest focus */ #endif } return 0; }