Package: openscad
Version: 2011.12-3

The attached test file has what is arguably a bug.  On line 197 it
says
    rotate([90 + led_angle])
where it should say
    rotate([90 + led_angle, 0, 0])

However, when fed to openscad the results are unpredictable.  Amongst
the outcomes I have seen:
  - the hole (which is the cylinder cut out near the top of the
    object) appears with various unpredictable alignments
  - assertion failures from openscad
       CGAL error: assertion violation!
       Expression : is_finite(d)
       File       : /usr/include/CGAL/GMP/Gmpq_type.h
       Line       : 132
       Explanation: 
       Refer to the bug-reporting instructions at 
http://www.cgal.org/bug_report.html
       Aborted
  - the behavour I intended when I wrote the file

IMO the following would be acceptable behaviours:
  - reject the input file
  - treat the missing elements as 0
  - if documented, interpret the input in some entirely different way

I conjecture that the part of openscad code which interprets the array
argument to the rotate() command fails to check that the array has 3
elements before reading all 3 of them - and as a result gets
unpredictable values from whatever happens to be next in memory.

Ian.

// -*- C -*-

led_dia = 5 + 0.6;
led_depth = 5;

led_tip_height_above_crossbar = 70;
led_angle = -60;
crossbar_dia = 25; // fixme

vert_space_inside = 8;
backfront_space_inside = 12;
width_space_inside = 10;

backfront_mate_size = 25;
tower_frontheight = 10;
tower_base_height = 20;
tower_slot_width = 3;

cableclamp_ctie_width = 4.0 + 1.0;
cableclamp_ctie_thick = 2.5 + 0.5;

lidclamp_ctie_width = 4.0 + 1.0;
lidclamp_ctie_thick = 2.5 + 0.5;

base_ctie_width = 4.0 + 1.0;
base_ctie_thick = 2.5 + 0.5;

tube_ctie_width = 4.0 + 1.0;
tube_ctie_thick = 2.5 + 0.5;

// tuning

tower_over_angle = 45;
tower_wall_thick = 1.6;
tower_forehead_angle = 30;
lid_wall_thick = 1.6;
lid_slop = 0.75;
//cableclamp_ctie_anchor = 5;
lidclamp_cableclamp_ctie_between = 0;
base_ctie_anchor = 5;
tube_ctie_anchor = 5;
protrusion_size = 2;
protrusion_none_frontback = 10;
protrusion_slop = 0.25;
cableclamp_ctie_z = tower_frontheight/2;

towerleg_backfront = 5;
towerleg_width = 3;
towerleg_foot_gap = 2;
towerleg_foot_backfront = 20;
towerleg_foot_width = 40;
towerleg_foot_height = 10;
towerleg_yslope = 0.7;
towerleg_xslope = 0.3;
echo(sqrt(towerleg_yslope*towerleg_yslope+towerleg_xslope*towerleg_xslope));

//--- tests ---

test_width = 24;
test_height = 24;

test_thicks = [9,14,21];

module Tests(){ ////toplevel
  for (thicki=[0:len(test_thicks)-1]) {
    translate([thicki*test_width-0.5, 0, 0]) {
      difference(){
        cube([test_width,
              test_thicks[thicki] + led_depth,
              test_height]);
        translate([test_width/2, -1, test_height/2])
          rotate([-90,0,0])
          cylinder(r=led_dia/2, h=led_depth+1, $fn=30);
      }
    }
  }
}

//Tests();

//--- real thing ---

// calculated

tower_overhang = led_dia * 2.5;
tower_width = width_space_inside + tower_wall_thick*2;

tower_over_max_y = tower_overhang * sin(tower_over_angle);
tower_over_max_z = tower_frontheight + tower_overhang * cos(tower_over_angle);
tower_total_max_z = tower_over_max_z + vert_space_inside + led_depth;
tower_rearwall_y = -(backfront_space_inside + tower_wall_thick);
led_head_y = tower_over_max_y/2;
led_head_z = tower_frontheight + tower_overhang*sin(tower_over_angle)/2;
backfront_mate_extra = (backfront_mate_size - (-tower_rearwall_y));

