discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Re: [OpenSCAD] Images on curved (cylindrical) surface

F
frankv
Mon, Jul 11, 2016 12:54 AM

I was just looking at this problem myself. My starting point was
http://www.thingiverse.com/thing:1481
http://www.thingiverse.com/thing:1481  which wraps 3 copies of an image
around a cylinder, then extrudes. There's about 15KB of Python source that
generates an OpenSCAD file. License on this is "Creative Commons -
Attribution - Non-Commercial". The author is Philipp Tiefenbacher
(wizard23). I've refactored his code a little, and extended it to include
conic surfaces, without really understanding how the underlying stuff
works.I haven't finished my tidy-up yet, but I'm happy to share (now or when
finished) as per Philipp's license. I'm new to openSCAD & Python (but a
long-time programmer) so my "tidy" may be less than your "tidy". I'm equally
happy for someone else to finish this off.If all you're interested in is
mapping text characters to a cylinder, then
http://www.thingiverse.com/thing:1661993 is useful.Frank

--
View this message in context: http://forum.openscad.org/Images-on-curved-cylindrical-surface-tp17823p17904.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

I was just looking at this problem myself. My starting point was http://www.thingiverse.com/thing:1481 <http://www.thingiverse.com/thing:1481> which wraps 3 copies of an image around a cylinder, then extrudes. There's about 15KB of Python source that generates an OpenSCAD file. License on this is "Creative Commons - Attribution - Non-Commercial". The author is Philipp Tiefenbacher (wizard23). I've refactored his code a little, and extended it to include conic surfaces, without really understanding how the underlying stuff works.I haven't finished my tidy-up yet, but I'm happy to share (now or when finished) as per Philipp's license. I'm new to openSCAD & Python (but a long-time programmer) so my "tidy" may be less than your "tidy". I'm equally happy for someone else to finish this off.If all you're interested in is mapping text characters to a cylinder, then http://www.thingiverse.com/thing:1661993 is useful.Frank -- View this message in context: http://forum.openscad.org/Images-on-curved-cylindrical-surface-tp17823p17904.html Sent from the OpenSCAD mailing list archive at Nabble.com.
FV
Frank van der Hulst
Mon, Jul 11, 2016 8:42 AM

Turned out to be easier than I thought... because openSCAD now can handle
faces with more that 3 vertices, I could throw out all Philipp's stuff that
I didn't understand. Here's working version:

#!/usr/bin/python

import sys
import png
import urllib
from math import *
from pyopenscad import *

Wrap a 2D image around a conic surface

Based on source code by Philipp Tiefenbacher (wizard23)

Licensed as per http://creativecommons.org/licenses/by-nc/3.0/ (Creative

Commons - Attribution - Non-Commercial)

Frank van der Hulst

11 July 2016

Usage: python conewrap.py imgFile bottomRadius topRadius > output.scad

Global variables

numRows = 0
numCols = 0
minRadius = 0

Read a grey-scale PNG and return a table (array of arrays) of pixel values

def getPNG(filename):
r=png.Reader(file=urllib.urlopen(filename))
data = r.read()
pixel = data[2]
raw = []
for row in pixel:
r = []
raw.append(r)
for px in row:
r.append(px)
return raw

Project a pixel from the bitmap onto a conic surface

Each pixel represents a unit square

The height describes the horizontal distance of that pixel from the

surface of the cone. Where the cone is reasonably steep, this approximates
to how high

the image is embossed on the cone's surface (positive z values), or how

deeply it is recessed into the surface (negative z values)

bottomRadius and topRadius are the radii of the circles at the bottom and

top of the conic fragment. They may be equal for a cylinder, or topRadius
may be larger or smaller than bottomRadius.

topRadius may be zero to produce an actual cone. If bottomRadius < the

minimum radius to map the image (e.g. the image is 256 pixels wide &&
bottomRadius < 40.74 (256/2*pi)), bottomRadius is increased

cylRange is the fraction (0-1) of the cylinder the image should be

wrapped around (e.g. 0.25 means wrapi it around 90 degrees)
def projectCone(x, y, height, bottomRadius, topRadius, cylRange):

Calculate radial for wrapping

a = x2pi/numCols*cylRange

Calculate distance from axis... linear interpolation between top and

bottom radius of the cone
r = topRadius + (bottomRadius-topRadius) * (numRows-y)*1.0/numRows +
height

Calculate 3D coordinate of this point

return [rcos(a), rsin(a), y]

Map the pixMap onto a conic surface with the given radii

def mapImage(pixMap, bottomRadius, topRadius):
minRadius=numCols/(2pi)
if (bottomRadius < minRadius):
bottomRadius = minRadius
cylRange = minRadius
1.0/bottomRadius

