Skip to content

Commit 69e3fd3

Browse files
committed
Major enhancements to extrusions
1 parent fceee7d commit 69e3fd3

File tree

11 files changed

+65
-28
lines changed

11 files changed

+65
-28
lines changed

ForInstalledPython/glow.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

GlowScriptOffline/glowscript_libraries/RScompiler.3.0.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

GlowScriptOffline/glowscript_libraries/compiler.3.0.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

GlowScriptOffline/glowscript_libraries/glow.3.0.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

GlowScriptOffline3.0.zip

1.13 KB
Binary file not shown.

docs/VPythonDocs/extrusion.html

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,25 @@
4949
<p class="Normal"><strong>The position of the extrusion</strong> is <strong>ex.pos</strong>: After creating an extrusion named &quot;ex&quot;, <strong>ex.pos</strong> is located at the center of the bounding box. Later changes to ex.pos move the center of the extrusion to a new location. If you specify <span class="attribute">pos</span> when creating the extrusion, the center of the extrusion will be moved to that location, just as if you changed ex.pos after creating the extrusion.</p>
5050
<p class="Normal">After creating an extrusion, changing the axis rotates the combined object. As with some other objects such as sphere or compound, changing the axis does not affect the size.</p>
5151
<p class="Normal"><strong><font color="#0000a0">Other attributes</font></strong></p>
52-
<p class="Normal">An extrusion is made out of <a href="triangle.html">quads</a> and <a href="triangle.html">triangles</a> which are then made into a <a href="compound.html"><strong>compound</strong></a> object for speed of display. You can make additional copies of an extrusion by <a href="clone.html"><strong>cloning</strong></a> it. You can move an extrusion by specifying a new <span class="attribute">pos</span>, and you can change its <span class="attribute">size</span>, <span class="attribute">axis</span>, <span class="attribute">up</span>, <span class="attribute">color</span>, <span class="attribute">opacity</span>, <span class="attribute">shininess</span>, and <span class="attribute">emissive</span>, as with other objects, but note that color is &quot;multiplicative&quot;; see <a href="compound.html"><strong>compound</strong></a>.</p>
52+
<p class="Normal">An extrusion is made out of <a href="triangle.html">quads</a> and <a href="triangle.html">triangles</a> which are then made into a <a href="compound.html"><strong>compound</strong></a> object for speed of display. You can make additional copies of an extrusion by <a href="clone.html"><strong>cloning</strong></a> it. You can move an extrusion by specifying a new <span class="attribute">pos</span>, and you can change its <span class="attribute">size</span>, <span class="attribute">axis</span>, <span class="attribute">up</span>, <span class="attribute">color</span>, <span class="attribute">opacity</span>, <span class="attribute">shininess</span>, and <span class="attribute">emissive</span>, as with other objects. <span class="attributes"><span class="attribute">up </span><span class="attribute"></span> controls the orientation of the initial cross section; default is vec(0,1,0); see the box object for a discussion of this attribute</span>. Note that color is &quot;multiplicative&quot;; see <a href="compound.html"><strong>compound</strong></a>.</p>
5353
<p class="Normal">Here are additional attributes that can be specified when creating an extrusion but cannot be changed later: </p>
54-
<p class="attributes"><span class="attribute">show_start_face</span> and <span class="attribute">show_end_face</span> By default, these attributes are True and the start and end faces are displayed. If you set one of these to False, that face is left open. These attributes have no effect if the path is closed.</p>
55-
<p class="attributes"><span class="attribute">start_face_color</span> and <span class="attribute">end_face_color</span> By default,the starting and ending faces are given the same color as the rest of the extrusion, as specified by <span class="attribute">color</span>, but you can specify that other colors be used for the starting or ending face. These attributes have no effect if the path is closed.</p>
56-
<p class="attributes"><span class="attribute">smooth</span> By default, adjacent normals for which the cosine of the angle between them is greater than 0.95 (corresponding to an angle of 18 degrees) are averaged so as to smooth the adjacent surfaces. You can set <span class="attribute">smooth</span> to a looser criterion for more smoothing. For example, setting smooth=0.9 will smooth adjoining surfaces whose orientation differs by 53 degrees, a much looser criterion.</p>
57-
<p class="Normal"><strong><font color="#0000a0">The three steps to making an extrusion</font></strong></p>
54+
<p class="attributes"><span class="attribute">color</span> You can simply say &quot;color=color.red&quot; to make all the segments red, but you can also say &quot;color = [color.red, color.green, color.blue]&quot;, in which case the first segment will be red, the second will be green, and the third will be blue. The number of colors must be the same as the number of points on the path, so the example here is for an extrusion with three points along the path. At a smooth turn along the path, the colors just before and after the joint are blended together.</p>
55+
<p class="attributes"><span class="attribute">scale</span> If scale is 3, all joints are enlarged by a factor of 3. If instead you give a list of numbers, such as &quot;scale = [2, 3, 0.5.]&quot;, the initial cross section is scaled by a factor of 2, the second by a factor of 3, and the third by a factor of 0.5. The number of scale factors must be the same as the number of points along the path. </p>
56+
<p class="attributes"><span class="attribute">xscale</span> If xscale is 3, all joints are enlarged in the x direction by a factor of 3. If instead you give a list of numbers, such as &quot;xscale = [2, 3, 0.5.]&quot;, the initial x component of the cross section is scaled by a factor of 2, the second by a factor of 3, and the third by a factor of 0.5. The number of xscale factors must be the same as the number of points along the path. <span class="Normal">By default, the starting face of an extrusion is oriented with &quot;up&quot; in the +y direction (unless you specify a different &quot;up&quot; for the extrusion).+x is to the right and +y is up.</span></p>
57+
<p class="attributes"><span class="attribute">yscale</span> If yscale is 3, all joints are enlarged in the y direction by a factor of 3. If instead you give a list of numbers, such as &quot;yscale = [2, 3, 0.5.]&quot;, the initial y component of the cross section is scaled by a factor of 2, the second by a factor of 3, and the third by a factor of 0.5. The number of yscale factors must be the same as the number of points on the path. <span class="Normal">By default, the starting face of an extrusion is oriented with &quot;up&quot; in the +y direction (unless you specify a different &quot;up&quot; for the extrusion).+x is to the right and +y is up.</span></p>
58+
<p class="attributes"><span class="attribute">twist</span> If twist is 0.1 (an angle in radians), each segment of the extrusion is rotated 0.1 radians about the path, with respect to the previous segment. If instead you give a list of numbers, such as &quot;twist = [0.1, 0.3, -0.2]&quot;, the initial cross section is rotated counterclockwise by 0.1 radians, the second cross section is rotated counterclockwise by 0.3 radians with respect of the first segment, and the third cross section is rotated clockwise by 0.2 radians with respect of the second segment. The number of twist factors must be the same as the number of points on the path.</p>
59+
<p class="attributes"><span class="attribute">show_start_face</span> and <span class="attribute">show_end_face</span> By default, these attributes are True and the start and end faces are displayed. If you set one of these to False, that face is left open. These attributes have no effect if the path is closed.</p>
60+
<p class="attributes"><span class="attribute">start_face_color</span> and <span class="attribute">end_face_color</span> By default,the starting and ending faces are given the same color as the color specified for the associated segment, but you can specify that other colors be used for the starting or ending face. These attributes have no effect if the path is closed.</p>
61+
<p class="attributes"><span class="attribute">start_normal</span> and <span class="attribute">end_normal</span> By default,the outward-going normals to the starting and ending faces are determined by the direction of the path from the starting point to the next segment on the path, but you can specify different normals for the starting and/or ending faces. These attributes have no effect if the path is closed.</p>
62+
<p class="attributes"><span class="attribute">smooth</span> By default, adjacent segments for which the cosine of the angle between the two path elements is greater than 0.95 (corresponding to an angle of 18 degrees) are averaged so as to smooth the adjacent surfaces. You can set <span class="attribute">smooth</span> to a looser criterion for more smoothing. For example, setting smooth=0.9 will smooth adjoining surfaces whose orientation differs by 53 degrees, a much looser criterion..</p>
63+
<p class="attributes"><span class="attribute">smooth_joints</span> and <span class="attribute">sharp_joints</span> You can override the <span class="attribute">smooth</span> specification for specific points along the path. Suppose that all of the joints are &quot;smooth'; that is, the differences in direction from one segment to another are all quite small, but you would like to consider segments 2 and 5 nevertheless to be &quot;sharp&quot;, which affects the appearance and color of the joint. In that case you would say &quot;sharp_joints = [2, 5]&quot;. Similarly, if there are sharp turns at segments 1 and 7 that you would like to treat as &quot;smooth&quot;, you would say &quot;smooth_joints = [1, 7]. As usual with lists, 0 is the first joint and 1 is the second joint. Here is an example of the effect on color, where the upper example shows a fade from blue to orange, and the lower example with an inserted&quot;sharp&quot; joint shows an abupt color change:</p>
64+
<p class="Normal"></p>
65+
<table width="529" border="0">
66+
<tr>
67+
<td width="523"><div align="center"><span class="Normal"><img src="images/colors_abutting.jpg" width="312" height="200" alt="colors abutting" /></span></div></td>
68+
</tr>
69+
</table>
70+
<p class="Normal"><strong><font color="#0000a0">The three steps to making an extrusion</font></strong></p>
5871
<p class="Normal"><strong>1)</strong> Create a 2D <span class="attribute">shape</span>, either by giving a list of points or by choosing a shape from a supplied library of common shapes. Here are three examples. The first creates a triangle by listing 2D points. The second example creates a circular shape from the <strong><a href="shapes.html">shapes and paths library</a></strong>, and the third creates a rectangular shape, using the shapes library.</p>
5972
<p class="program">tri = [ [2,0], [0,4], [-2,0], [2,0] ]</p>
6073
<p class="program">circ = shapes.circle(radius=3)</p>
32.1 KB
Loading