tower_height_contribution = led_head_z + tower_base_height;

base_ctie_anchor_eff = base_ctie_anchor+base_ctie_thick/2;
tube_ctie_anchor_eff = tube_ctie_anchor+tube_ctie_thick/2;

base_width = 0.7 * crossbar_dia;
base_backfront = backfront_mate_extra - tower_rearwall_y;
base_height = led_tip_height_above_crossbar - tower_height_contribution;

protrusion_frontback = base_backfront - protrusion_none_frontback;

echo(tower_height_contribution, base_height);

module TowerWallCrossSection(){
  // generates a 2D shape - a polygon
  // x is what is going to be -y
  // y is what is going to be z
  polygon([[0,                  0],
           [0,                  tower_frontheight],
           [-tower_over_max_y,  tower_over_max_z],
           [-tower_over_max_y
            + tan(tower_forehead_angle) * (vert_space_inside + led_depth),
            tower_total_max_z],
           [-tower_rearwall_y,  tower_total_max_z],
           [-tower_rearwall_y,  0],
           [-tower_rearwall_y, -tower_base_height],
           [-backfront_mate_extra, -tower_base_height]],
          convexity=5);
}

module TowerWallSomeEdge(front){
  minkowski(){
    difference(){
      TowerWallCrossSection();
      translate([front ? 0.10 : -0.10, 0])
        TowerWallCrossSection();
    }
    circle(r=tower_wall_thick, $fn=8);
  }
}

module TowerBulkCrossSection(){
  intersection(){
    TowerWallCrossSection();
    union(){
      translate([-led_head_y, led_head_z])
        circle(r = led_depth);
      TowerWallSomeEdge(true);
      translate([-50, -50])
        square([100, 50]);
    }
  }
}

module TowerRearWallCrossSection(){
  intersection(){
    TowerWallCrossSection();
    union(){
      intersection(){
        translate([0,-10]) square([100, 10+led_head_z]);
        TowerWallSomeEdge(false);
      }
      TowerBulkCrossSection();
    }
  }
}


module TowerCrossSectionDemo(){
  %TowerWallCrossSection();
  //TowerBulkCrossSection();
  TowerRearWallCrossSection();
}

module TowerMain(){
  for (mir=[0,1])
    mirror([mir,0,0]) rotate([90,0,-90]) {
      translate([0,0, tower_width/2-tower_wall_thick])
        linear_extrude(height=tower_wall_thick) {
        TowerWallCrossSection();
      }
      translate([0,0,-1])
        linear_extrude(height=tower_width/2+0.9)
        union(){
          TowerBulkCrossSection();
          hull(){
            intersection(){
              TowerWallCrossSection();
              translate([-30, -30])
                square([30 + 0.1, 30 + tower_frontheight]);
            }
          }
        }
      translate([0,0, tower_slot_width/2])
        linear_extrude(height=(tower_width - tower_slot_width)/2 - 0.2)
        TowerRearWallCrossSection();
    }
}

module LedHole(){
  translate([0, led_head_y, led_head_z])
    rotate([90 + led_angle])
    translate([0,0,-10])
    cylinder(r=led_dia/2, h=led_depth+1+10, $fn=26, $fa=10);
}