Generate all the points for the surface

pts = []
for y in xrange(0, numRows):
# Generate a "circle" of points for this layer
for x in xrange(0, numCols):
# Pixels range in value from 0-255, where 0 = black and 255 = white
p = projectCone(x, y, -pixMap[y][x]/255.0, bottomRadius, topRadius,
cylRange)
pts.append(p)

Generate bottom face: A face is 4 indices of points

faces = []
bottom=[]
for x in xrange(0, numCols):
bottom.append(x)
bottom.append(0)
faces.append(bottom)

Generate all the faces: A face is 4 indices of points

for y in range(0, numRows-1):
for x in range(0, numCols):
p1 = ynumCols+(x+1)%numCols
p2 = y
numCols+x
p3 = (y+1)*numCols+x
p4 = (y+1)*numCols + (x+1)%numCols
f = [p1, p2, p3, p4]
faces.append(f)

Generate top face if this not a complete cone... NB reverse direction

if (topRadius != 0):
top=[]
for x in xrange(0, numCols):
top.append(numRowsnumCols - x)
top.append(numRows
numCols)
faces.append(top)

return polyhedron(pts, faces, 6)

if (len(sys.argv) !=4):
print "Usage: python ", sys.argv[0], "imgFile bottomRadius topRadius >
output.scad"
print "e.g.  python ", sys.argv[0], "santa-claus-grey.png 45 0 >
santa.scad"
exit()

File to project must be 8-bit greyscale

imgFile = sys.argv[1]

Radius of the bottom of the cone... if it is less than minRadius, the

cone will be expanded to minRadius. If greater than minRadius, a D-shaped
partial cone will be produced

Zero means the output cone's radius will be adjusted to wrap the image

exactly once around the cone
coneRadius = float(sys.argv[2])

Radius of the top of the cone... may be zero

topRadius = float(sys.argv[3])

Read pixel map from PNG file

pixMap = getPNG(imgFile)

Flip image upside-down

pixMap.reverse()
numCols = len(pixMap[0])
numRows = len(pixMap)

result = mapImage(pixMap, coneRadius, topRadius)

import time
print time.strftime("// Generated: %Y-%m-%d %H:%M")
print "// Source file: ", imgFile
print "// Image Height = ", numRows
print "// Image Width = ", numCols
print "// Minimum cylinder radius = ", minRadius
print "// Cylinder radius = ", coneRadius
print "$fa=2; $fs=0.5;\n"
print result.render()

On Mon, Jul 11, 2016 at 12:54 PM, frankv drifter.frank@gmail.com wrote:

I was just looking at this problem myself. My starting point was http://www.thingiverse.com/thing:1481
which wraps 3 copies of an image around a cylinder, then extrudes. There's
about 15KB of Python source that generates an OpenSCAD file. License on
this is "Creative Commons - Attribution - Non-Commercial". The author is
Philipp Tiefenbacher (wizard23). I've refactored his code a little, and
extended it to include conic surfaces, without really understanding how the
underlying stuff works. I haven't finished my tidy-up yet, but I'm happy to
share (now or when finished) as per Philipp's license. I'm new to openSCAD
& Python (but a long-time programmer) so my "tidy" may be less than your
"tidy". I'm equally happy for someone else to finish this off. If all
you're interested in is mapping text characters to a cylinder, then
http://www.thingiverse.com/thing:1661993 is useful. Frank

View this message in context: Re: Images on curved (cylindrical) surface
http://forum.openscad.org/Images-on-curved-cylindrical-surface-tp17823p17904.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

