1include <BOSL2/std.scad>
  2include <BOSL2/constants.scad>
  3use <BOSL2/shapes3d.scad>
  4use <JetBrainsMono-Italic-VariableFont_wght.ttf>
  5use <NotoSansJP-Regular.otf>
  6use <PTMono-Regular.ttf>
  7use <NotoSansMono-Bold.ttf>
  8
  9lens_focal_length = 50; //mm 75
 10lens_diameter = 50; //mm 30
 11lens_retaining_edge = 1; //mm
 12lens_thickness = 2; //mm
 13
 14camera_inner_dimensions = [100,100,50]; //mm 
 15
 16external_width = 3; //mm
 17
 18image_plane_width = 1; // mm
 19
 20// This equation can come in handy OA*f/(OA+f)=OA'
 21object_distances = [100,102.632,105.556,108.824,112.5,116.667,121.429,126.923,133.333,140.909,150,161.111,192.857,175,216.667,235.185,258.333,288.095,327.778,383.333,466.667,605.556,883.333,1716.67,"∞"]; // mm [300,325,350,375,400,450,500,600,750,1000,1500,3000,"∞"]
 22
 23text_top_padding = 1; // mm
 24text_offset_coeff = -3.9; // -1.9
 25index_offset = true; // false
 26text_size = 3.4; // mm 2.6
 27text_angle = 180; // deg
 28text_font = "JetBrainsMono:style=Bold Italic"; //"JetBrainsMono:style=Bold";
 29
 30jp_font = "NotoSansJP:style=Bold";
 31camera_name = "立方体";
 32spec_text_size = 5;
 33spec_text_padding = 5; // 15
 34
 35attaching_mechanism_dimensions = [15,40,2]; // mm
 36attaching_mechanism_tolerance = 0.5; // mm (applied to both parts)
 37
 38cyl_resolution = 200;
 39txt_resolution = 80;
 40crn_resolution = 60;
 41
 42corner_rounding = 2;
 43
 44// System
 45camera_box_dimensions = [camera_inner_dimensions.x+external_width*2,camera_inner_dimensions.y+external_width*2,camera_inner_dimensions.z+external_width];
 46
 47
 48// Modules
 49
 50function image_plane_calc(object_distance,focal_length)= (object_distance == "∞")? focal_length : -object_distance*focal_length/(focal_length-object_distance);
 51
 52
 53module image_plane_transform(object_distance,focal_length) { // mm
 54    if(object_distance == "∞"){
 55    translate([focal_length,0,0]) children();
 56        } else{
 57   OA_prime = -object_distance*focal_length/(focal_length-object_distance);
 58    translate([OA_prime,0,0]) children();
 59    }
 60}
 61
 62function image_plane_text_dist_from_top (object_distance,focal_length,index) = -text_top_padding+(index_offset ? text_offset_coeff*(ceil(len(object_distances)/2)-index-1) : text_offset_coeff*image_plane_calc(object_distance,focal_length)-text_offset_coeff*focal_length);
 63    
 64
 65module image_plane_text_transform(object_distance,focal_length,index){
 66    fixed_index = index%(ceil(len(object_distances)/2));
 67    has_looped = fixed_index<index;
 68    dist_from_top = image_plane_text_dist_from_top(object_distance,focal_length,fixed_index);
 69    translate([0, has_looped ? camera_inner_dimensions.y+external_width*2: 0, camera_inner_dimensions.z+external_width/2-(has_looped ? text_size : 0)])
 70    translate([external_width/2, (has_looped ? 0 : 1) * external_width/4, external_width/2])
 71    translate([0,0,dist_from_top])
 72    image_plane_transform(object_distance,focal_length)  children();
 73}
 74
 75module image_plane_text(object_distance,focal_length,index){
 76    fixed_index = index%(ceil(len(object_distances)/2));
 77    has_looped = fixed_index<index;
 78    image_plane_text_transform(object_distance,focal_length,index) rotate([90,text_angle+(has_looped?180:0),(has_looped?180:0)])
 79    translate([0,0,(has_looped ? -1 : 0) * external_width/4])
 80    linear_extrude(external_width/4)
 81    if(object_distance != "∞"){
 82     text(format("{:-4d} mm; Υ: {:0.3f}", [object_distance, image_plane_calc(object_distance,focal_length)/-object_distance]),text_size, font = text_font, $fn=txt_resolution);
 83    } else {
 84     text(format("{:-4s} mm", [object_distance]),text_size, font = text_font, $fn=txt_resolution);
 85    }
 86    }
 87
 88module image_plane(object_distance,focal_length,index) { // mm
 89    fixed_index = index%(ceil(len(object_distances)/2));
 90    has_looped = fixed_index<index;
 91    translate([external_width/2, external_width/2+external_width/4, external_width/2+external_width/4]) 
 92    image_plane_transform(object_distance,focal_length)
 93    cube([image_plane_width,camera_inner_dimensions.y+external_width/2,camera_inner_dimensions.z+external_width/2]);
 94    // Legend text
 95    image_plane_text(object_distance,focal_length,index);
 96    translate([image_plane_width/4, -external_width/4,0]) 
 97    image_plane_text_transform(object_distance,focal_length,index)
 98   translate([0,0,(has_looped ? text_size : 0)]) cube([image_plane_width/2,external_width/4,camera_inner_dimensions.z]);
 99}
