Flatten Plane / Match plane
-
Hi i'm working on creating a very simplistic ruby plugin that will flatten a plane / match a plane. After looking at the other flatten plugins they don't seem to fit what I need. The plugin I'm designing will allow you to select at most two joined faces and make them co-planar. However I'm having trouble setting one faces plane equal to that of the first plane. Is their a method for setting the plane of a face?
P.S. I just signed up and the developer / plugins forum is locked.
Thanks,
-
Hi there, stevo..
I think there is a waiting period, or invitation only. -
face.plane
gives a face's plane
face.normal
gives a face's normal vectorYou'll need to get the angle between the two faces' normals.
Get the cross_vector between them.
Make a rotation transformation using the cross and angle.
Apply the rotation to one face...
Here's an example... Select just a face [non-horizontal, NO edges selected], run the code - it flattens the face onto a 'horizontal plane - for simplicity the first normal [n0] is set as Z_AXIS.clone... rather than from a second face's normal; also the rotation is about the first vertex of the selected face - but you can determine that as desired from shared vertices etc when using two faces as your source of data...m=Sketchup.active_model;m.start_operation('f');f=m.selection[0];n0=Z_AXIS.clone;n1=f.normal;c=n0.cross(n1);a=n0.angle_between(n1);t=Geom;;Transformation.rotation(f.vertices[0].position,c,-a);m.active_entities.transform_entities(t,f);m.commit_operation
Tip: you might want to temporarily group the transformed face to prevent any attached other faces' edges distorting as a result of the selected face's transformation...
-
What I do in Vertex Tools for "Make Coplanar" is:
<span class="syntaxdefault"><br /></span><span class="syntaxcomment"># Get a plane that is the average of the two faces.<br /># http://www.sketchup.com/intl/en/developer/docs/ourdoc/geom#fit_plane_to_points<br /></span><span class="syntaxdefault">vertices </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> face1</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">vertices </span><span class="syntaxkeyword">|</span><span class="syntaxdefault"> face2</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">vertices<br />plane </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> Geom</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">fit_plane_to_points</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> vertices </span><span class="syntaxkeyword">)<br /><br /></span><span class="syntaxcomment"># Then project each vertex towards the plane.<br /># http://www.sketchup.com/intl/en/developer/docs/ourdoc/point3d#project_to_plane<br /># http://www.sketchup.com/intl/en/developer/docs/ourdoc/entities#transform_by_vectors<br /></span><span class="syntaxdefault">vectors </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> vertices</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">map </span><span class="syntaxkeyword">{</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">|</span><span class="syntaxdefault">vertex</span><span class="syntaxkeyword">|<br /></span><span class="syntaxdefault"> vertex</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">position</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">project_to_plane</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> plane </span><span class="syntaxkeyword">)<br />}<br /></span><span class="syntaxdefault">entities</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">transform_by_vectors</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> vertices</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> vectors </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault"></span>
-
Wow wasn't expecting this big of a response. Thanks! Basically from what I have seen a lot of the flattening tools tend to flatten to a plane that is relative to one of the axis's which basically requires you to then fix the model afterward. I was simply wanting to select a triangle of the model then select a connected triangle and flatten it to the first triangles plane. Unfortunately there is no set plane function, however you can get the plane of the triangle very easily you just can't set the plane as easily. Thomthom is that what your code is doing? Do you already have a plugin that achieves this?
-
Well, not quite. What the sample I posted does is take the average plane of both. this is what Vertex Tools does.
But if you want to adjust the second to the first:
<span class="syntaxdefault"><br /></span><span class="syntaxcomment"># Then project each vertex towards the plane.<br /></span><span class="syntaxdefault">vectors </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> face2</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">vertices</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">map </span><span class="syntaxkeyword">{</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">|</span><span class="syntaxdefault">vertex</span><span class="syntaxkeyword">|<br /></span><span class="syntaxdefault"> vertex</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">position</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">project_to_plane</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> face1</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">plane </span><span class="syntaxkeyword">)<br />}<br /></span><span class="syntaxdefault">entities</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">transform_by_vectors</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> face2</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">vertices</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> vectors </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault"></span>
"Setting the plane" can be interpreted many ways in how the face should be adjusted. My approach is to just project the vertices to the target plane.
-
Projecting a face's vertices onto a new plane will 'distort' the face, if the plane.normal is NOT parallel to the face.normal: by 'distort' I mean that the face's vertices/edges relative relationships will have changed.
Transformation rotating of a face [i.e. its vertices/edges] about a point, around an axis,and by an angle, will leave that face 'undistorted' - i.e. its vertices/edges will all be in the same relative relationships, but of course all in a different orientation.
As I said, it will also distort any other edges connected to the face's vertices but not 'used' to the face itself, unless you temporarily group the face as it's transformed. This is the basis of an 'unfold' tool, whereas the un-grouped version is the basis of a 'vertex-editor'... -
Makes sense. I typically use 3ds Max and it has a planar tool that operates very close to how I want my flatten plugin (It will also disturb any faces that are attached to the surrounding edges and re-orient the face...). Flattening two faces to the same or average plane does come at a price I.E. "disturbing" the surrounding edges and anything attached. Fortunately for me In my situation their isn't a lot of surrounding faces to deal with. Basically I just want to click on two faces and click the flatten tool to bring the second face on to the same plane as the first (Making the two faces coplanar)so I can remove the edge that joins the two. If I had the ultimate wish list I would have a plugin that would allow me to select the bounding edges of an area and flatten any edges contained with in that area thus leaving the surrounding edges undisturbed...I will try both your methods and see if I can't get something working.
-
How would that work? Leaving the border edges intact while keeping everything on the inside plane? To what plane?
Got sample model or screenshot?
-
It would be some what difficult to achieve however the idea would be to use the first edge or triangle clicked to create a refrence plane to match all the selected faces to.
-
What are you trying to make with this? Sample model or screenshot would help.
-
Actually the mesh optimizer is what I was wanting to have the ability to preserve the selected edges and remove the interior edges. Which vertex tools are you referring to? Are those available as a plugin? Also how are you storing face1 and face2 in your example. The one thing I can't figure out is how to refrence the selected face. I know you can set selection = sketchup.active_model.selection but how do you get the currently sellected face from that? I know how to test to see what is selected by checking the entity.typename == "face" but how do I store the selected face in a a variable I.E. face1 = currently selected face...
Thanks,
-
Found your vertex tools thomthom I might have to give those a try this weekend. Sketchup is definately lacking in the vertex department and those tools look really awesome. Tig in your example would I replace the n0=Z_AXIS.clone with the plane of the second face? If so How do I get the second face from the selected model?
Thanks,
-
@stevo7122 said:
Actually the mesh optimizer is what I was wanting to have the ability to preserve the selected edges and remove the interior edges.
So you are in fact flattening the outer edges? When you say preserve you just want to not erase it - but you can modify it so everything becomes planar?
It's really help if you posted some visual examples.@stevo7122 said:
Which vertex tools are you referring to? Are those available as a plugin?
http://www.thomthom.net/software/vertex_tools/
@stevo7122 said:
Also how are you storing face1 and face2 in your example. The one thing I can't figure out is how to refrence the selected face. I know you can set selection = sketchup.active_model.selection but how do you get the currently sellected face from that?
# Assuming only one face is selected; sel = Sketchup.active_model.selection face1 = sel[0]
# Assuming only two faces are selected; sel = Sketchup.active_model.selection face1, face2 = sel.to_a
Sketchup.active_model.selection is an Enumerable object.
Sketchup.active_model.selection.to_a will give you an Array.
I take it you are quite new to scripting? Are you familiar with Enumerable and Array?
@stevo7122 said:
I know how to test to see what is selected by checking the entity.typename == "face" but how do I store the selected face in a a variable I.E. face1 = currently selected face...
#typename is horribly slow. Use #is_a? instead. Have a look at this article for more info: http://www.thomthom.net/thoughts/2011/12/never-ever-use-typename/
-
I think I figured it out. I actually needed to set n0=selection[1].normal I.E. the normal of the other plane...One last quick question is their a way to remove the conjoined edge between the two triangles after I make them coplanar? Im sure in the api you can find the conjoined edge is their a delete function that you would perform?Thank you both for all of your help.
-
After you are sure they are now coplanar... and ignoring that they might have different materials etc... try something like...
es0=face0.edges; face1.edges.each{|e|e.erase! if e.valid? && es0.include?(e)}
-
thomthom I just purchased your vertex tools and will give them a try. I do have one last issue. It seems that no matter which order I select to flatten the two triangles it always flattens to the plane of the same triangle. What i'm wanting is to flatten to the plane of the first selected triangle depending on which order I select. Using Tig's code below I removed the z axis and set it equal to the normal of the first plane:
` #Set m = to the active Model
m=Sketchup.active_model;
m.start_operation('f');#Get the first plane and store it in f
f=m.selection[0];
#n0=Z_AXIS.clone;#Get the normal of the second plane and store it in n0
n0=m.selection[1].normal;#set n1 = to the first planes normal.
n1=f.normal;#Set c equal to the cross vector of the first plane.
c=n0.cross(n1);set a equal to the angle between the first and second faces.
a=n0.angle_between(n1);
t=Geom::Transformation.rotation(f.vertices[0].position,c,-a);
m.active_entities.transform_entities(t,f);
m.commit_operation` -
Shouldn't this work given that f is equal to the first plane selected or am i not understanding something?
-
You've swapped the faces' normals over.
Redo the code more logically
f0=selection[0] f1=selection[1] n0=f0.normal n1=f1.normal
etc
The cross, angle, transformation etc should then go smoothly...
Then you won't get so confused.
Incidentally, the selected objects are 'faces' NOT 'planes'...
You can only have 2 faces selected, for this to be foolproof... -
I think my issue is i'm not actually capturing the first triangle being clicked anywhere I'm just enumerating the selected model and incidently just reversing the code. I think I need to some how determine which triangle was clicked first I.E. f0 or f1 and then adjust accordingly.
Advertisement