lib/glow/extrude.js

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -531,29 +531,52 @@ function extrusion(args) {
531531
// If the turn is gradual (not sharp), average the neighboring normals to smooth the joint.
532532
// If the path is not closed, tessellate (divide into triangles) and apply to the ends of the path.
533533
// After creating all the quads and triangles, return a compound object made from these.
534-
535-
// VPython 6 had per-joint attributes twist, and the scalar start_twist.
536534

537535
// Implemented December 2020 - March 2021 by Bruce Sherwood:
538536
// Major restructuring of the extrusion code, making it feasible to implement
539537
// scale, xscale, yscale, color, and twist that can be lists (length must equal number of joints)
540-
// or single values which then apply all along the path. Also newly implemented
541-
// start_normal, end_normal, smooth_joints, sharp_joints.
538+
// or single values which then apply all along the path.
539+
// Also newly implemented: start_normal, end_normal, smooth_joints, sharp_joints.
542540

543541
if (args.canvas === undefined) args.canvas = canvas.get_selected()
544542
if (args.path === undefined) throw new Error('An extrusion object needs a path attribute.')
543+
if (args.path.length < 2) throw new Error('The path must have more than one point.')
545544
var path_closed = args.path[args.path.length-1].equals(args.path[0])
546545
if (args.shape === undefined) throw new Error('An extrusion object needs a shape attribute.')
547546
args.pos = (args.pos === undefined) ? null : args.pos
548547
args.axis = (args.axis === undefined) ? null : args.axis
549-
args.up = (args.up === undefined) ? vec(0,1,0) : norm(args.up)
548+
args.up = (args.up === undefined) ? vec(0,1,0) : args.up.norm()
549+
let first_segment = (args.path[1].sub(args.path[0])).norm()
550+
if (first_segment.cross(args.up).mag < 0.1) { // construct args.up to be perpendicular to first_segment
551+
if (args.up.cross(vec(0,1,0)).mag > 0.2) { // try making args.up be vec(0,1,0)
552+
args.up = vec(0,1,0)
553+
} else if (args.up.cross(vec(1,0,0)).mag > 0.2) { // try making args.up be vec(1,0,0)
554+
args.up = vec(1,0,0)
555+
} else if (args.up.cross(vec(0,0,1)).mag > 0.2) { // try making args.up be vec(0,0,1)
556+
args.up = vec(0,0,1)
557+
}
558+
}
559+
560+
// let c = vec(0,0,0)
561+
// if (args.up === undefined) {
562+
// let a = args.path[1].sub(args.path[0]) // first segment
563+
// if (args.path.length > 2) {
564+
// let b = args.path[2].sub(args.path[1]) // second segment
565+
// c = cross(a,b).norm()
566+
// }
567+
// if (args.path.length == 2 || c.mag === 0) {
568+
569+
// }
570+
// } else args.up = norm(args.up)
550571
args.color = (args.color === undefined) ? color.white : args.color
551572
args.twist = (args.twist === undefined) ? 0 : args.twist
552573
args.opacity = (args.opacity === undefined) ? 1 : args.opacity
553574
args.shininess = (args.shininess === undefined) ? 0.6 : args.shininess
554575
args.emissive = (args.emissive === undefined) ? false : args.emissive
555-
args.sharp_joints - (args.sharp_joints === undefined) ? [] : args.sharp_joints
556-
args.smooth_joints - (args.snooth_joints === undefined) ? [] : args.smooth_joints
576+
args.sharp_joints = (args.sharp_joints === undefined) ? [] : args.sharp_joints
577+
args.smooth_joints = (args.smooth_joints === undefined) ? [] : args.smooth_joints
578+
if (args.sharp_joints.length === undefined) throw new Error("sharp_joints must be a list of path indexes.")
579+
if (args.smooth_joints.length === undefined) throw new Error("smooth_joints must be a list of path indexes.")
557580

558581
if (path_closed) {
559582
if (args.show_start_face !== undefined) throw new Error("Cannot specify show_start_face for a closed-path extrusion.")
@@ -568,13 +591,6 @@ function extrusion(args) {
568591
args.end_normal = (args.end_normal === undefined) ? null : args.end_normal
569592
args.show_start_face = (args.show_start_face === undefined) ? true : args.show_start_face
570593
args.show_end_face = (args.show_end_face === undefined) ? true : args.show_end_face
571-
if (args.color.length !== undefined) {
572-
args.start_face_color = (args.start_face_color === undefined) ? args.color[0] : args.start_face_color
573-
args.end_face_color = (args.end_face_color === undefined) ? args.color[args.color.length-1] : args.end_face_color
574-
} else {
575-
args.start_face_color = (args.start_face_color === undefined) ? args.color : args.start_face_color
576-
args.end_face_color = (args.end_face_color === undefined) ? args.color : args.end_face_color
577-
}
578594

579595
// Smooth the edges if cosine of difference angle is greater than 0.95 (less than 18 degrees)
580596
args.smooth = (args.smooth === undefined) ? 0.95 : args.smooth
@@ -631,6 +647,9 @@ function extrusion(args) {
631647
if (slen !== args.path.length)
632648
throw new Error('The length '+slen+' of the list of color values does not match the length '+args.path.length+' of the path.')
633649
}
650+
651+
args.start_face_color = (args.start_face_color === undefined) ? args.color[0] : args.start_face_color
652+
args.end_face_color = (args.end_face_color === undefined) ? args.color[args.color.length-1] : args.end_face_color
634653

635654
let tw = args.twist
636655
args.twist = []
@@ -743,8 +762,13 @@ function extrusion(args) {
743762
newy = y.rotate({angle:theta, axis:axis})
744763
sharp = (theta >= smoothangle) // if true, path takes a sharp turn here
745764
if (!path_closed && (ipath === 0 || ipath == L-1)) sharp = false
746-
else if (sharp && args.smooth_joints.indexOf(ipath) >= 0) sharp = false
747-
else if (!sharp && args.sharp_joints.indexOf(ipath) >= 0) sharp = true
765+
if (sharp) { // if ipath is in both args.smooth_joints and in args.sharp_joints, no change:
766+
if (args.smooth_joints.indexOf(ipath) >= 0) sharp = false
767+
if (args.sharp_joints.indexOf(ipath) >= 0) sharp = true
768+
} else { // if ipath is in both args.smooth_joints and in args.sharp_joints, no change:
769+
if (args.sharp_joints.indexOf(ipath) >= 0) sharp = true
770+
if (args.smooth_joints.indexOf(ipath) >= 0) sharp = false
771+
}
748772
turn = norm(z).add(norm(newz))
749773
if (ipath > 0 && (sharp || ipath == L-1)) {
750774
for (let k=lastzero+1; k<ipath; k++) joints[k].ltex /= ltex

package/RScompiler.3.0.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package/compiler.3.0.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package/glow.3.0.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)