module TowerProper(){
  difference(){
    TowerMain();
    LedHole();
    // passages for cable ties
    translate([0,
               tower_rearwall_y/2,
               cableclamp_ctie_z
               + cableclamp_ctie_width/2 + lidclamp_ctie_thick/2
               + lidclamp_cableclamp_ctie_between])
      cube([50, lidclamp_ctie_width, lidclamp_ctie_thick], center=true);
    translate([0,
                (backfront_mate_extra+tower_rearwall_y)/2,
                -tower_base_height
               + max(protrusion_size + protrusion_slop + 0.1,
                     base_ctie_anchor_eff)])
      cube([50, base_ctie_width, base_ctie_thick], center=true);
//    for (extra_y=[0, -(cableclamp_ctie_thick + cableclamp_ctie_anchor)]) {
//      translate([-tower_width/2,
//               -cableclamp_ctie_thick/2 - tower_wall_thick + extra_y,
//               cableclamp_ctie_z])
//      cube([tower_wall_thick+2,
//            cableclamp_ctie_thick,
//            cableclamp_ctie_width], center=true);
//    }
    for (mir=[0,1])
     mirror([mir,0,0]) {
        translate([tower_width/4, 20, cableclamp_ctie_z])
          cube([cableclamp_ctie_thick,
                tower_wall_thick*2+1+40,
                cableclamp_ctie_width],
               center=true);
      }
    translate([0, tower_rearwall_y, -tower_base_height])
      BaseRegistrationProtrusion(protrusion_slop);
  }
}

module Tower(){ ////toplevel
  TowerProper();
  for (mir=[0,1]) {
    mirror([mir,0,0]){
      translate([0,
                 tower_rearwall_y + 0.1,
                 -1])
        mirror([0,0,1])
        multmatrix([[1,0, towerleg_xslope,0],
                    [0,1,-towerleg_yslope,0],
                    [0,0,1,0],
                    [0,0,0,1]])
        cube([towerleg_width, towerleg_backfront, tower_base_height-2]);
    }
  }
  translate([-towerleg_foot_width/2,
             tower_rearwall_y - towerleg_foot_gap,
             -tower_base_height])
    mirror([0,1,0])
    cube([towerleg_foot_width, towerleg_foot_backfront, towerleg_foot_height]);
}

module TowerMainHull(){
  hull(){ TowerMain(); }
}

module Lid(){
  intersection(){
    difference(){
      minkowski(){
        TowerMainHull();
        sphere(r=lid_wall_thick+lid_slop, $fn=8);
      }
      minkowski(){
        TowerMainHull();
        sphere(r=lid_slop, $fn=6);
      }
    }
    translate([-50,-50,led_head_z]) cube([100,100,100]);
  }
}

module LidT(){ ////toplevel
  rotate([180,0,0]) Lid();
}

module BaseRegistrationProtrusion(extra){
  size = protrusion_size + extra;
  translate([0, base_backfront/2, 0]){
    hull(){
      translate([0,0, -0.5])
        cube([protrusion_size*2, protrusion_frontback, 1.0], center=true);
      translate([0, 0, protrusion_size-0.5])
        cube([0.05, protrusion_frontback-protrusion_size*2, 1.0], center=true);
    }
  }
}

module Base(){
  difference(){
    mirror([0,0,1]){
      hull(){
        translate([-tower_width/2, 0, 0])
          cube([tower_width, base_backfront, 0.1]);
        translate([-base_width/2, 0, base_height])
          cube([base_width, base_backfront, crossbar_dia/2]);
      }
    }
    translate([0, base_backfront/2, -base_ctie_anchor_eff])
      cube([100, base_ctie_width, base_ctie_thick], center=true);
    translate([0, base_backfront/2, -base_height + tube_ctie_anchor_eff])
      cube([100, tube_ctie_width, tube_ctie_thick], center=true);
    translate([0, -1, -(base_height + crossbar_dia/2)])
      rotate([-90,0,0])
      cylinder(r=crossbar_dia/2, h=101);
  }
  BaseRegistrationProtrusion(0.0);
}

module BaseT(){ ////toplevel
  rotate([90,0,0]) Base();
}

module Demo(){
  Tower();
  %Lid();
  translate([0,0, 25]) Lid();
  translate([0, tower_rearwall_y, -(tower_base_height+5)]) Base();
}

//TowerCrossSectionDemo();
//TowerWallSomeEdge(false);
//TowerWallFrontEdge();
//TowerMainHull();
//LidT();
Tower();
//Lid();
//BaseRegistrationProtrusion();
//Base();
//BaseT();
//Demo();

Reply via email to