Turned out to be easier than I thought... because openSCAD now can handle faces with more that 3 vertices, I could throw out all Philipp's stuff that I didn't understand. Here's working version: #!/usr/bin/python import sys import png import urllib from math import * from pyopenscad import * # Wrap a 2D image around a conic surface # Based on source code by Philipp Tiefenbacher (wizard23) # Licensed as per http://creativecommons.org/licenses/by-nc/3.0/ (Creative Commons - Attribution - Non-Commercial) # # Frank van der Hulst # 11 July 2016 # Usage: python conewrap.py imgFile bottomRadius topRadius > output.scad # Global variables numRows = 0 numCols = 0 minRadius = 0 # Read a grey-scale PNG and return a table (array of arrays) of pixel values def getPNG(filename): r=png.Reader(file=urllib.urlopen(filename)) data = r.read() pixel = data[2] raw = [] for row in pixel: r = [] raw.append(r) for px in row: r.append(px) return raw # Project a pixel from the bitmap onto a conic surface # Each pixel represents a unit square # The height describes the horizontal distance of that pixel from the surface of the cone. Where the cone is reasonably steep, this approximates to how high # the image is embossed on the cone's surface (positive z values), or how deeply it is recessed into the surface (negative z values) # bottomRadius and topRadius are the radii of the circles at the bottom and top of the conic fragment. They may be equal for a cylinder, or topRadius may be larger or smaller than bottomRadius. # topRadius may be zero to produce an actual cone. If bottomRadius < the minimum radius to map the image (e.g. the image is 256 pixels wide && bottomRadius < 40.74 (256/2*pi)), bottomRadius is increased # cylRange is the fraction (0-1) of the cylinder the image should be wrapped around (e.g. 0.25 means wrapi it around 90 degrees) def projectCone(x, y, height, bottomRadius, topRadius, cylRange): # Calculate radial for wrapping a = x*2*pi/numCols*cylRange # Calculate distance from axis... linear interpolation between top and bottom radius of the cone r = topRadius + (bottomRadius-topRadius) * (numRows-y)*1.0/numRows + height # Calculate 3D coordinate of this point return [r*cos(a), r*sin(a), y] # Map the pixMap onto a conic surface with the given radii def mapImage(pixMap, bottomRadius, topRadius): minRadius=numCols/(2*pi) if (bottomRadius < minRadius): bottomRadius = minRadius cylRange = minRadius*1.0/bottomRadius # Generate all the points for the surface pts = [] for y in xrange(0, numRows): # Generate a "circle" of points for this layer for x in xrange(0, numCols): # Pixels range in value from 0-255, where 0 = black and 255 = white p = projectCone(x, y, -pixMap[y][x]/255.0, bottomRadius, topRadius, cylRange) pts.append(p) # Generate bottom face: A face is 4 indices of points faces = [] bottom=[] for x in xrange(0, numCols): bottom.append(x) bottom.append(0) faces.append(bottom) # Generate all the faces: A face is 4 indices of points for y in range(0, numRows-1): for x in range(0, numCols): p1 = y*numCols+(x+1)%numCols p2 = y*numCols+x p3 = (y+1)*numCols+x p4 = (y+1)*numCols + (x+1)%numCols f = [p1, p2, p3, p4] faces.append(f) # Generate top face if this not a complete cone... NB reverse direction if (topRadius != 0): top=[] for x in xrange(0, numCols): top.append(numRows*numCols - x) top.append(numRows*numCols) faces.append(top) return polyhedron(pts, faces, 6) if (len(sys.argv) !=4): print "Usage: python ", sys.argv[0], "imgFile bottomRadius topRadius > output.scad" print "e.g. python ", sys.argv[0], "santa-claus-grey.png 45 0 > santa.scad" exit() # File to project must be 8-bit greyscale imgFile = sys.argv[1] # Radius of the bottom of the cone... if it is less than minRadius, the cone will be expanded to minRadius. If greater than minRadius, a D-shaped partial cone will be produced # Zero means the output cone's radius will be adjusted to wrap the image exactly once around the cone coneRadius = float(sys.argv[2]) # Radius of the top of the cone... may be zero topRadius = float(sys.argv[3]) # Read pixel map from PNG file pixMap = getPNG(imgFile) # Flip image upside-down pixMap.reverse() numCols = len(pixMap[0]) numRows = len(pixMap) result = mapImage(pixMap, coneRadius, topRadius) import time print time.strftime("// Generated: %Y-%m-%d %H:%M") print "// Source file: ", imgFile print "// Image Height = ", numRows print "// Image Width = ", numCols print "// Minimum cylinder radius = ", minRadius print "// Cylinder radius = ", coneRadius print "$fa=2; $fs=0.5;\n" print result.render() On Mon, Jul 11, 2016 at 12:54 PM, frankv <drifter.frank@gmail.com> wrote: > I was just looking at this problem myself. My starting point was http://www.thingiverse.com/thing:1481 > which wraps 3 copies of an image around a cylinder, then extrudes. There's > about 15KB of Python source that generates an OpenSCAD file. License on > this is "Creative Commons - Attribution - Non-Commercial". The author is > Philipp Tiefenbacher (wizard23). I've refactored his code a little, and > extended it to include conic surfaces, without really understanding how the > underlying stuff works. I haven't finished my tidy-up yet, but I'm happy to > share (now or when finished) as per Philipp's license. I'm new to openSCAD > & Python (but a long-time programmer) so my "tidy" may be less than your > "tidy". I'm equally happy for someone else to finish this off. If all > you're interested in is mapping text characters to a cylinder, then > http://www.thingiverse.com/thing:1661993 is useful. Frank > ------------------------------ > View this message in context: Re: Images on curved (cylindrical) surface > <http://forum.openscad.org/Images-on-curved-cylindrical-surface-tp17823p17904.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 > >
B
blobule
Mon, Jul 11, 2016 4:28 PM

