Hi I am looking for a way to apply a style to a geometry exactly the same way round corner does, I wanna keep the inner edges hidden smoothed and the rest of the edges visible unsmoothed, any ideas?
Def Add_Polygon.rb (2.6 KB)
Hi I am looking for a way to apply a style to a geometry exactly the same way round corner does, I wanna keep the inner edges hidden smoothed and the rest of the edges visible unsmoothed, any ideas?
Def Add_Polygon.rb (2.6 KB)
you have a unorthodox way of creating the object, so I played around to see how I could achieve your desired resultā¦
I would not normally add the first face this way, but this shows one way of finding the edges and applying :soft
ā¦
pts_bottom=[[-1.69267, 1.96424, 0], [-1.85607, 1.85607, 0], [-1.96424, 1.69267, 0], [-2, 1.5, 0], [-2, -1.5, 0],
[-1.96424, -1.69267, 0], [-1.85607, -1.85607, 0], [-1.69267, -1.96424, 0], [-1.5, -2, 0], [1.5, -2, 0],
[1.69267, -1.96424, 0], [1.85607, -1.85607, 0], [1.96424, -1.69267, 0], [2, -1.5, 0], [2, 1.5, 0],
[1.96424, 1.69267, 0], [1.85607, 1.85607, 0], [1.69267, 1.96424, 0], [1.5, 2, 0], [-1.5, 2, 0]]
mesh2 = Geom::PolygonMesh.new
polygon_index = mesh2.add_polygon(pts_bottom)
Sketchup.active_model.entities.add_faces_from_mesh(mesh2)
face = Sketchup.active_model.entities[-1]
face.pushpull(5)
Sketchup.active_model.entities.grep(Sketchup::Edge) do |edge|
next unless edge.length == 5
edge.soft = true if edge.faces[0].normal.dot(edge.faces[1].normal).abs < 0.98
end
john
YES!, thank you john, this is what I was looking forā¦
Hi I am back, I try to make a simpler shape, cant seem to understand how to do it, why my angle the angle is allways 0?, cant use follow me command because this is a small part of something bigger, cant seem to understand faces.length, the side edges should be connected to only 2 faces?
Def Add_Polygon v2.rb (1.6 KB)
your :sides
method produces 27 faces instead of 6ā¦
john
27 faces total ok, but if i am iterating through every edge, and faces.length trows diferent values
edges.each {|edge|
faces=edge.faces
if faces.length==2
also why angle is always = 0
ang0=faces[0].normal
ang1=faces[1].normal
angle=ang0.angle_between(ang1)
heres a different approach with additional code so you can āwatchā what happensā¦
@faces = []
@edges = []
@ents = Sketchup.active_model.entities
@bot_points2 = [[0.46424, -0.19267, 0], [0.35607, -0.35607, 0], [0.19267, -0.46424, 0], [0, -0.5, 0], [0, 0, 0], [0.5, 0, 0], [0.46424, -0.19267, 0]]
@top_points2 = [[0.46424, -0.19267, 1], [0.35607, -0.35607, 1], [0.19267, -0.46424, 1], [0, -0.5, 1], [0, 0, 1], [0.5, 0, 1], [0.46424, -0.19267, 1]]
def bottom_cap
pts_bottom = @bot_points2
face = @ents.add_face(pts_bottom)
# face.reverse!
@faces << face
end
def top_cap
pts_top = @top_points2
face = @ents.add_face(pts_top)
face.reverse!
@faces << face
end
def side_edges
joining_edge_pts = @bot_points2.zip(@top_points2)
joining_edge_pts.flatten.each_slice(3).to_a.each_slice(2).to_a
joining_edge_pts.each{|pair| @ents.add_line(pair)}
end
def missing_faces
ents=Sketchup.active_model.entities
edges = ents.grep(Sketchup::Edge)
edges.each {|edge|
@edges << edge
next unless edge.faces.empty?
edge.find_faces
}
end
def soften_edges
@edges.each { |edge|
faces = edge.faces
next if faces.map{|face| @faces.include?(face)}.include?(true)
next if faces.map{|face| face.area < 0.2}.include?(false)
edge.soft=true
edge.smooth=true
}
end
model = Sketchup.active_model
sel = model.selection
view = model.active_view
sel.clear unless sel.empty?
model.start_operation('slowly')
bottom_cap
sleep 0.5
view.refresh
top_cap
sleep 0.5
view.refresh
side_edges
sleep 0.5
view.refresh
missing_faces
sleep 0.5
view.refresh
soften_edges
model.commit_operation
john
John I am gonna be honest with you, you blew my mind with that sleep command!! didnt know about it, ok iāve been testing your code, and it seem you rely on face.area to determine what edge to smooth, but when we grow bigger you face a problem, the points you have now will be ramdon generated acording to shapes made by the user or library, so question 1: should we look for faces closed to each other with the same area? in that way we dont rely on a āfixedā value? question 2: why your object edges are welded somehow and mine are not?Def Add_Polygon v2.rb (6.1 KB)
PS: Thanks for the Help!!!
your Geom::PolygonMesh
code is creating to many faces, it is breaking the face finding, edge smoothing, etcā¦
which is why I changed that method, added the missing faces method and changed the order each is is calledā¦
face.area was just something else you can look, you can pre-calulate from the input, but I just measured it for a quick demoā¦
Iām joining this party kind of late, but looking at your original code I saw a couple of serious issues.
In your sides method, on each pass through the loop you add a polygon to the mesh using add_polygon and then you also invoke add_faces_from_mesh. So, the first pass adds a polygon to the mesh and then a face from that mesh. The second pass adds a second polygon to the same mesh and then adds two faces based on the mesh: a duplicate of the original plus the added one. And so on, increasing the number of duplicates on each pass. The result is a large load of duplicate faces that make the subsequent analysis fail, as almost none of the edges border just two faces! You should move the add_faces_from_mesh outside the end of the loop and let it make faces from all the polygons at once.
In soften_edges, you seem to misunderstand how a dot product works (or perhaps have a typo). Since the normal vector to a face is a unit vector, the dot product between two of them is between 1 and -1 (dot = |a|*|b|*cos(angle)). Here |a| == |b| == 1 and -1 < cos < 1! So, the first test fails because the dot magnitude will never be > 1. This might be a typo where you meant <1? The second test is also not likely to pass very often because you are dealing with finite precision computer arithmetic. It is not likely that a calculated abs of a dot product will exactly equal 1, even if the two faces are coplanar. You need to test to within a tolerance, or better, use the Ruby APIās Vector3d#parallel? method which already uses a tolerance.
That said, Iām not clear what edges you expected to soften and smooth, as your sample has no faces that are coplanar.
@slbaumgartner, I believe this is the desired outcomeā¦
def bottom_cap
pts_bottom = @bot_points
face = @ents.add_face(pts_bottom)
#face.reverse!
@faces << face
end
def top_cap
pts_top = @top_points
face = @ents.add_face(pts_top)
#face.reverse!
@faces << face
end
def side_edges
joining_edge_pts = @bot_points.zip(@top_points)
joining_edge_pts.flatten.each_slice(3).to_a.each_slice(2).to_a
joining_edge_pts.each{|pair| @ents.add_line(pair)}
end
def missing_faces
ents=Sketchup.active_model.entities
edges = ents.grep(Sketchup::Edge)
edges.each {|edge|
@edges << edge
next unless edge.faces.empty?
edge.find_faces
@area << edge.faces[0].area
}
end
def soften_edges
avg = @area.sum/@area.size
@edges.each { |edge|
faces = edge.faces
next if faces.map{|face| @faces.include?(face)}.include?(true)
next if faces.map{|face| face.area < avg}.include?(false)
edge.soft=true
edge.smooth=true
}
end
model = Sketchup.active_model
sel = model.selection
view = model.active_view
sel.clear unless sel.empty?
model.start_operation('slowly')
@area = []
@faces = []
@edges = []
bottom_cap
sleep 0.5
view.refresh
top_cap
sleep 0.5
view.refresh
side_edges
sleep 0.5
view.refresh
missing_faces
sleep 0.5
view.refresh
soften_edges
model.commit_operation
Iām curious why after having drawn the bottom cap you donāt just #pushpull it to create the other cap and all the side edges and faces in one go? Why create elaborate code to do something built into the Ruby API?
Yea, if the corners were drawn as Arc entities they should have their edges soft+smooth automatically. You could then traverse the vertical edges of the start/end of each curve and turn off soft+smooth.
Illustrating @tt_suās point and mine (I drew the bottom manually since that part of the code isnāt the key idea).
Oh, there isnāt even any need to manually unsmooth the edges connected to the curve cornersā¦
ā¦ah, I suppose the whole loop would have had to be a Curve
for all extruded edges to appear smooth.
Yes, same as pushpull does in the GUI. Pushpull leaves an unsmoothed edge wherever there is a join between two separate things in the faceās loop. One has to weld the loop into a Curve to get it to smooth everything.
@tt_su, @slbaumgartner Hi, the whole idea is to have a shape made by user or library, read the outerloop of the shape, and then make a path, square/round/whetever to make aluminium/pvc windows with a specific profile, pushpull or followme will be limited if a want to have a texture (correct me if im wrong). Well lets say I have a pvc with wood texture. The whole idea is to move points around whetever i need them to be, maybe my approach is wrong, should i read the profile, get outerloop, make a path then follow me?
@slbaumgartner, yes thanks now my Polymesh works in a perfect way, of course I took it out of the loop.
@john_drivenupthewall, your new approach seem perfect except for the small first object, the 90 degrees faces are smoothed and they should not be, maybe an if about it will fix it, another thing i noticed is that my Polymesh works on the large objects but fails on the small one, i get a nill somewhere soften_edges, no edges?
Def Add_Polygon v2.rb (6.2 KB)
PS: thanks everybody, awesome input, im learning a lot over here, and that makes happyā¦
I donāt understand what you mean by that, nor why your and Johnās approaches donāt have the same issue? Please explain. Texture is something you apply to faces in the API. The way you created those faces is irrelevant.
Thatās how I would do itā¦
itās using Sketchup.active_model.entities
so itās only meant to run on one item at a timeā¦
if you want to test three items you need to make sure you reference the correct entitiesā¦
john
the main change is in soften edgesā¦
def soften_edges
@edges.flatten.each do |edge|
# the only important faces
faces = edge.faces
# conditionals
next if faces.length == 1 || # this needed for v2
faces[0].normal.angle_between(faces[1].normal).radians >= 45 || # degree could change
faces[0].area.round(1) != faces[1].area.round(1) # different approx sizes
# set both true
edge.soft = edge.smooth = true
end
@edges = []
end
after modifying your codeā¦
# we need to know the existing faces
orig_faces = @ents.grep(Sketchup::Face)
# then make new faces
@ents.add_faces_from_mesh(mesh, Geom::PolygonMesh::NO_SMOOTH_OR_HIDE)
# find the new by checking again and minus the originals
faces = (@ents.grep(Sketchup::Face) - orig_faces)
# only collect relevent edges
faces.each { |f| @edges << f.edges }
I commented and formatted your script ā¦
edit: fixed a typo and removed the .rb file as you have it nowā¦