discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

STL is unreadable or not 'watertight'

A
adrian
Tue, Feb 28, 2017 2:30 PM

This is driving me a bit nuts.  I have a geometry but when I export it to an
STL, importing it to MeshLab will result in a non-watertight object and
NetFabb won't even open it.  Makerbot Desktop doesn't seem to have any
problem with it though.  However, I need the center of mass of the object,
and I don't know of another way of doing it without MeshLab.

Anyone have any ideas what I can do?

I'll try and post a working minimal model to the forum in a bit.

--
View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

This is driving me a bit nuts. I have a geometry but when I export it to an STL, importing it to MeshLab will result in a non-watertight object and NetFabb won't even open it. Makerbot Desktop doesn't seem to have any problem with it though. However, I need the center of mass of the object, and I don't know of another way of doing it without MeshLab. Anyone have any ideas what I can do? I'll try and post a working minimal model to the forum in a bit. -- View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642.html Sent from the OpenSCAD mailing list archive at Nabble.com.
NH
nop head
Tue, Feb 28, 2017 2:43 PM

Impossible to say without the file or some code. Basically it means you
have a mesh with hole in it. You can easily make those with polyhedron or
by doing CGS ops on almost coincident surfaces.

On 28 February 2017 at 14:30, adrian adrianh.bsc@gmail.com wrote:

This is driving me a bit nuts.  I have a geometry but when I export it to
an
STL, importing it to MeshLab will result in a non-watertight object and
NetFabb won't even open it.  Makerbot Desktop doesn't seem to have any
problem with it though.  However, I need the center of mass of the object,
and I don't know of another way of doing it without MeshLab.

Anyone have any ideas what I can do?

I'll try and post a working minimal model to the forum in a bit.

--
View this message in context: http://forum.openscad.org/STL-
is-unreadable-or-not-watertight-tp20642.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Impossible to say without the file or some code. Basically it means you have a mesh with hole in it. You can easily make those with polyhedron or by doing CGS ops on almost coincident surfaces. On 28 February 2017 at 14:30, adrian <adrianh.bsc@gmail.com> wrote: > This is driving me a bit nuts. I have a geometry but when I export it to > an > STL, importing it to MeshLab will result in a non-watertight object and > NetFabb won't even open it. Makerbot Desktop doesn't seem to have any > problem with it though. However, I need the center of mass of the object, > and I don't know of another way of doing it without MeshLab. > > Anyone have any ideas what I can do? > > I'll try and post a working minimal model to the forum in a bit. > > > > -- > View this message in context: http://forum.openscad.org/STL- > is-unreadable-or-not-watertight-tp20642.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
A
adrian
Tue, Feb 28, 2017 2:50 PM

Nm, seems to be a bug in MeshLab that corrupted the file.

--
View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20647.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Nm, seems to be a bug in MeshLab that corrupted the file. -- View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20647.html Sent from the OpenSCAD mailing list archive at Nabble.com.
A
adrian
Tue, Feb 28, 2017 3:14 PM

Nope, seems to be some operation.  Simplifying the model somewhat fixed the
issue.  Trying to track down the problem now.  Will post later with my
findings.

--
View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20649.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Nope, seems to be some operation. Simplifying the model somewhat fixed the issue. Trying to track down the problem now. Will post later with my findings. -- View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20649.html Sent from the OpenSCAD mailing list archive at Nabble.com.
A
adrian
Tue, Feb 28, 2017 3:43 PM

