3D tryckt Ping-Pong boll (4 / 5 steg)
Steg 4: Borrning triangulära hål
I det här avsnittet ska vi titta in i hur man skapar ett mönster av prismor från geodesic sfär ansikten, att vi sedan ska subtrahera från våra bollen från steg 2 att generera faktiska hålen.
Först måste vi skapa prismor från geodesic sfär trianglar.
Det gör skapa vi först en mindre triangel inom varje triangel av en geodetisk linje
sphere av kvittning dess kanter inåt med ett fast avstånd och datoranvändning
skärningspunkter av översatta kanterna som utgör hörnen
i nya triangeln (se bilden ovan).
För att generera prismat, Använd jag den solidFromSlicesmetoden för att pressa den nuvarande triangeln (i1 i2 i3) vinkelrätt till dess yta.
Funktionen createPrism
genererar en prisma från en enhet sfär triangel, en radie och en förskjutning
funktion createPrism (sphereTri, radius, offset)
{/ / beräkna koordinaterna för hörnen i input triangeln
var v1 = nya CSG. Vector3D (scalar_mul (sphereTri [0], radie));
var v2 = nya CSG. Vector3D (scalar_mul (sphereTri [1], radie));
var v3 = nya CSG. Vector3D (scalar_mul (sphereTri [2], radie));
göra plan basera (v1, x, y)
var xAxis = v2.minus(v1).unit();
var v13 = v3.minus(v1);
var yAxis = v13.minus(xAxis.times(v13.dot(xAxis))).unit();
Hämta 2d-koordinater av triangeln hörnen i denna bas
var v1_2d = nya CSG. Vector2D (0, 0);
var v2_2d = nya CSG. Vector2D(v2.minus(v1).dot(xAxis), 0);
var v3_2d = nya CSG. Vector2D(v3.minus(v1).dot(xAxis), v3.minus(v1).dot(yAxis));
få i mitten av varje segment i planet
var v12_2d = v2_2d.minus(v1_2d);
var v23_2d = v3_2d.minus(v2_2d);
var v31_2d = v1_2d.minus(v3_2d);
få enhet vektorn vinkelrätt mot i1i2 segment i planet
var ortho12 = nya CSG. Vector2D (-v12_2d.y, v12_2d.x).unit();
IF(v3_2d.minus(v1_2d).dot(ortho12) < 0)
ortho12 = ortho12.times(-1);
var ortho23 = nya CSG. Vector2D (-v23_2d.y, v23_2d.x).unit();
IF(v1_2d.minus(v2_2d).dot(ortho23) < 0)
ortho23 = ortho23.times(-1);
var ortho31 = nya CSG. Vector2D (-v31_2d.y, v31_2d.x).unit();
IF(v2_2d.minus(v1_2d).dot(ortho31) < 0)
ortho31 = ortho31.times(-1);
översätta alla tri segment inåt genom samma offset
var s12b = translate_segment ([v1_2d, v2_2d], ortho12.times(offset));
var s23b = translate_segment ([v2_2d, v3_2d], ortho23.times(offset));
var s31b = translate_segment ([v3_2d, v1_2d], ortho31.times(offset));
beräkna skärningspunkter av översatta segment i planet
var i1 = skär (s12b, s23b);
var i2 = skär (s23b, s31b);
var i3 = skär (s31b, s12b);
var i1_3d = v1.plus(xAxis.times(i1.x)).plus(yAxis.times(i1.y));
var i2_3d = v1.plus(xAxis.times(i2.x)).plus(yAxis.times(i2.y));
var i3_3d = v1.plus(xAxis.times(i3.x)).plus(yAxis.times(i3.y));
skapa en polygon från skärningspunkter
var tri = nya CSG. Polygon ([
nya CSG. Vertex(i1_3d),
nya CSG. Vertex(i2_3d),
nya CSG. Vertex(i3_3d)
]);
var zAxis = tri.plane.normal;
återgå tri.solidFromSlices({
numslices: 2, / / belopp av skivor
slinga: falsk, / / sista CSG stängs av looping (starta = slutet) som en torus
motringning: function(t,slice) {
ECHO ("t:" + t)
återgå this.translate (scalar_mul ([zAxis.x, zAxis.y, zAxis.z], 4 * t));
}
{}) .translate (scalar_mul ([zAxis.x, zAxis.y, zAxis.z], -2));
}
Multiplicerar en 3d vektor med en skalär
funktion scalar_mul (v, c)
{
tillbaka [c * v [0], c * v [1], c * v [2]];
}
översätter ett 2d segment av en 2d-vektor
funktion translate_segment (seg, vec)
{
S0b = seg[0].plus(vec);
S1B = seg[1].plus(vec);
tillbaka [s0b, s1b];
}
beräknar skärningspunkten mellan 2 2d segment
funktionen intersect (s1, s2)
{
var p = s1 [0];
var q = s2 [0];
var r = s1[1].minus(p);
var s = s2[1].minus(q);
var u = q.minus (p) .cross (r) /r.cross(s);
var t = q.minus (p) .cross(s) /r.cross(s);
om (r.cross(s)! = 0 & & u > = 0 & & u < = 1 & & t > = 0 & & t < = 1)
återvända p.plus(r.times(t));
returnera null;
}
Att använda sig av funktionen createPrism ovanför, whe kan nu generera fullt
hålbild av iteration över geodetiska sfär trianglar:
Hål mönster skript
funktionen Main () {
var ballDiameter = 40; mm
var segmentWidth = 2; mm
var sphereTris = []; innehar lista av geodesic sfär trianglar
addPolyCb = funktion (v1, v2, v3)
{
sphereTris.push([
[v1.x, v1.y, v1.z],
[v2.x, v2.y, v2.z],
[v3.x, v3.y, v3.z]
]);
}
createGeodesicSphere (addPolyCb, 1);
var holePattern;
för (j = 0; j!=sphereTris.length; ++ Jansson)
{
var prisma = createPrism (sphereTris [j], ballDiameter/2., segmentWidth/2.);
IF(j==0)
{
holePattern = prisma;
}
annat
holePattern = holePattern.union(prism);
}
återvända holePattern;
}
funktionen dela upp (v1, v2, v3, addPolyCb, djup)
{
IF(DEPTH == 0) {
addPolyCb (v1, v2, v3);
hemkomst.
}
var v12 = v1.plus(v2).unit();
var v23 = v2.plus(v3).unit();
var v31 = v3.plus(v1).unit();
var newDepth = djup - 1.
Dela upp (v1, v12, v31, addPolyCb, newDepth);
Dela upp (v2 v23, v12, addPolyCb, newDepth);
Dela upp (v3, v31, v23, addPolyCb, newDepth);
Dela upp (v12, v23, v31, addPolyCb, newDepth);
}
funktion createGeodesicSphere (addPolyCb, djup) {
var X = 0.525731112119133606;
var Z = 0.850650808352039932;
var vdata = [
[-X, 0,0, Z], [X, 0,0, Z], [-X, 0,0, -Z], [X, 0,0, -Z],
[0,0, Z, X], [0,0, Z, -X], [0.0, -Z, X], [0.0, -Z, -X],
[Z, X, 0,0], [-Z, X, 0,0], [Z, -X, 0,0], [-Z, -X, 0,0]
];
var tindices = [
[0, 4, 1], [0, 9, 4], [9, 5, 4], [4, 5, 8], [4, 8, 1],
[8, 10, 1], [8, 3, 10], [5, 3, 8], [5, 2, 3], [2, 7, 3],
[7, 10, 3], [7, 6, 10], [7, 11, 6], [11, 0, 6], [0, 1, 6],
[6, 1, 10], [9, 0, 11], [9, 11, 2], [9, 2, 5], [7, 2, 11]
];
för (var jag = 0; jag < 20; i ++)
Dela upp (nya CSG. Vector3D(vdata[tindices[i][0]]),
nya CSG. Vector3D(vdata[tindices[i][1]]),
nya CSG. Vector3D(vdata[tindices[i][2]]),
addPolyCb, djup);
}