I'm trying to import an SVG of a screenshot into my OpenSCAD program.
OpenSCAD ignores parts of the file - namely, those parts on the periphery
that aren't "colored". I've attached three examples of the same screenshot
(originally the attached PNG), each processed slightly differently in
Inkscape.
Only hershy and hershy2 are imported properly. hershy1 is imported bit the
"white" area at the bottom of the image is not and as a result the SVG
scales improperly.
All three SVG files have the same values of:
width="571.5mm"
height="428.625mm"
viewBox="0 0 571.5 428.625"
Am I correct that OpenSCAD is not preserving this information upon import?
Thanks,
Ken
It's important to remember that OpenSCAD has a very different view of
the world than SVG does.
I expect that the overall drawing dimensions play a part in the import,
because of the coordinate system changes required to convert from SVG's
positive-down coordinate system to OpenSCAD's positive-up coordinate
system, but they don't add anything to the object imported. OpenSCAD
doesn't have a notion of an image size; there is infinite emptiness on
every side of your OpenSCAD model.
If you wanted to force a total size, that included in some sense the
whitespace around the objects, I think you'd have to wrap the entire
drawing in a border, an outline with a slightly smaller outline
subtracted from it. You could then use OpenSCAD mechanisms to subtract
that border.
The only case that I can think of where you would want that would be if
you expected to use resize() and wanted it to scale the entire original
drawing, whitespace and all. There's not really anything that SVG
import() or resize() could do to support that, because again the
imported objects don't have an enclosing "image size", either for
import() to preserve or for resize() to operate on.
Note that as soon as you subtract away the border, the enclosed
nothingness merges with the surrounding nothingness, and you're left
with just the model. You'd need to resize and then remove the border.
Note that this is far from the only information discarded during
import. SVG allows for overlapping objects; OpenSCAD does not. SVG
objects are unioned during the import. If you have two concentric
circles in SVG, and import, you end up with one circle in OpenSCAD. SVG
allows for lines; OpenSCAD does not - it only allows closed polygons.
SVG allows colors; OpenSCAD mostly does not, and does not preserve them
during import.
“The only case that I can think of where you would want that would be if you expected to use resize() and wanted it to scale the entire original drawing, whitespace and all.”
That’s exactly what I need to do. I’ll have to figure out how to add a very thin border around an image in Inkscape.
Thanks,
Ken
From: Jordan Brown openscad@jordan.maileater.net
Sent: Wednesday, May 31, 2023 5:23 PM
To: OpenSCAD general discussion Mailing-list discuss@lists.openscad.org; ken@volksswitch.org
Subject: Re: [OpenSCAD] importing "all" of an SVG
It's important to remember that OpenSCAD has a very different view of the world than SVG does.
I expect that the overall drawing dimensions play a part in the import, because of the coordinate system changes required to convert from SVG's positive-down coordinate system to OpenSCAD's positive-up coordinate system, but they don't add anything to the object imported. OpenSCAD doesn't have a notion of an image size; there is infinite emptiness on every side of your OpenSCAD model.
If you wanted to force a total size, that included in some sense the whitespace around the objects, I think you'd have to wrap the entire drawing in a border, an outline with a slightly smaller outline subtracted from it. You could then use OpenSCAD mechanisms to subtract that border.
The only case that I can think of where you would want that would be if you expected to use resize() and wanted it to scale the entire original drawing, whitespace and all. There's not really anything that SVG import() or resize() could do to support that, because again the imported objects don't have an enclosing "image size", either for import() to preserve or for resize() to operate on.
Note that as soon as you subtract away the border, the enclosed nothingness merges with the surrounding nothingness, and you're left with just the model. You'd need to resize and then remove the border.
Note that this is far from the only information discarded during import. SVG allows for overlapping objects; OpenSCAD does not. SVG objects are unioned during the import. If you have two concentric circles in SVG, and import, you end up with one circle in OpenSCAD. SVG allows for lines; OpenSCAD does not - it only allows closed polygons. SVG allows colors; OpenSCAD mostly does not, and does not preserve them during import.
On 5/31/2023 6:47 PM, ken@volksswitch.org wrote:
“The only case that I can think of where you would want that would be
if you expected to use resize() and wanted it to scale the entire
original drawing, whitespace and all.”
That’s exactly what I need to do. I’ll have to figure out how to add
a very thin border around an image in Inkscape.
Rectangle, smaller rectangle, select both, Path/Difference.
But it occurs to me that that's not necessary. All that's necessary is
to set up the right bounding box, which means that all you need is a SVG
object at each extreme - at the top left and bottom right, say.
On May 31, 2023, at 6:47 PM, ken@volksswitch.org ken@volksswitch.org wrote:
“The only case that I can think of where you would want that would be if you expected to use resize() and wanted it to scale the entire original drawing, whitespace and all.”
That’s exactly what I need to do. I’ll have to figure out how to add a very thin border around an image in Inkscape.
There's a more esoteric solution available... You can get a geometric bounding box of the SVG content. You can then use offset()
and difference()
to make the outline you want, at the distance you want from the shape.
include <BOSL2/std.scad>
module bounding_box2d() {
module _xProjection() {
projection()
rotate([90,0,0])
linear_extrude(1, center=true)
hull()
children();
}
// a bounding box with an offset of 1 in all axis
module _oversize_bbox() {
minkowski() {
_xProjection() children(); // x axis
rotate(-90) _xProjection() rotate(90) children(); // y axis
}
}
offset(-1/2) _oversize_bbox() children();
}
module boxit(size, padding=10, linewidth=1) {
module _mkbox() {
difference() {
offset(delta=padding+linewidth) children();
offset(delta=padding) children();
}
}
module _mkall() {
union() {
_mkbox() bounding_box2d() children();
children();
}
}
_mkall() resize(size) children();
}
boxit(size=[200,50], padding=10, linewidth=1)
mirror([0,1,0])
import("foo.svg");
On 5/31/2023 8:49 PM, Revar Desmera wrote:
There's a more esoteric solution available... You can get a geometric
bounding box of the SVG content. You can then use offset()
and
difference()
to make the outline you want, at the distance you want
from the shape.
I guess we first need to ask Ken whether the OpenSCAD program gets to
know anything about the SVG dimensions.
If the OpenSCAD program gets to know the SVG page dimensions, then you
just use scale() instead of resize() and everything is easy.
But if you don't get to know SVG dimensions, if the intent is to scale
the SVG page into a particular OpenSCAD rectangle without knowing the
SVG dimensions, then ... it's harder, and you wouldn't get to know the
required border either.
(What we really need here is an import function that reads an SVG and
returns metadata, and perhaps the entire drawing.)
A simple test
the svg y values need to be negated on import to openscad, due to
different coordinate systems, more or less. The values for viewbox etc.,
are not ignored, but do not behave in a method you'd necessarily
expect. It may depend on the version of openscad that you use.
On 31/05/2023 21:27, ken@volksswitch.org wrote:
I’m trying to import an SVG of a screenshot into my OpenSCAD program.
OpenSCAD ignores parts of the file – namely, those parts on the
periphery that aren’t “colored”. I’ve attached three examples of the
same screenshot (originally the attached PNG), each processed slightly
differently in Inkscape.
Only hershy and hershy2 are imported properly. hershy1 is imported
bit the “white” area at the bottom of the image is not and as a result
the SVG scales improperly.
All three SVG files have the same values of:
width="571.5mm"
height="428.625mm"
viewBox="0 0 571.5 428.625"
Am I correct that OpenSCAD is not preserving this information upon import?
Thanks,
Ken
OpenSCAD mailing list
To unsubscribe send an email todiscuss-leave@lists.openscad.org
On 6/1/2023 4:10 AM, Raymond West wrote:
the svg y values need to be negated on import to openscad, due to
different coordinate systems, more or less. The values for viewbox
etc., are not ignored, but do not behave in a method you'd necessarily
expect. It may depend on the version of openscad that you use.
It's not just negated. That would in a sense work, but would leave the
drawing in the lower-right (+X, -Y) quadrant, which would confuse
people. It also offsets the drawing up into the upper-right (+X, +Y)
quadrant. I've never spent the effort to fully understand the
transformation used.
But that ends up not really being relevant here. The problem here would
still exist if the two had compatible coordinate systems.
The problem is that SVG has a notion of a "page size" or "image size",
and OpenSCAD doesn't. Ken wants to have an object of some size, inside
a page of some size, and then wants to resize() the page to a desired
size. Once the SVG has been imported, there's no notion of a "page".
Those dimensions are lost; all that remains is the object, and that's
what resize() bases its work on, rather than basing it on the "page".
Hi all,
First a tiny bit of context. I’ve created a free, OpenSCAD-based, designer for keyguards (https://volksswitch.org/index.php/volks-devices/fully-customizable-3d-printable-aac-keyguard-for-tablets/). A keyguard is used by a disabled person to reliably interact with an app on a tablet – normally for communication purposes.
To aid the individual in matching the keyguard design to their app, I ask them to take a screenshot of their app on their tablet, convert it to an SVG using a tool like Inkscape (a 3-step process) and then check a box in the designer to “display screenshot”.
That request invokes this code:
module show_screenshot(){
color("DarkMagenta",.5)
translate([0,0,-rail_height/2-0.5])
resize([swm,shm,0])
offset(delta = .005)
import(file = "screenshot.svg",center=true);
}
swm – is the screen width in millimeters
swh – is the screen height in millimeters
The “image” is then placed just below the preview of the keyguard. When the entire SVG is imported, this code produces a VERY accurate representation of the screen along with the keyguard they’re trying to design. When it’s not completely imported, the “image” is distorted and unreliable as a representation of the screen layout.
Thanks,
Ken
From: Jordan Brown openscad@jordan.maileater.net
Sent: Thursday, June 1, 2023 12:48 AM
To: Revar Desmera revarbat@gmail.com; OpenSCAD general discussion discuss@lists.openscad.org
Subject: [OpenSCAD] Re: importing "all" of an SVG
On 5/31/2023 8:49 PM, Revar Desmera wrote:
There's a more esoteric solution available... You can get a geometric bounding box of the SVG content. You can then use offset()
and difference()
to make the outline you want, at the distance you want from the shape.
I guess we first need to ask Ken whether the OpenSCAD program gets to know anything about the SVG dimensions.
If the OpenSCAD program gets to know the SVG page dimensions, then you just use scale() instead of resize() and everything is easy.
But if you don't get to know SVG dimensions, if the intent is to scale the SVG page into a particular OpenSCAD rectangle without knowing the SVG dimensions, then ... it's harder, and you wouldn't get to know the required border either.
(What we really need here is an import function that reads an SVG and returns metadata, and perhaps the entire drawing.)
Do you know the dimensions of the SVG file, or might (e.g.) different
users end up using different scales?