Ok.  So the problem is a translation() call is messing up the geometry.  Here
is here is the code:
$fn=34;module mirror2(rot){    rotate(rot/2)        children();
rotate(-rot/2)        mirror([1,0,0])            children();}module
eye(inner=true, outer=true){    if (inner)    {        if (outer)        {
difference()            {                object(0);
object(wallThickness);            }        }        else        {
object(0);        }    }    else    {        object(wallThickness);    }
module object(thickness)    {        // eye (outer wall)
translate([-4,-5.1,4])            rotate([-90,0,-20])            scale([1.8,
1.1, 1])                sphere(d=2-thickness2);    }}module
headSphere(inner=true, outer=true){    if (inner)    {        if (outer)
{            difference()            {                object(0);
object(wallThickness);            }        }        else        {
object(0);        }    }    else    {        object(wallThickness);    }
module object(thickness)    {        translate([0,0,-2])
scale([1.3, 1.1, 1.3])                sphere(d=15-thickness
2);    }}module
mouth(inner=true, outer=true){    if (inner)    {        if (outer)        {
difference()            {                object(wallThickness);
object(0);            }        }        else        {
object(wallThickness);        }    }    else    {        object(0);    }
module object(thickness)    {        // mouth (outer wall)
translate([0,-7.5,-2])            rotate([-45,0,0])            scale([1.8,
1.1, 1])                sphere(d=5+thickness2);    }}module
alignmentHolder(inner=true, outer=true){    if (inner)    {        if
(outer)        {            difference()            {
object(wallThickness);                object(0);            }        }
else        {            object(wallThickness);        }    }    else    {
object(0);    }        module object(thickness)    {        mirror2(0)
translate([1.2-.4-thickness/2, 2, -4+.15])            rotate([0,90,0])
cylinder(d=5.4+thickness,h=.4
5+thickness);    }}module
neckHollow(inner=true, outer=true){    if (inner)    {        if (outer)
{            difference()            {                object(wallThickness);
object(0);            }        }        else        {
object(wallThickness);        }    }    else    {        object(0);    }
module object(thickness)    {        translate([0,0,thickness])
// neck hollow            translate([0,0,33-44])            scale_([1.3,
4.5, 1], undef, [0, 2, 0])                hull()                {
translate([0,2,neckHeight])                        cube([5,.001,.001],
center=true);                    scale([1.3, 1.1, 1])
translate([0,0,-1.2])                        linear_extrude(.0001)
circle(d=10);                }            }}module hair(inner=true,
outer=true){    if (inner)    {        if (outer)        {
difference()            {                object(0);
object(wallThickness);            }        }        else        {
object(0);        }    }    else    {        object(wallThickness);    }
module object(thickness)    {        difference()        {
//mirror2(0)            translate([0,0,-15/2-(1.8)])
side(thickness);            neckHollow(inner=false);        }        module
side(thickness)        {            h = 1;            translate([0,0,
h+(thickness ? .00001+thickness : 0)])                difference()
{                    linear_extrude(15/2-h)
offset(r=-thickness)                            hair2d();                }
//neckHollow(outer=false);        }        module hair2d()        {
intersection()            {                projection()
headSphere(outer=false);                translate([-15, -3])
square([30,15]);            }        }    }}module weight(){
translate([0,2,-4+.15])        rotate([90,90,0])        wedge(10, 60,
wedge_centred);}preview = 0;neckHeight=5.5*1.3;wallThickness=.4;module
head(){    difference()    {        if(1)        {            // eye
mirror2(0)                difference()                {
eye();                    headSphere(inner=false);                }
//mouth            intersection()            {                mouth();
headSphere(inner=false);            }                        // neck hollow
difference()            {                intersection()                {
neckHollow();                    headSphere(outer=false);                }
alignmentHolder(outer=false);            }            // alignment holder
difference()            {                alignmentHolder();
neckHollow(inner=false);            }                        // hair
difference()            {                hair();
headSphere(inner=false);            }                        // weight
inside of head            difference()            {
intersection()                {                    weight();
union(1)                    {
headSphere(inner=false);                        hair(inner=false);
}                }                neckHollow(inner=false);
alignmentHolder(outer=false);            }            // head
difference()            {                headSphere();
mirror2(0)                eye(inner=false);
mouth(inner=false);                              neckHollow(outer=false);
alignmentHolder(outer=false);
hair(inner=false);            }        }        if (preview)        {
// used to see within head            translate([6.4,-5,-15/2])
cube([20,7,15]);        }    }}module scale_(a, v, offset){
translate(offset)        scale(a)        translate(-offset)
children();}wedge_below_xy = 0;wedge_above_xy = 1;wedge_centred  = 2;//
wedge////  Generates a wedge which is off to the right of the y-axis and is
centred on//  the x-axis.////  Primary purporse of wedge is to produce a
wedge for intersecting with an//  object.//// size//  - is matrix then//
length = size[0]2 (y-axis)//      width  = size[1] (x-axis)//      height
= size[2] (z-axis)//      angle  = has no meaning in this context//  - is
a value then//      specifies the half base size along xy-plane//
length = size
2 (y-axis)//      width  = size (x-axis)//      - if angle
is undefined then//          height = size.//        else//
height = tan(angle)*size.// type//  - is wedge_centred then wedge is
centred around the xy-plane//    (See Figure 1)//  - is wedge_above_xy
then wedge is above the xy-plane//    (See Figure 2)//  - is
wedge_below_xy then wedge is below the xy-plane//    (See Figure 2)////
E.g. Figure 1:  wedge_centred////  y-axis
z-axis//                                                          //
|<-width->|                            |              //    |.
___                      |          ___ //    |        |    ^
|      /|  ^  //    |        |    |                      |      / |  |
//    |        |    |                      |    /  |  |  //    |
|    |                      |    /  |  |  //    |        | length/2
|  /    | height//    |        |    |                      |  /    |  |
//    |        |    |                      | / angle|  |  //    |
|    v                      |/  |    |  |  //  --+        |------ x-axis
---+ <-+    |---|--//    |        |                            |\      |
|  //    |        |                            | \      |  |  //    |
|                            |  \    |  |  //    |        |
|  \    |  |  //    |        |                            |    \  |  |
//    |        |                            |    \  |  |  //    |
|                            |      \ |  |  //    |
|
|      |  v //    |                                      |
//    |                                      |              ////  E.g.
Figure 2:  wedge_above_xy and wedge_below_xy////  y-axis
z-axis                  z-axis            //
//    |<-width->|                |                        |
//    |.  ___          |          ___          |//    |
|    ^            |      /|  ^          |//    |        |    |
|      / |  |          |//    |        |    |            |    /  |  |
|//    |        |    |            |    /  |  |          |//    |
| length/2        |  /    | height        |//    |        |    |
|  /    |  |          | angle//    |        |    |            | /      |
|          | |//    |        |    v            |/      |  v          |
v//  --+        |------ x-axis ---+--------+------
---+--------+------//    |        |                | ^
|\      |  ^  //    |        |                | |                      |
\      |  |  //    |        |                | angle                  |
\    |  |  //    |        |                |                        |
\    | height//    |        |                |                        |
\  |  |  //    |        |                |                        |
\  |  |  //    |        |                |                        |
\ |  |  //    |
|                |                        |
v //    |                          |                        |
//    |                          |                        |
//module wedge(size, angle, type){    ASSERT(type != undef, "Specify type of
wedge");    if (is_matrix(size))    {        w(size[0], size[1], size[2],
type);    }    else    {        if (angle == undef)        {
w(size, size, size, type);        }        else        {
//echo(size=size,angle=angle);            ASSERT(-180 < angle && angle < 180
, str("Wedge angle is ", angle, " but must be between (-180, 180)"));
if (angle >= 0)            {                w(size, size, tan(type ==
wedge_centred ? angle/2 : angle)*size, type);            }            else
{                // If angle is < 0 then make positive and use below type if
above                // or vice versa.  This results in the same wedge but
keeps the                // face normals going in the correct direction.
w(size, size, tan(type == wedge_centred ? -angle/2 : -angle)*size
, type == wedge_centred ? wedge_centred : !type);            }
}    }    module w(l, w, h, type)    {        wedge_faces =
[[0,1,2,3],[3,5,4,0],[4,1,0],[2,5,3],[4,5,2,1]];        if (type ==
wedge_centred)        {            polyhedron(
[[0,-l,0],[w,-l,-h],[w,l,-h],[0,l,0],[w,-l,h],[w,l,h]],
wedge_faces            );        }        else if (type == wedge_below_xy)
{            echo("ANGLE", angle([w,0,0], [w,0,h]));            polyhedron(
[[0,-l,0],[w,-l,-h],[w,l,-h],[0,l,0],[w,-l,0],[w,l,0]],
wedge_faces            );        }        else if (type == wedge_above_xy)
{            polyhedron(
[[0,-l,0],[w,-l,0],[w,l,0],[0,l,0],[w,-l,h],[w,l,h]],
wedge_faces            );        }        else        {
ASSERT(false, str("Wedge type not valid value (", type, ") when calling
module wedge()."));        }    }}module ASSERT(x, msg){    if (!x)    {
if (msg == undef)        {            echo(str(" ASSERT FAILURE:  No
message."));        }        else        {            echo(str(" ASSERT
FAILURE:  ", msg, ""));        }    }}function is_matrix(x)  = len(x)
!= undef && (x[0] != x[0][0] || len(x) != len(str(x)));//
headtranslate([0,0,44])    head();
The 2nd last line when not commented out, will result in an STL that is a
bit corrupted.  Very weird, and definitely very wrong.
Tested in OpenSCAD version 2016.10.04 (git 7e0935d) and OpenSCAD version
2015.03-2

--
View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20652.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Ok. So the problem is a translation() call is messing up the geometry. Here is here is the code: $fn=34;module mirror2(rot){ rotate(rot/2) children(); rotate(-rot/2) mirror([1,0,0]) children();}module eye(inner=true, outer=true){ if (inner) { if (outer) { difference() { object(0); object(wallThickness); } } else { object(0); } } else { object(wallThickness); } module object(thickness) { // eye (outer wall) translate([-4,-5.1,4]) rotate([-90,0,-20]) scale([1.8, 1.1, 1]) sphere(d=2-thickness*2); }}module headSphere(inner=true, outer=true){ if (inner) { if (outer) { difference() { object(0); object(wallThickness); } } else { object(0); } } else { object(wallThickness); } module object(thickness) { translate([0,0,-2]) scale([1.3, 1.1, 1.3]) sphere(d=15-thickness*2); }}module mouth(inner=true, outer=true){ if (inner) { if (outer) { difference() { object(wallThickness); object(0); } } else { object(wallThickness); } } else { object(0); } module object(thickness) { // mouth (outer wall) translate([0,-7.5,-2]) rotate([-45,0,0]) scale([1.8, 1.1, 1]) sphere(d=5+thickness*2); }}module alignmentHolder(inner=true, outer=true){ if (inner) { if (outer) { difference() { object(wallThickness); object(0); } } else { object(wallThickness); } } else { object(0); } module object(thickness) { mirror2(0) translate([1.2-.4-thickness/2, 2, -4+.15]) rotate([0,90,0]) cylinder(d=5.4+thickness,h=.4*5+thickness); }}module neckHollow(inner=true, outer=true){ if (inner) { if (outer) { difference() { object(wallThickness); object(0); } } else { object(wallThickness); } } else { object(0); } module object(thickness) { translate([0,0,thickness]) // neck hollow translate([0,0,33-44]) scale_([1.3, 4.5, 1], undef, [0, 2, 0]) hull() { translate([0,2,neckHeight]) cube([5,.001,.001], center=true); scale([1.3, 1.1, 1]) translate([0,0,-1.2]) linear_extrude(.0001) circle(d=10); } }}module hair(inner=true, outer=true){ if (inner) { if (outer) { difference() { object(0); object(wallThickness); } } else { object(0); } } else { object(wallThickness); } module object(thickness) { difference() { //mirror2(0) translate([0,0,-15/2-(1.8)]) side(thickness); neckHollow(inner=false); } module side(thickness) { h = 1; translate([0,0, h+(thickness ? .00001+thickness : 0)]) difference() { linear_extrude(15/2-h) offset(r=-thickness) hair2d(); } //neckHollow(outer=false); } module hair2d() { intersection() { projection() headSphere(outer=false); translate([-15, -3]) square([30,15]); } } }}module weight(){ translate([0,2,-4+.15]) rotate([90,90,0]) wedge(10, 60, wedge_centred);}preview = 0;neckHeight=5.5*1.3;wallThickness=.4;module head(){ difference() { if(1) { // eye mirror2(0) difference() { eye(); headSphere(inner=false); } //mouth intersection() { mouth(); headSphere(inner=false); } // neck hollow difference() { intersection() { neckHollow(); headSphere(outer=false); } alignmentHolder(outer=false); } // alignment holder difference() { alignmentHolder(); neckHollow(inner=false); } // hair difference() { hair(); headSphere(inner=false); } // weight inside of head difference() { intersection() { weight(); union(1) { headSphere(inner=false); hair(inner=false); } } neckHollow(inner=false); alignmentHolder(outer=false); } // head difference() { headSphere(); mirror2(0) eye(inner=false); mouth(inner=false); neckHollow(outer=false); alignmentHolder(outer=false); hair(inner=false); } } if (preview) { // used to see within head translate([6.4,-5,-15/2]) cube([20,7,15]); } }}module scale_(a, v, offset){ translate(offset) scale(a) translate(-offset) children();}wedge_below_xy = 0;wedge_above_xy = 1;wedge_centred = 2;// wedge//// Generates a wedge which is off to the right of the y-axis and is centred on// the x-axis.//// Primary purporse of wedge is to produce a wedge for intersecting with an// object.//// size// - is matrix then// length = size[0]*2 (y-axis)// width = size[1] (x-axis)// height = size[2] (z-axis)// angle = has no meaning in this context// - is a value then// specifies the half base size along xy-plane// length = size*2 (y-axis)// width = size (x-axis)// - if angle is undefined then// height = size.// else// height = tan(angle)*size.// type// - is wedge_centred then wedge is centred around the xy-plane// (See Figure 1)// - is wedge_above_xy then wedge is above the xy-plane// (See Figure 2)// - is wedge_below_xy then wedge is below the xy-plane// (See Figure 2)//// E.g. Figure 1: wedge_centred//// y-axis z-axis// // |<-width->| | // |_________. ___ | ___ // | | ^ | /| ^ // | | | | / | | // | | | | / | | // | | | | / | | // | | length/2 | / | height// | | | | / | | // | | | | / angle| | // | | v |/ | | | // --+ |------ x-axis ---+ <-+ |---|--// | | |\ | | // | | | \ | | // | | | \ | | // | | | \ | | // | | | \ | | // | | | \ | | // | | | \ | | // |_________| | \| _v_ // | | // | | //// E.g. Figure 2: wedge_above_xy and wedge_below_xy//// y-axis z-axis z-axis // // |<-width->| | | // |_________. ___ | ___ |// | | ^ | /| ^ |// | | | | / | | |// | | | | / | | |// | | | | / | | |// | | length/2 | / | height |// | | | | / | | | angle// | | | | / | | | |// | | v |/ | v | v// --+ |------ x-axis ---+--------+------ ---+--------+------// | | | ^ |\ | ^ // | | | | | \ | | // | | | angle | \ | | // | | | | \ | height// | | | | \ | | // | | | | \ | | // | | | | \ | | // |_________| | | \| _v_ // | | | // | | | //module wedge(size, angle, type){ ASSERT(type != undef, "Specify type of wedge"); if (is_matrix(size)) { w(size[0], size[1], size[2], type); } else { if (angle == undef) { w(size, size, size, type); } else { //echo(size=size,angle=angle); ASSERT(-180 < angle && angle < 180 , str("Wedge angle is ", angle, " but must be between (-180, 180)")); if (angle >= 0) { w(size, size, tan(type == wedge_centred ? angle/2 : angle)*size, type); } else { // If angle is < 0 then make positive and use below type if above // or vice versa. This results in the same wedge but keeps the // face normals going in the correct direction. w(size, size, tan(type == wedge_centred ? -angle/2 : -angle)*size , type == wedge_centred ? wedge_centred : !type); } } } module w(l, w, h, type) { wedge_faces = [[0,1,2,3],[3,5,4,0],[4,1,0],[2,5,3],[4,5,2,1]]; if (type == wedge_centred) { polyhedron( [[0,-l,0],[w,-l,-h],[w,l,-h],[0,l,0],[w,-l,h],[w,l,h]], wedge_faces ); } else if (type == wedge_below_xy) { echo("ANGLE", angle([w,0,0], [w,0,h])); polyhedron( [[0,-l,0],[w,-l,-h],[w,l,-h],[0,l,0],[w,-l,0],[w,l,0]], wedge_faces ); } else if (type == wedge_above_xy) { polyhedron( [[0,-l,0],[w,-l,0],[w,l,0],[0,l,0],[w,-l,h],[w,l,h]], wedge_faces ); } else { ASSERT(false, str("Wedge type not valid value (", type, ") when calling module wedge().")); } }}module ASSERT(x, msg){ if (!x) { if (msg == undef) { echo(str(" ASSERT FAILURE: &nbsp;No message.")); } else { echo(str("&nbsp;ASSERT FAILURE: &nbsp;", msg, "")); } }}function is_matrix(x) = len(x) != undef && (x[0] != x[0][0] || len(x) != len(str(x)));// headtranslate([0,0,44]) head(); The 2nd last line when not commented out, will result in an STL that is a bit corrupted. Very weird, and definitely very wrong. Tested in OpenSCAD version 2016.10.04 (git 7e0935d) and OpenSCAD version 2015.03-2 -- View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20652.html Sent from the OpenSCAD mailing list archive at Nabble.com.
NH
nop head
Tue, Feb 28, 2017 4:25 PM

With or without the translation it has 8 holes according to netfabb and
lots of degenerate faces. They seem to be where the hair joins the head.
Possibly it needs to overlap a bit.

The way a translate can break things (although in this case it seems broken
anyway) is that the precision of floating point numbers gets less as they
get bigger. When you have very close vertices they can collapse when made
more distant from the origin.

On 28 February 2017 at 15:43, adrian adrianh.bsc@gmail.com wrote:

Ok. So the problem is a translation() call is messing up the geometry.
Here is here is the code:

$fn=34;

module mirror2(rot)
{
rotate(rot/2)
children();

 rotate(-rot/2)
     mirror([1,0,0])
         children();

}

module eye(inner=true, outer=true)
{
if (inner)
{
if (outer)
{
difference()
{
object(0);
object(wallThickness);
}
}
else
{
object(0);
}
}
else
{
object(wallThickness);
}
module object(thickness)
{
// eye (outer wall)
translate([-4,-5.1,4])
rotate([-90,0,-20])
scale([1.8, 1.1, 1])
sphere(d=2-thickness*2);
}
}

module headSphere(inner=true, outer=true)
{
if (inner)
{
if (outer)
{
difference()
{
object(0);
object(wallThickness);
}
}
else
{
object(0);
}
}
else
{
object(wallThickness);
}
module object(thickness)
{
translate([0,0,-2])
scale([1.3, 1.1, 1.3])
sphere(d=15-thickness*2);
}
}

module mouth(inner=true, outer=true)
{
if (inner)
{
if (outer)
{
difference()
{
object(wallThickness);
object(0);
}
}
else
{
object(wallThickness);
}
}
else
{
object(0);
}

 module object(thickness)
 {
     // mouth (outer wall)
     translate([0,-7.5,-2])
         rotate([-45,0,0])
         scale([1.8, 1.1, 1])
             sphere(d=5+thickness*2);
 }

}

module alignmentHolder(inner=true, outer=true)
{
if (inner)
{
if (outer)
{
difference()
{
object(wallThickness);
object(0);
}
}
else
{
object(wallThickness);
}
}
else
{
object(0);
}

 module object(thickness)
 {
     mirror2(0)
         translate([1.2-.4-thickness/2, 2, -4+.15])
         rotate([0,90,0])
             cylinder(d=5.4+thickness,h=.4*5+thickness);
 }

}

module neckHollow(inner=true, outer=true)
{
if (inner)
{
if (outer)
{
difference()
{
object(wallThickness);
object(0);
}
}
else
{
object(wallThickness);
}
}
else
{
object(0);
}

 module object(thickness)
 {
     translate([0,0,thickness])
         // neck hollow
         translate([0,0,33-44])
         scale_([1.3, 4.5, 1], undef, [0, 2, 0])
             hull()
             {
                 translate([0,2,neckHeight])
                     cube([5,.001,.001], center=true);
                 scale([1.3, 1.1, 1])
                     translate([0,0,-1.2])
                     linear_extrude(.0001)
                         circle(d=10);
             }
         }

}

module hair(inner=true, outer=true)
{
if (inner)
{
if (outer)
{
difference()
{
object(0);
object(wallThickness);
}
}
else
{
object(0);
}
}
else
{
object(wallThickness);
}

 module object(thickness)
 {
     difference()
     {
         //mirror2(0)
         translate([0,0,-15/2-(1.8)])
             side(thickness);
         neckHollow(inner=false);
     }
     module side(thickness)
     {
         h = 1;
         translate([0,0, h+(thickness ? .00001+thickness : 0)])
             difference()
             {
                 linear_extrude(15/2-h)
                     offset(r=-thickness)
                         hair2d();
             }
         //neckHollow(outer=false);
     }
     module hair2d()
     {
         intersection()
         {
             projection()
                 headSphere(outer=false);
             translate([-15, -3])
                 square([30,15]);
         }
     }
 }

}

module weight()
{
translate([0,2,-4+.15])
rotate([90,90,0])
wedge(10, 60, wedge_centred);
}
preview = 0;
neckHeight=5.5*1.3;
wallThickness=.4;
module head()
{
difference()
{
if(1)
{
// eye
mirror2(0)
difference()
{
eye();
headSphere(inner=false);
}

         //mouth
         intersection()
         {
             mouth();
             headSphere(inner=false);
         }

         // neck hollow
         difference()
         {
             intersection()
             {
                 neckHollow();
                 headSphere(outer=false);
             }
             alignmentHolder(outer=false);
         }

         // alignment holder
         difference()
         {
             alignmentHolder();
             neckHollow(inner=false);
         }

         // hair
         difference()
         {
             hair();
             headSphere(inner=false);
         }

         // weight inside of head
         difference()
         {
             intersection()
             {
                 weight();
                 union(1)
                 {
                     headSphere(inner=false);
                     hair(inner=false);
                 }
             }
             neckHollow(inner=false);
             alignmentHolder(outer=false);
         }

         // head
         difference()
         {
             headSphere();

             mirror2(0)
             eye(inner=false);

             mouth(inner=false);

             neckHollow(outer=false);

             alignmentHolder(outer=false);

             hair(inner=false);
         }
     }
     if (preview)
     {
         // used to see within head
         translate([6.4,-5,-15/2])
         cube([20,7,15]);
     }
 }

}

module scale_(a, v, offset)
{
translate(offset)
scale(a)
translate(-offset)
children();
}

wedge_below_xy = 0;
wedge_above_xy = 1;
wedge_centred  = 2;

// wedge
//
//  Generates a wedge which is off to the right of the y-axis and is centred on
//  the x-axis.
//
//  Primary purporse of wedge is to produce a wedge for intersecting with an
//  object.
//
// size
//  - is matrix then
//      length = size[0]2 (y-axis)
//      width  = size[1] (x-axis)
//      height = size[2] (z-axis)
//      angle  = has no meaning in this context
//  - is a value then
//      specifies the half base size along xy-plane
//      length = size
2 (y-axis)
//      width  = size (x-axis)
//      - if angle is undefined then
//          height = size.
//        else
//          height = tan(angle)*size.
// type
//  - is wedge_centred then wedge is centred around the xy-plane
//    (See Figure 1)
//  - is wedge_above_xy then wedge is above the xy-plane
//    (See Figure 2)
//  - is wedge_below_xy then wedge is below the xy-plane
//    (See Figure 2)
//
//  E.g. Figure 1:  wedge_centred
//
//  y-axis                                z-axis
//
//    |<-width->|                            |
//    |.  ___                      |          ___
//    |        |    ^                      |      /|  ^
//    |        |    |                      |      / |  |
//    |        |    |                      |    /  |  |
//    |        |    |                      |    /  |  |
//    |        | length/2                  |  /    | height
//    |        |    |                      |  /    |  |
//    |        |    |                      | / angle|  |
//    |        |    v                      |/  |    |  |
//  --+        |------ x-axis            ---+ <-+    |---|--
//    |        |                            |\      |  |
//    |        |                            | \      |  |
//    |        |                            |  \    |  |
//    |        |                            |  \    |  |
//    |        |                            |    \  |  |
//    |        |                            |    \  |  |
//    |        |                            |      \ |  |
//    |
|                            |      |  v
//    |                                      |
//    |                                      |
//
//  E.g. Figure 2:  wedge_above_xy and wedge_below_xy
//
//  y-axis                    z-axis                  z-axis
//
//    |<-width->|                |                        |
//    |.  ___          |          ___          |
//    |        |    ^            |      /|  ^          |
//    |        |    |            |      / |  |          |
//    |        |    |            |    /  |  |          |
//    |        |    |            |    /  |  |          |
//    |        | length/2        |  /    | height        |
//    |        |    |            |  /    |  |          | angle
//    |        |    |            | /      |  |          | |
//    |        |    v            |/      |  v          | v
//  --+        |------ x-axis ---+--------+------      ---+--------+------
//    |        |                | ^                      |\      |  ^
//    |        |                | |                      | \      |  |
//    |        |                | angle                  |  \    |  |
//    |        |                |                        |  \    | height
//    |        |                |                        |    \  |  |
//    |        |                |                        |    \  |  |
//    |        |                |                        |      \ |  |
//    |
|                |                        |      |  v
//    |                          |                        |
//    |                          |                        |
//
module wedge(size, angle, type)
{
ASSERT(type != undef, "Specify type of wedge");
if (is_matrix(size))
{
w(size[0], size[1], size[2], type);
}
else
{
if (angle == undef)
{
w(size, size, size, type);
}
else
{
//echo(size=size,angle=angle);
ASSERT(-180 < angle && angle < 180
, str("Wedge angle is ", angle, " but must be between (-180, 180)"));
if (angle >= 0)
{
w(size, size, tan(type == wedge_centred ? angle/2 : angle)*size, type);
}
else
{
// If angle is < 0 then make positive and use below type if above
// or vice versa.  This results in the same wedge but keeps the
// face normals going in the correct direction.
w(size, size, tan(type == wedge_centred ? -angle/2 : -angle)*size
, type == wedge_centred ? wedge_centred : !type);
}

     }
 }

 module w(l, w, h, type)
 {
     wedge_faces = [[0,1,2,3],[3,5,4,0],[4,1,0],[2,5,3],[4,5,2,1]];
     if (type == wedge_centred)
     {
         polyhedron(
             [[0,-l,0],[w,-l,-h],[w,l,-h],[0,l,0],[w,-l,h],[w,l,h]],
             wedge_faces
         );
     }
     else if (type == wedge_below_xy)
     {
         echo("ANGLE", angle([w,0,0], [w,0,h]));
         polyhedron(
             [[0,-l,0],[w,-l,-h],[w,l,-h],[0,l,0],[w,-l,0],[w,l,0]],
             wedge_faces
         );
     }
     else if (type == wedge_above_xy)
     {
         polyhedron(
             [[0,-l,0],[w,-l,0],[w,l,0],[0,l,0],[w,-l,h],[w,l,h]],
             wedge_faces
         );
     }
     else
     {
         ASSERT(false, str("Wedge type not valid value (", type, ") when calling module wedge()."));
     }
 }

}
module ASSERT(x, msg)
{
if (!x)
{
if (msg == undef)
{
echo(str(" ASSERT FAILURE:  No message."));
}
else
{
echo(str(" ASSERT FAILURE:  ", msg, ""));
}
}
}

function is_matrix(x)  = len(x) != undef && (x[0] != x[0][0] || len(x) != len(str(x)));

// head
translate([0,0,44])
head();

The 2nd last line when not commented out, will result in an STL that is a
bit corrupted. Very weird, and definitely very wrong.

Tested in OpenSCAD version 2016.10.04 (git 7e0935d) and OpenSCAD version
2015.03-2


View this message in context: Re: STL is unreadable or not 'watertight'
http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20652.html
Sent from the OpenSCAD mailing list archive http://forum.openscad.org/
at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

With or without the translation it has 8 holes according to netfabb and lots of degenerate faces. They seem to be where the hair joins the head. Possibly it needs to overlap a bit. The way a translate can break things (although in this case it seems broken anyway) is that the precision of floating point numbers gets less as they get bigger. When you have very close vertices they can collapse when made more distant from the origin. On 28 February 2017 at 15:43, adrian <adrianh.bsc@gmail.com> wrote: > Ok. So the problem is a translation() call is messing up the geometry. > Here is here is the code: > > $fn=34; > > module mirror2(rot) > { > rotate(rot/2) > children(); > > rotate(-rot/2) > mirror([1,0,0]) > children(); > } > > module eye(inner=true, outer=true) > { > if (inner) > { > if (outer) > { > difference() > { > object(0); > object(wallThickness); > } > } > else > { > object(0); > } > } > else > { > object(wallThickness); > } > module object(thickness) > { > // eye (outer wall) > translate([-4,-5.1,4]) > rotate([-90,0,-20]) > scale([1.8, 1.1, 1]) > sphere(d=2-thickness*2); > } > } > > module headSphere(inner=true, outer=true) > { > if (inner) > { > if (outer) > { > difference() > { > object(0); > object(wallThickness); > } > } > else > { > object(0); > } > } > else > { > object(wallThickness); > } > module object(thickness) > { > translate([0,0,-2]) > scale([1.3, 1.1, 1.3]) > sphere(d=15-thickness*2); > } > } > > module mouth(inner=true, outer=true) > { > if (inner) > { > if (outer) > { > difference() > { > object(wallThickness); > object(0); > } > } > else > { > object(wallThickness); > } > } > else > { > object(0); > } > > module object(thickness) > { > // mouth (outer wall) > translate([0,-7.5,-2]) > rotate([-45,0,0]) > scale([1.8, 1.1, 1]) > sphere(d=5+thickness*2); > } > } > > module alignmentHolder(inner=true, outer=true) > { > if (inner) > { > if (outer) > { > difference() > { > object(wallThickness); > object(0); > } > } > else > { > object(wallThickness); > } > } > else > { > object(0); > } > > module object(thickness) > { > mirror2(0) > translate([1.2-.4-thickness/2, 2, -4+.15]) > rotate([0,90,0]) > cylinder(d=5.4+thickness,h=.4*5+thickness); > } > } > > module neckHollow(inner=true, outer=true) > { > if (inner) > { > if (outer) > { > difference() > { > object(wallThickness); > object(0); > } > } > else > { > object(wallThickness); > } > } > else > { > object(0); > } > > module object(thickness) > { > translate([0,0,thickness]) > // neck hollow > translate([0,0,33-44]) > scale_([1.3, 4.5, 1], undef, [0, 2, 0]) > hull() > { > translate([0,2,neckHeight]) > cube([5,.001,.001], center=true); > scale([1.3, 1.1, 1]) > translate([0,0,-1.2]) > linear_extrude(.0001) > circle(d=10); > } > } > } > > > module hair(inner=true, outer=true) > { > if (inner) > { > if (outer) > { > difference() > { > object(0); > object(wallThickness); > } > } > else > { > object(0); > } > } > else > { > object(wallThickness); > } > > module object(thickness) > { > difference() > { > //mirror2(0) > translate([0,0,-15/2-(1.8)]) > side(thickness); > neckHollow(inner=false); > } > module side(thickness) > { > h = 1; > translate([0,0, h+(thickness ? .00001+thickness : 0)]) > difference() > { > linear_extrude(15/2-h) > offset(r=-thickness) > hair2d(); > } > //neckHollow(outer=false); > } > module hair2d() > { > intersection() > { > projection() > headSphere(outer=false); > translate([-15, -3]) > square([30,15]); > } > } > } > } > > module weight() > { > translate([0,2,-4+.15]) > rotate([90,90,0]) > wedge(10, 60, wedge_centred); > } > preview = 0; > neckHeight=5.5*1.3; > wallThickness=.4; > module head() > { > difference() > { > if(1) > { > // eye > mirror2(0) > difference() > { > eye(); > headSphere(inner=false); > } > > //mouth > intersection() > { > mouth(); > headSphere(inner=false); > } > > // neck hollow > difference() > { > intersection() > { > neckHollow(); > headSphere(outer=false); > } > alignmentHolder(outer=false); > } > > // alignment holder > difference() > { > alignmentHolder(); > neckHollow(inner=false); > } > > // hair > difference() > { > hair(); > headSphere(inner=false); > } > > // weight inside of head > difference() > { > intersection() > { > weight(); > union(1) > { > headSphere(inner=false); > hair(inner=false); > } > } > neckHollow(inner=false); > alignmentHolder(outer=false); > } > > // head > difference() > { > headSphere(); > > mirror2(0) > eye(inner=false); > > mouth(inner=false); > > neckHollow(outer=false); > > alignmentHolder(outer=false); > > hair(inner=false); > } > } > if (preview) > { > // used to see within head > translate([6.4,-5,-15/2]) > cube([20,7,15]); > } > } > } > > module scale_(a, v, offset) > { > translate(offset) > scale(a) > translate(-offset) > children(); > } > > wedge_below_xy = 0; > wedge_above_xy = 1; > wedge_centred = 2; > > // wedge > // > // Generates a wedge which is off to the right of the y-axis and is centred on > // the x-axis. > // > // Primary purporse of wedge is to produce a wedge for intersecting with an > // object. > // > // size > // - is matrix then > // length = size[0]*2 (y-axis) > // width = size[1] (x-axis) > // height = size[2] (z-axis) > // angle = has no meaning in this context > // - is a value then > // specifies the half base size along xy-plane > // length = size*2 (y-axis) > // width = size (x-axis) > // - if angle is undefined then > // height = size. > // else > // height = tan(angle)*size. > // type > // - is wedge_centred then wedge is centred around the xy-plane > // (See Figure 1) > // - is wedge_above_xy then wedge is above the xy-plane > // (See Figure 2) > // - is wedge_below_xy then wedge is below the xy-plane > // (See Figure 2) > // > // E.g. Figure 1: wedge_centred > // > // y-axis z-axis > // > // |<-width->| | > // |_________. ___ | ___ > // | | ^ | /| ^ > // | | | | / | | > // | | | | / | | > // | | | | / | | > // | | length/2 | / | height > // | | | | / | | > // | | | | / angle| | > // | | v |/ | | | > // --+ |------ x-axis ---+ <-+ |---|-- > // | | |\ | | > // | | | \ | | > // | | | \ | | > // | | | \ | | > // | | | \ | | > // | | | \ | | > // | | | \ | | > // |_________| | \| _v_ > // | | > // | | > // > // E.g. Figure 2: wedge_above_xy and wedge_below_xy > // > // y-axis z-axis z-axis > // > // |<-width->| | | > // |_________. ___ | ___ | > // | | ^ | /| ^ | > // | | | | / | | | > // | | | | / | | | > // | | | | / | | | > // | | length/2 | / | height | > // | | | | / | | | angle > // | | | | / | | | | > // | | v |/ | v | v > // --+ |------ x-axis ---+--------+------ ---+--------+------ > // | | | ^ |\ | ^ > // | | | | | \ | | > // | | | angle | \ | | > // | | | | \ | height > // | | | | \ | | > // | | | | \ | | > // | | | | \ | | > // |_________| | | \| _v_ > // | | | > // | | | > // > module wedge(size, angle, type) > { > ASSERT(type != undef, "Specify type of wedge"); > if (is_matrix(size)) > { > w(size[0], size[1], size[2], type); > } > else > { > if (angle == undef) > { > w(size, size, size, type); > } > else > { > //echo(size=size,angle=angle); > ASSERT(-180 < angle && angle < 180 > , str("Wedge angle is ", angle, " but must be between (-180, 180)")); > if (angle >= 0) > { > w(size, size, tan(type == wedge_centred ? angle/2 : angle)*size, type); > } > else > { > // If angle is < 0 then make positive and use below type if above > // or vice versa. This results in the same wedge but keeps the > // face normals going in the correct direction. > w(size, size, tan(type == wedge_centred ? -angle/2 : -angle)*size > , type == wedge_centred ? wedge_centred : !type); > } > > } > } > > module w(l, w, h, type) > { > wedge_faces = [[0,1,2,3],[3,5,4,0],[4,1,0],[2,5,3],[4,5,2,1]]; > if (type == wedge_centred) > { > polyhedron( > [[0,-l,0],[w,-l,-h],[w,l,-h],[0,l,0],[w,-l,h],[w,l,h]], > wedge_faces > ); > } > else if (type == wedge_below_xy) > { > echo("ANGLE", angle([w,0,0], [w,0,h])); > polyhedron( > [[0,-l,0],[w,-l,-h],[w,l,-h],[0,l,0],[w,-l,0],[w,l,0]], > wedge_faces > ); > } > else if (type == wedge_above_xy) > { > polyhedron( > [[0,-l,0],[w,-l,0],[w,l,0],[0,l,0],[w,-l,h],[w,l,h]], > wedge_faces > ); > } > else > { > ASSERT(false, str("Wedge type not valid value (", type, ") when calling module wedge().")); > } > } > } > module ASSERT(x, msg) > { > if (!x) > { > if (msg == undef) > { > echo(str(" ASSERT FAILURE: No message.")); > } > else > { > echo(str(" ASSERT FAILURE: ", msg, "")); > } > } > } > > function is_matrix(x) = len(x) != undef && (x[0] != x[0][0] || len(x) != len(str(x))); > > // head > translate([0,0,44]) > head(); > > The 2nd last line when not commented out, will result in an STL that is a > bit corrupted. Very weird, and definitely very wrong. > > Tested in OpenSCAD version 2016.10.04 (git 7e0935d) and OpenSCAD version > 2015.03-2 > > ------------------------------ > View this message in context: Re: STL is unreadable or not 'watertight' > <http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20652.html> > Sent from the OpenSCAD mailing list archive <http://forum.openscad.org/> > at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >
A
adrian
Tue, Feb 28, 2017 9:05 PM

Then this is an export issue, or a point representation issue? Or is it a
coplanar face issue?

Might have to finally open up the code and take a look at the export.

--
View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20666.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Then this is an export issue, or a point representation issue? Or is it a coplanar face issue? Might have to finally open up the code and take a look at the export. -- View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20666.html Sent from the OpenSCAD mailing list archive at Nabble.com.
W
wolf
Tue, Feb 28, 2017 9:19 PM

Hi Adrian
Your problem is most likely internal rounding errors, which cause
"degenerate triangles" when OpenSCAD generates the .stl file. "Degenerate
triangles" are faces where at least one altitude is near zero (not, as is
often claimed, the triangle area is near zero). A near zero altitude does
lead to a poorly defined face normal, a crack, or even a reversal of face
orientation - all meaning that e.g. boolean operations on such a .stl file
are impossible. There are further consequences, which I need not detail
here, as you cannot influence them writing an OpenSCAD script.

There are many ways to generate "degenerate triangles". In your code, I spot
many 90 degree rotations, which are a sure way to cause internal rounding
errors, and thus "broken" .stl files. Remove them.
Also scan your code for other opportunities to generate faces with near-zero
altitude, such as scaling. Translations are very low on my list of
candidates that generate broken .stl files. Near-zero, by the way, means 3-5
powers of 10 below the largest length that you use. In that sense, using
cubes like [5,.001,.001] is dangerous, and so is linear_extrude(.0001)

For my colleagues, let me add here two pieces of code, to demonstrate what I
have said. The first one generates a shape that cannot be subjected to
further boolean operations:
// source:
https://github.com/openscad/openscad/blob/master/testdata/scad/3D/issues/issue1258.scad

difference() {
translate([-6, 4, 30]) cube(size = [17.5, 48, 60], center = true);
translate([-10.5, 3, 30]) cube(size = [20.5, 55, 80], center = true);
}

translate([-0.25, -19, 33])
rotate([0, 90, 0])
rotate([0, 0, -45])
cube(size = [15, 15, 3], center = false);

This code generates the same shape, and can be subjected to further boolean
operations. Notice how I have replaced the 90 degree rotation with changes
elsewhere to arrive at the same shape:
difference() {
translate([-6, 4, 30]) cube(size = [17.5, 48, 60], center = true);
translate([-10.5, 3, 30]) cube(size = [20.5, 55, 80], center = true);
}
translate([-0.25, -19, 33])
rotate([45,0,0])
cube(size = [3, 15, 15], center = false);

Create .stl files from both, and have a look at the faces and edges present,
to see examples of some of the further consequences I mentioned above:
vertices where there should be none and faces that should not be present.

wolf

--
View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20667.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Hi Adrian Your problem is most likely internal rounding errors, which cause "degenerate triangles" when OpenSCAD generates the .stl file. "Degenerate triangles" are faces where at least one altitude is near zero (not, as is often claimed, the triangle area is near zero). A near zero altitude does lead to a poorly defined face normal, a crack, or even a reversal of face orientation - all meaning that e.g. boolean operations on such a .stl file are impossible. There are further consequences, which I need not detail here, as you cannot influence them writing an OpenSCAD script. There are many ways to generate "degenerate triangles". In your code, I spot many 90 degree rotations, which are a sure way to cause internal rounding errors, and thus "broken" .stl files. Remove them. Also scan your code for other opportunities to generate faces with near-zero altitude, such as scaling. Translations are very low on my list of candidates that generate broken .stl files. Near-zero, by the way, means 3-5 powers of 10 below the largest length that you use. In that sense, using cubes like [5,.001,.001] is dangerous, and so is linear_extrude(.0001) For my colleagues, let me add here two pieces of code, to demonstrate what I have said. The first one generates a shape that cannot be subjected to further boolean operations: // source: https://github.com/openscad/openscad/blob/master/testdata/scad/3D/issues/issue1258.scad difference() { translate([-6, 4, 30]) cube(size = [17.5, 48, 60], center = true); translate([-10.5, 3, 30]) cube(size = [20.5, 55, 80], center = true); } translate([-0.25, -19, 33]) rotate([0, 90, 0]) rotate([0, 0, -45]) cube(size = [15, 15, 3], center = false); This code generates the same shape, and can be subjected to further boolean operations. Notice how I have replaced the 90 degree rotation with changes elsewhere to arrive at the same shape: difference() { translate([-6, 4, 30]) cube(size = [17.5, 48, 60], center = true); translate([-10.5, 3, 30]) cube(size = [20.5, 55, 80], center = true); } translate([-0.25, -19, 33]) rotate([45,0,0]) cube(size = [3, 15, 15], center = false); Create .stl files from both, and have a look at the faces and edges present, to see examples of some of the further consequences I mentioned above: vertices where there should be none and faces that should not be present. wolf -- View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20667.html Sent from the OpenSCAD mailing list archive at Nabble.com.
W
wolf
Tue, Feb 28, 2017 11:08 PM

What I should have added to my previous post:

difference()
{
union()
{
translate([-10, -19, 33])  rotate([0, 90, 0])  rotate([0, 0, -45])
cube(size = [15, 15,15], center = false);
translate([-3, 4, 30]) cube(size = [17.5, 48, 60], center = true);
}
translate([-10.25, 3, 30]) cube(size = [20, 75, 80], center = true);
translate([12.75, 3, 30]) cube(size = [20, 75, 80], center = true);
}

This is the proper way to create the shape, as it has the proper meshing on
both sides, and the rounding issues due to  rotate([0, 90, 0]) have been
wiped out. With no rounding issues present, there are also no "degenerate
triangles" and thus no problems with further boolean operations.

wolf

--
View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20671.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

What I should have added to my previous post: difference() { union() { translate([-10, -19, 33]) rotate([0, 90, 0]) rotate([0, 0, -45]) cube(size = [15, 15,15], center = false); translate([-3, 4, 30]) cube(size = [17.5, 48, 60], center = true); } translate([-10.25, 3, 30]) cube(size = [20, 75, 80], center = true); translate([12.75, 3, 30]) cube(size = [20, 75, 80], center = true); } This is the proper way to create the shape, as it has the proper meshing on both sides, and the rounding issues due to rotate([0, 90, 0]) have been wiped out. With no rounding issues present, there are also no "degenerate triangles" and thus no problems with further boolean operations. wolf -- View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20671.html Sent from the OpenSCAD mailing list archive at Nabble.com.
A
adrian
Wed, Mar 1, 2017 3:59 AM

Thanks Wolf,

I don't know the API yet, but that a 90 degree rotation causes degenerate
faces is definitely a bug.  I'll try and take a look at this sometime in the
next couple of weeks as this is completely unacceptable.

--
View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20678.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Thanks Wolf, I don't know the API yet, but that a 90 degree rotation causes degenerate faces is definitely a bug. I'll try and take a look at this sometime in the next couple of weeks as this is completely unacceptable. -- View this message in context: http://forum.openscad.org/STL-is-unreadable-or-not-watertight-tp20642p20678.html Sent from the OpenSCAD mailing list archive at Nabble.com.