100
101module rounded_cuboid(dimensions,edges,rounding){
102    cuboid(dimensions,anchor=[-1,-1,-1],rounding=rounding,edges=edges,$fn=crn_resolution);
103}
104
105difference(){
106    rounded_cuboid(camera_box_dimensions,[BOTTOM+FRONT,BOTTOM+RIGHT,BOTTOM+LEFT,BOTTOM+BACK,FRONT+LEFT,FRONT+RIGHT,BACK+LEFT,BACK+RIGHT],corner_rounding);
107    // Internal cavity
108translate([external_width, external_width, external_width]) cube(camera_inner_dimensions);
109    // Lens
110    translate([0, external_width+camera_inner_dimensions.y/2, external_width+camera_inner_dimensions.z]) rotate([-90,0,-90])
111    cylinder(external_width/2-lens_thickness/2,lens_diameter/2-lens_retaining_edge,lens_diameter/2, $fn=cyl_resolution);
112    translate([external_width/2+lens_thickness/2, external_width+camera_inner_dimensions.y/2, external_width+camera_inner_dimensions.z]) rotate([-90,0,-90])
113    cylinder(external_width/2-lens_thickness/2,lens_diameter/2,lens_diameter/2-lens_retaining_edge, $fn=cyl_resolution);
114    translate([external_width/2-lens_thickness/2, external_width+camera_inner_dimensions.y/2, external_width+camera_inner_dimensions.z]) rotate([-90,0,-90])
115    cylinder(lens_thickness,lens_diameter/2,lens_diameter/2, $fn=cyl_resolution);
116    // Image planes
117for(i = [0:len(object_distances)-1]){
118    distance = object_distances[i];
119    image_plane(distance,lens_focal_length,i);
120    }
121    // Camera specs
122    // f-stop
123    translate([spec_text_padding,external_width/4,spec_text_padding]) rotate([90,0,0])
124    linear_extrude(external_width/4)
125    text(format("f/   {:.2f}", [lens_focal_length/lens_diameter]),spec_text_size, font = text_font, $fn=txt_resolution);
126    // focal length
127    translate([spec_text_padding,external_width/4,spec_text_padding+spec_text_size*1.5]) rotate([90,0,0])
128    linear_extrude(external_width/4)
129    text(format("f: {:3d} mm", [lens_focal_length]),spec_text_size, font = text_font, $fn=txt_resolution);
130    // Camera name
131    translate([spec_text_padding,external_width/4,spec_text_padding+spec_text_size*1.5*2]) rotate([90,0,0])
132    linear_extrude(external_width/4)
133    text(camera_name, spec_text_size, font = jp_font, $fn=txt_resolution);
134    // Attaching mechanism internal
135    translate([camera_inner_dimensions.x+external_width-attaching_mechanism_tolerance, external_width+camera_inner_dimensions.y/2-(attaching_mechanism_dimensions.x+attaching_mechanism_tolerance-attaching_mechanism_tolerance/4), external_width+camera_inner_dimensions.z-(attaching_mechanism_dimensions.y+attaching_mechanism_tolerance)]) rounded_cuboid([attaching_mechanism_dimensions.z+attaching_mechanism_tolerance,(attaching_mechanism_dimensions.x+attaching_mechanism_tolerance),(attaching_mechanism_dimensions.y+attaching_mechanism_tolerance)],[FRONT+LEFT,FRONT+RIGHT,FRONT+BOTTOM,BACK+LEFT,BACK+RIGHT,BACK+BOTTOM,BOTTOM+LEFT,BOTTOM+RIGHT],(attaching_mechanism_dimensions.z+attaching_mechanism_tolerance)/4);
136}
137
138// Attaching mechanism external part
139translate([camera_inner_dimensions.x+external_width, external_width+camera_inner_dimensions.y/2+attaching_mechanism_tolerance/4, external_width+camera_inner_dimensions.z]) rounded_cuboid([attaching_mechanism_dimensions.z-attaching_mechanism_tolerance,attaching_mechanism_dimensions.x-attaching_mechanism_tolerance,attaching_mechanism_dimensions.y-attaching_mechanism_tolerance],[FRONT+LEFT,FRONT+RIGHT,FRONT+TOP,BACK+LEFT,BACK+RIGHT,BACK+TOP,TOP+LEFT,TOP+RIGHT],(attaching_mechanism_dimensions.z-attaching_mechanism_tolerance)/4);