Discussion:
[OpenSCAD] Vectors, Lists, and Strings
Dan Shriver
2018-08-29 18:50:17 UTC
Permalink
I'm having some issues with datatypes in OpenScad and wondering what the
best approach is.

I am recursively calling functions that return lists (or vectors) of tuples
such as: [[0,1], [5,3]] and trying to concatenate them together. The
problem is that the nesting level increases. What I want is one
list/vector of tuples and no subnesting.

I've tried some approaches to flattening the results but usually it ends up
getting rid of the tuples (which I want) and keeping the arbitrary nesting
above them (which I don't want).

The other thing I tried is to have the function return just the tuples (not
in a list) but that gives an error.

Could I take a string of tuples, concatenate them and do something to
transform it into a list of tuples?
doug moen
2018-08-29 20:39:07 UTC
Permalink
Post the code that isn't working, and we will help you to fix it.
Post by Dan Shriver
I'm having some issues with datatypes in OpenScad and wondering what the
best approach is.
I am recursively calling functions that return lists (or vectors) of
tuples such as: [[0,1], [5,3]] and trying to concatenate them together.
The problem is that the nesting level increases. What I want is one
list/vector of tuples and no subnesting.
I've tried some approaches to flattening the results but usually it ends
up getting rid of the tuples (which I want) and keeping the arbitrary
nesting above them (which I don't want).
The other thing I tried is to have the function return just the tuples
(not in a list) but that gives an error.
Could I take a string of tuples, concatenate them and do something to
transform it into a list of tuples?
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Dan Shriver
2018-08-29 21:35:22 UTC
Permalink
Here is the code
If i use "flatten" on each one of the recursive calls I get all the depth
and none of the tuples.
Here I get both

--------------------
// Echo expression and return it
function echoit(x) = echo(x) x;
//echo with label
function echoit2(x,y) = echo(x,y) y;

/*
function fixVector(vectorOfVectors) for(a = vectorOfVectors)a;
*/

function flatten(l) = [ for (a = l) for (b = a) b ] ;

//given nested lists of arbitrary levels, make it a list of points
function makePointList(L,n=0,res=[]) =
n>=len(L) ?
res
: L[n]*0==[0,0] ?
makePointList(L,n+1, concat(res,[L[n]]))
: makePointList(L,n+1, makePointList(L[n],0,res));

function arcx(radius,startAngle,endAngle,pointsPerGeneration,i,offsetx=0) =
let ( span = endAngle - startAngle, step = span/pointsPerGeneration, angle
= startAngle + (step * i) ) radius * cos(angle) + offsetx;

function arcy(radius,startAngle,endAngle,pointsPerGeneration,i,offsety=0) =
let ( span = endAngle - startAngle, step = span/pointsPerGeneration, angle
= startAngle + (step * i) ) radius * sin(angle) + offsety;

function loopArc(radius, number, generations, quadrant,
pointsPerGeneration, angle, direction, offsetx=0, offsety=0) =
(generations > 1) ?
(direction > 0) ? let(newQuadrant = (quadrant + 1) % 4,
startAngle = angle,
newRadius = (radius/2) * sin(atan(2/(number -1))),
newx = offsetx + (newRadius * (number -1)),
newy = offsety + newRadius,
endAngle = computeAngle(number, newQuadrant))
[ for (i = [0:pointsPerGeneration])
[arcx(radius,startAngle,endAngle,pointsPerGeneration, i, newx),
arcy(newy,radius,startAngle,endAngle,pointsPerGeneration, i, newy),
loopArc(newRadius, number, (generations-1),newQuadrant,
pointsPerGeneration,endAngle,1,newx,newy)]]

: let( newQuadrant = (quadrant + 3) % 4,
newRadius = (radius/2) * sin(atan(2/(number -1))),
startAngle = computeAngle(number, newQuadrant),
newx = offsetx + (newRadius * (number -1)),
newy = offsety + newRadius,
endAngle = angle)
[ for (i = [0:pointsPerGeneration]) [ loopArc(newRadius, number,
(generations-1),newQuadrant, pointsPerGeneration,endAngle,-1,newx,newy),
arcx(radius,startAngle,endAngle,pointsPerGeneration, i, newx),
arcy(radius,startAngle,endAngle,pointsPerGeneration, i, newy)]] :

(direction > 0) ? let(newQuadrant = (quadrant + 1) % 4,
startAngle = angle,
newRadius = (radius/2) * sin(atan(2/(number -1))),
newx = offsetx + (newRadius * (number -1)),
newy = offsety + newRadius,
endAngle = computeAngle(number, newQuadrant))
[ for (i = [0:pointsPerGeneration])
[arcx(radius,startAngle,endAngle,pointsPerGeneration, i, newx),
arcy(radius,startAngle,endAngle,pointsPerGeneration, i, newy)]]

: let( newQuadrant = (quadrant + 3) % 4,
newRadius = (radius/2) * sin(atan(2/(number -1))),
startAngle = echoit2("startAngle via computeAngle
",computeAngle(number, newQuadrant)),
newx = echoit2("newx ",offsetx + (newRadius * (number -1))),
newy = echoit2("newy ",offsety + newRadius),
endAngle = echoit2("endAngle ",angle))
[ for (i = [0:pointsPerGeneration]) [
arcx(radius,startAngle,endAngle,pointsPerGeneration, i, newx),
arcy(radius,startAngle,endAngle,pointsPerGeneration, i, newy)]]
;


//there is a list of values
//[quadrant - 1] peels off the
//value from the list for returning
function computeAngle(number, quadrant) =
let(baseAngle = atan(2/(number-1)))
[
baseAngle,
180 - baseAngle,
180 + baseAngle,
360 - baseAngle
][quadrant];

echo(computeAngle(4,1));

function nextQuadrant(quadrant) = (quadrant + 1) % 4;


//quadrant is the graph quadrant for the next circle except it is C indexed
so it is 0 - 3 rather than 1 - 4
module bCurve(radius, number, generations, quadrant, pointsPerGeneration) {

numPoints = pointsPerGeneration - 1;

laterQuadrant = nextQuadrant(quadrant);

earlierQuadrant = (quadrant + 3) % 4;

startAngle = computeAngle(number,quadrant);
endAngle = computeAngle(number,laterQuadrant);

echo("start angle ",startAngle," end angle ",endAngle," quadrant
",quadrant," next quadrant ", laterQuadrant," earlier quadrant
",earlierQuadrant);

newRadius = (radius/2) * sin(atan(2/(number-1)));

points = (generations > 1) ? [ for (i = [0:(numPoints)]) [
loopArc(newRadius, number, (generations-1),earlierQuadrant,
numPoints,endAngle,-1), arcx(radius,startAngle,endAngle,numPoints, i),
arcy(radius,startAngle,endAngle,numPoints, i), loopArc(newRadius, number,
(generations-1),laterQuadrant, numPoints,endAngle,1)]] :
[ for (i = [0:(numPoints)]) [
arcx(radius,startAngle,endAngle,numPoints, i),
arcy(radius,startAngle,endAngle,numPoints, i)]]
;

echo("POINTS ARE: ",points);

//poly = makePointList(points);

//poly = flatten(points);

echo("*****************POLY IS: ",poly);


difference() {
offset(0.01) polygon(poly);
polygon(poly);
}

//make the nested lists into one flat list
/* poly = makePointList(points);

echo(poly);

difference() {
offset(0.01) polygon(poly);
polygon(poly);
}
*/
}


bCurve(30,2,2,0,10);
Post by doug moen
Post the code that isn't working, and we will help you to fix it.
Post by Dan Shriver
I'm having some issues with datatypes in OpenScad and wondering what the
best approach is.
I am recursively calling functions that return lists (or vectors) of
tuples such as: [[0,1], [5,3]] and trying to concatenate them together.
The problem is that the nesting level increases. What I want is one
list/vector of tuples and no subnesting.
I've tried some approaches to flattening the results but usually it ends
up getting rid of the tuples (which I want) and keeping the arbitrary
nesting above them (which I don't want).
The other thing I tried is to have the function return just the tuples
(not in a list) but that gives an error.
Could I take a string of tuples, concatenate them and do something to
transform it into a list of tuples?
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Ronaldo Persiano
2018-08-29 23:45:09 UTC
Permalink
If I have understood well the question of your first message, the
function makePointList is the only concern here.

Depending what your input vector is, makePointList may be a correct
solution. It does work for nested lists of 2D points but it fails if
something else appears in the input list.

a = [[0,0],[1,1],[[1,2]], [[2,3],[[3,4]]]];
echo(makePointList(a));
// ECHO : [ [0,0], [1,1], [1,2], [2,3],[[3,4] ]

b = [["x",0],[1,1],[[1,2]], [[2,3],[[3,4]]]];
echo(makePointList(b));
// Recursion stack overflow

c = [[0,0],[1,1],[[1,2]], [0, [2,3],[[3,4]]]];
echo(makePointList(c));
// Recursion stack overflow

The other thing I tried is to have the function return just the tuples (not
Post by Dan Shriver
in a list) but that gives an error.
AFAIK, there is no way to represent tuples in OpenSCAD other than lists.
The function fixVector will give a sintax error.
Post by Dan Shriver
Here is the code
If i use "flatten" on each one of the recursive calls I get all the depth
and none of the tuples.
Here I get both
--------------------
// Echo expression and return it
function echoit(x) = echo(x) x;
//echo with label
function echoit2(x,y) = echo(x,y) y;
/*
function fixVector(vectorOfVectors) for(a = vectorOfVectors)a;
*/
function flatten(l) = [ for (a = l) for (b = a) b ] ;
//given nested lists of arbitrary levels, make it a list of points
function makePointList(L,n=0,res=[]) =
n>=len(L) ?
res
: L[n]*0==[0,0] ?
makePointList(L,n+1, concat(res,[L[n]]))
: makePointList(L,n+1, makePointList(L[n],0,res));
function arcx(radius,startAngle,endAngle,pointsPerGeneration,i,offsetx=0)
= let ( span = endAngle - startAngle, step = span/pointsPerGeneration,
angle = startAngle + (step * i) ) radius * cos(angle) + offsetx;
function arcy(radius,startAngle,endAngle,pointsPerGeneration,i,offsety=0)
= let ( span = endAngle - startAngle, step = span/pointsPerGeneration,
angle = startAngle + (step * i) ) radius * sin(angle) + offsety;
function loopArc(radius, number, generations, quadrant,
pointsPerGeneration, angle, direction, offsetx=0, offsety=0) =
(generations > 1) ?
(direction > 0) ? let(newQuadrant = (quadrant + 1) % 4,
startAngle = angle,
newRadius = (radius/2) * sin(atan(2/(number -1))),
newx = offsetx + (newRadius * (number -1)),
newy = offsety + newRadius,
endAngle = computeAngle(number, newQuadrant))
[ for (i = [0:pointsPerGeneration])
[arcx(radius,startAngle,endAngle,pointsPerGeneration, i, newx),
arcy(newy,radius,startAngle,endAngle,pointsPerGeneration, i, newy),
loopArc(newRadius, number, (generations-1),newQuadrant,
pointsPerGeneration,endAngle,1,newx,newy)]]
: let( newQuadrant = (quadrant + 3) % 4,
newRadius = (radius/2) * sin(atan(2/(number -1))),
startAngle = computeAngle(number, newQuadrant),
newx = offsetx + (newRadius * (number -1)),
newy = offsety + newRadius,
endAngle = angle)
[ for (i = [0:pointsPerGeneration]) [ loopArc(newRadius, number,
(generations-1),newQuadrant, pointsPerGeneration,endAngle,-1,newx,newy),
arcx(radius,startAngle,endAngle,pointsPerGeneration, i, newx),
(direction > 0) ? let(newQuadrant = (quadrant + 1) % 4,
startAngle = angle,
newRadius = (radius/2) * sin(atan(2/(number -1))),
newx = offsetx + (newRadius * (number -1)),
newy = offsety + newRadius,
endAngle = computeAngle(number, newQuadrant))
[ for (i = [0:pointsPerGeneration])
[arcx(radius,startAngle,endAngle,pointsPerGeneration, i, newx),
arcy(radius,startAngle,endAngle,pointsPerGeneration, i, newy)]]
: let( newQuadrant = (quadrant + 3) % 4,
newRadius = (radius/2) * sin(atan(2/(number -1))),
startAngle = echoit2("startAngle via computeAngle
",computeAngle(number, newQuadrant)),
newx = echoit2("newx ",offsetx + (newRadius * (number -1))),
newy = echoit2("newy ",offsety + newRadius),
endAngle = echoit2("endAngle ",angle))
[ for (i = [0:pointsPerGeneration]) [
arcx(radius,startAngle,endAngle,pointsPerGeneration, i, newx),
arcy(radius,startAngle,endAngle,pointsPerGeneration, i, newy)]]
;
//there is a list of values
//[quadrant - 1] peels off the
//value from the list for returning
function computeAngle(number, quadrant) =
let(baseAngle = atan(2/(number-1)))
[
baseAngle,
180 - baseAngle,
180 + baseAngle,
360 - baseAngle
][quadrant];
echo(computeAngle(4,1));
function nextQuadrant(quadrant) = (quadrant + 1) % 4;
//quadrant is the graph quadrant for the next circle except it is C
indexed so it is 0 - 3 rather than 1 - 4
module bCurve(radius, number, generations, quadrant, pointsPerGeneration) {
numPoints = pointsPerGeneration - 1;
laterQuadrant = nextQuadrant(quadrant);
earlierQuadrant = (quadrant + 3) % 4;
startAngle = computeAngle(number,quadrant);
endAngle = computeAngle(number,laterQuadrant);
echo("start angle ",startAngle," end angle ",endAngle," quadrant
",quadrant," next quadrant ", laterQuadrant," earlier quadrant
",earlierQuadrant);
newRadius = (radius/2) * sin(atan(2/(number-1)));
points = (generations > 1) ? [ for (i = [0:(numPoints)]) [
loopArc(newRadius, number, (generations-1),earlierQuadrant,
numPoints,endAngle,-1), arcx(radius,startAngle,endAngle,numPoints, i),
arcy(radius,startAngle,endAngle,numPoints, i), loopArc(newRadius, number,
[ for (i = [0:(numPoints)]) [
arcx(radius,startAngle,endAngle,numPoints, i),
arcy(radius,startAngle,endAngle,numPoints, i)]]
;
echo("POINTS ARE: ",points);
//poly = makePointList(points);
//poly = flatten(points);
echo("*****************POLY IS: ",poly);
difference() {
offset(0.01) polygon(poly);
polygon(poly);
}
//make the nested lists into one flat list
/* poly = makePointList(points);
echo(poly);
difference() {
offset(0.01) polygon(poly);
polygon(poly);
}
*/
}
bCurve(30,2,2,0,10);
Post by doug moen
Post the code that isn't working, and we will help you to fix it.
Post by Dan Shriver
I'm having some issues with datatypes in OpenScad and wondering what the
best approach is.
I am recursively calling functions that return lists (or vectors) of
tuples such as: [[0,1], [5,3]] and trying to concatenate them together.
The problem is that the nesting level increases. What I want is one
list/vector of tuples and no subnesting.
I've tried some approaches to flattening the results but usually it ends
up getting rid of the tuples (which I want) and keeping the arbitrary
nesting above them (which I don't want).
The other thing I tried is to have the function return just the tuples
(not in a list) but that gives an error.
Could I take a string of tuples, concatenate them and do something to
transform it into a list of tuples?
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
TLC123
2018-08-30 16:13:09 UTC
Permalink
I'd do it like this:
ECHO: 1, [[0, 0], [1, 1], [1, 2], [2, 3], [3, 4]]
ECHO: true
ECHO: false
ECHO: false
ECHO: true
ECHO: [[0, 0], [1, 1], [1, 2], [2, 3], [3, 4]]
ECHO: [[1, 0, 0], [1, 1, 1], [1, 2, 2]]
ECHO: [[1, 1, 1], [1, 2, 1]]

effectively filtering out anything not your vertex type






a = [[0,0],[1,1],[[1,2]], [[2,3],[[3,4]]]];
echo(1,makePointListvec2(a));
echo(ismytypevec2([1,1]));
echo(ismytypevec2([1,1,1]));
echo(ismytypevec3([1,1]));
echo(ismytypevec3([1,1,1]));
// ECHO : [ [0,0], [1,1], [1,2], [2,3],[[3,4] ]

//
//b = [["x",0],[1,1],[[1,2]], [[2,3],[[3,4]]]];
//echo(makePointListvec2(b));
// Recursion stack overflow

c0 = [[0,0],[1,1],[[1,2]], [0, [2,3],[[3,4]]]];
echo(makePointListvec2(c0));
c1 = [[1,0,0],[1,1,1],[[1,2,2]], [1,0, [2,3],[[3,4]]]];
echo(makePointListvec3(c1));
c2 = [[0,0],[1,1,1],[[1,2,1]], [0, [2,3],[[3,4]]]];
echo(makePointListvec3(c2));

function makePointListvec2(a,c=0,result=[])= c<len(a) ?
makePointListvec2(a,c+1,concat(result,ismytypevec2(a[c])?[a[c]]:
makePointListvec2(a[c],0,[]) ) ) :result;
function ismytypevec2(d)= len(d)==2&&len(d[0])==undef&&len(d[1])==undef
;


function makePointListvec3(a,c=0,result=[])= c<len(a) ?
makePointListvec3(a,c+1,concat(result,ismytypevec3(a[c])?[a[c]]:
makePointListvec3(a[c],0,[]) ) ) :result;
function ismytypevec3(d)=
len(d)==3&&len(d[0])==undef&&len(d[1])==undef&&len(d[2])==undef ;



--
Sent from: http://forum.openscad.org/
Dan Shriver
2018-08-30 17:05:12 UTC
Permalink
Ronaldo was right: The problem was some "naked" (no "[]") tuples. When I
corrected that makePointList() worked.

Unfortunately, if I have generations > 1 I get lots of tuples with one
coordinate being a tiny number (-5.32907e-015) either that is throwing off
drawing the polygon or my points are in the wrong order.
Post by TLC123
ECHO: 1, [[0, 0], [1, 1], [1, 2], [2, 3], [3, 4]]
ECHO: true
ECHO: false
ECHO: false
ECHO: true
ECHO: [[0, 0], [1, 1], [1, 2], [2, 3], [3, 4]]
ECHO: [[1, 0, 0], [1, 1, 1], [1, 2, 2]]
ECHO: [[1, 1, 1], [1, 2, 1]]
effectively filtering out anything not your vertex type
a = [[0,0],[1,1],[[1,2]], [[2,3],[[3,4]]]];
echo(1,makePointListvec2(a));
echo(ismytypevec2([1,1]));
echo(ismytypevec2([1,1,1]));
echo(ismytypevec3([1,1]));
echo(ismytypevec3([1,1,1]));
// ECHO : [ [0,0], [1,1], [1,2], [2,3],[[3,4] ]
//
//b = [["x",0],[1,1],[[1,2]], [[2,3],[[3,4]]]];
//echo(makePointListvec2(b));
// Recursion stack overflow
c0 = [[0,0],[1,1],[[1,2]], [0, [2,3],[[3,4]]]];
echo(makePointListvec2(c0));
c1 = [[1,0,0],[1,1,1],[[1,2,2]], [1,0, [2,3],[[3,4]]]];
echo(makePointListvec3(c1));
c2 = [[0,0],[1,1,1],[[1,2,1]], [0, [2,3],[[3,4]]]];
echo(makePointListvec3(c2));
function makePointListvec2(a,c=0,result=[])= c<len(a) ?
makePointListvec2(a[c],0,[]) ) ) :result;
function ismytypevec2(d)= len(d)==2&&len(d[0])==undef&&len(d[1])==undef
;
function makePointListvec3(a,c=0,result=[])= c<len(a) ?
makePointListvec3(a[c],0,[]) ) ) :result;
function ismytypevec3(d)=
len(d)==3&&len(d[0])==undef&&len(d[1])==undef&&len(d[2])==undef ;
--
Sent from: http://forum.openscad.org/
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Loading...