When I need to wrap a shape around a cylinder, I cut it in small pieces that
I reassemble on the cylinder.
The shape (here in orange) can be anything close to flat.

http://forum.openscad.org/file/n17908/wrap2.wrap2

Here is the code:

w=30; // radius of cylinder
h=100; // height of cylinder

//
// the pattern should be at [w,0,0] and move in y according to a
// pattern should be 2Pi * w size in Y
// Some rings...
//
module pattern0(a=0) {
for(i=[0:3]) {
translate([w,aPI/180w+iPI/2w+w,-20])
rotate([-90,0,-90])
difference() {
cylinder(d1=PI/2w+3,d2=0,h=80);
translate([0,0,-0.1]) cylinder(d1=PI/2
w-3,d2=45+50,h=80);
}
}
}
// some text...
module pattern1(a=0) {
translate([w,aPI/180w,10])
rotate([90,0,90])
linear_extrude(height=5,convexity=2) text("bonjour!",32);
}

// rings and text...
module pattern2(a=0) {
pattern0(a);
pattern1(a);
}

module cutter(a=5,w=50,h=100) {
render()
intersection() {
rotate([0,0,-a/2]) translate([0,0,-h/2]) cube([w,50,h]);
rotate([0,0,a/2]) translate([0,-50,-h/2]) cube([w,50,h]);
}
}

%cylinder(r=w,h=h,center=true);

color("orange") translate([0,0,0]) pattern2(0);

step=5;
for( i=[0:step:360+2*step] ) {
rotate([0,0,i])
intersection() {
pattern2(-i);
cutter(step,w+20,h+20);
}
}

--
View this message in context: http://forum.openscad.org/Images-on-curved-cylindrical-surface-tp17823p17908.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

When I need to wrap a shape around a cylinder, I cut it in small pieces that I reassemble on the cylinder. The shape (here in orange) can be anything close to flat. <http://forum.openscad.org/file/n17908/wrap2.wrap2> Here is the code: w=30; // radius of cylinder h=100; // height of cylinder // // the pattern should be at [w,0,0] and move in y according to a // pattern should be 2Pi * w size in Y // Some rings... // module pattern0(a=0) { for(i=[0:3]) { translate([w,a*PI/180*w+i*PI/2*w+w,-20]) rotate([-90,0,-90]) difference() { cylinder(d1=PI/2*w+3,d2=0,h=80); translate([0,0,-0.1]) cylinder(d1=PI/2*w-3,d2=45+50,h=80); } } } // some text... module pattern1(a=0) { translate([w,a*PI/180*w,10]) rotate([90,0,90]) linear_extrude(height=5,convexity=2) text("bonjour!",32); } // rings and text... module pattern2(a=0) { pattern0(a); pattern1(a); } module cutter(a=5,w=50,h=100) { render() intersection() { rotate([0,0,-a/2]) translate([0,0,-h/2]) cube([w,50,h]); rotate([0,0,a/2]) translate([0,-50,-h/2]) cube([w,50,h]); } } %cylinder(r=w,h=h,center=true); color("orange") translate([0,0,0]) pattern2(0); step=5; for( i=[0:step:360+2*step] ) { rotate([0,0,i]) intersection() { pattern2(-i); cutter(step,w+20,h+20); } } -- View this message in context: http://forum.openscad.org/Images-on-curved-cylindrical-surface-tp17823p17908.html Sent from the OpenSCAD mailing list archive at Nabble.com.
K
kerog
Mon, Sep 5, 2016 9:37 PM

Would there be a way to package this in such a way that one could use it with
the Thingiverse customizer?

--
View this message in context: http://forum.openscad.org/Images-on-curved-cylindrical-surface-tp17823p18331.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Would there be a way to package this in such a way that one could use it with the Thingiverse customizer? -- View this message in context: http://forum.openscad.org/Images-on-curved-cylindrical-surface-tp17823p18331.html Sent from the OpenSCAD mailing list archive at Nabble.com.
N
Neon22
Mon, Sep 5, 2016 11:36 PM

you can't wrap the python for custoizer but if you embed the scad code into
your single file. no problem. Customiser can't include or use any external
file except for the ones the website includes itself. over which you have no
control.

--
View this message in context: http://forum.openscad.org/Images-on-curved-cylindrical-surface-tp17823p18332.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

you can't wrap the python for custoizer but if you embed the scad code into your single file. no problem. Customiser can't include or use any external file except for the ones the website includes itself. over which you have no control. -- View this message in context: http://forum.openscad.org/Images-on-curved-cylindrical-surface-tp17823p18332.html Sent from the OpenSCAD mailing list archive at Nabble.com.