How to rescale a 3d object (Stl file) ?
13 views (last 30 days)
Show older comments
I have a STL file, I read it and then I have to rescale or resize the 3d object. Basically each surface has to move according to the direction of its normal by a given distance. For example a cube of dimension 10mm*10mm*10mm, we want to add 2mm to each surface to get a cube of 12mm*12mm*12mm. I succeeded to implement an algorithm that works with simple geometry but when the object have curves it does work pretty well. My current algorithm is:
- Read the stl file : get the vertices and the faces
- Calculate the normal of each faces.
- Multiple the coordinates of each face's vertices by the normal of this face (Without repetition : 2 coplanar faces share a vertex, this vertex will just moves once according to this direction)
1 Comment
DGM
on 31 Mar 2025 at 11:13
What's described isn't a rescaling operation. It's a surface offset, like a dilation. Consider a non-convex model, and then you'll see why increasing the offset makes concavities smaller, not larger.
So we either want rescaling or a surface offset. Rescaling is just a linear transformation of the vertex data. Surface offset is a different thing. I'm not sure what the easiest way would be. In SCAD, it's typical to just bludgeon things with the Minkowski sum with a small sphere, but I don't know the MATLABish way.
Answers (1)
DGM
on 31 Mar 2025 at 15:42
I had a very sleepy think about this problem, and my dumb intuition led me astray. I figured I should be able to grab a vertex, find the face normals of its neighbors, and solve for the intersection of those planes with a given offset to find the new vertex position. For a simple test model, it does work.
unzip testfiles.zip
% everything is orthogonal
figure(1)
T = stlread('stepholecube.stl');
offset = 0.05;
Tm1 = demo(T,offset,[10 33]);
The problem shows up when double-checking the vertex offset distance. Say, for a face normal fn (from the neighbors) and a normalized vertex offset vector vn (as calculated), the re-calculated offset distance D = 1/dot(fn,vn) is not always equal for all faces. Of course the algebra suggests it's possible, but the mind's eye makes it seem like things should still line up.
What's a good way to make it visually obvious? Consider a single vertex with four faces. The difference in the included angles between the opposite faces should be large. Consider this symmetric wedge shape.
figure(2)
T = stlread('wedge.stl');
% visualize the objects
hp = patch('faces',T.ConnectivityList, ...
'vertices',T.Points, ...
'facecolor','r','edgecolor','k');
view(3)
camlight
axis equal
grid on
xlabel('X')
ylabel('Y')
zlabel('Z')
offset = 0.05;
Tm1 = demo(T,offset,[-45 0]);
After offsetting, it's clear that the bottom and top faces aren't parallel to their original positions. It should be obvious that simply offsetting vertices won't solve this problem. In order for these four faces to be offset, we'd need to add a new vertex and edge.
I probably did a terrible job of explaining anything, but that's the core takeaway. It's a bigger problem than just transforming points. We actually need to add new vertices and change the connectivity list accordingly. This is just an example with four symmetrically-arranged triangles local to a vertex. It will get more complicated.
function Tmodified = demo(T,offset,azel)
nverts = size(T.Points,1);
neighborF = vertexAttachments(T,(1:nverts).');
V1 = zeros(nverts,3);
for k = 1:nverts
% get the unique face normals
% of the neighboring faces
neighbors = neighborF{k}.';
fn = faceNormal(T,neighbors);
fn = unique(fn,'rows');
% find the point of intersection of offset planes
% except for trivial cases, this is only a best-fit solution
% in general, the offset planes may not all intersect at a single point anymore,
% necessitating the addition of new geometry to the model.
vaug = fn\(ones(size(fn,1),1)*offset);
% offset the vertex
V1(k,:) = T.Points(k,:) + vaug.';
end
% create the modified T object
Tmodified = triangulation(T.ConnectivityList,V1);
% visualize the objects
clf
hp = patch('faces',T.ConnectivityList, ...
'vertices',T.Points, ...
'facecolor','r','edgecolor','k');
view(3)
camlight
axis equal
grid on
xlabel('X')
ylabel('Y')
zlabel('Z')
hold on
% plot the object using the new vertices
hp2 = patch('faces',Tmodified.ConnectivityList, ...
'vertices',Tmodified.Points, ...
'facecolor','w','edgecolor','k','facealpha',0.5);
if nargin == 3
view(azel(1),azel(2))
end
end
If anyone has a more MATLABish solution, feel free to add it.
0 Comments
See Also
Categories
Find more on Lighting, Transparency, and Shading in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!