Reverse egde orientation
-
Hi there!
I need to swap start and end points of edges, for I need the orientation of edges on a face to be a contnious loop. (I´m aware of the outer_loop method of faces, but for certain reasons it doesn´t fit my needs.)
In a single face the edges are continous (which in my definition means every start point of an edge is the end point of exactly one other edge), but if you look at the side faces of a cube, both vertical edges seem to be oriented in positive z-direction.
Therefore I´m trying to implement same sort of "reverse"-method for edges.
my attempts so far:
new_edge = ents.add_edges edge_to_reverse.end.position, edge_to_reverse.start.position edge_to_reverse.erase!
that didn´t work, for when erasing the original edge, the newly created edge will also be erased.
My second approach was to save the original edge´s vertices, delete the edge and then draw a new one using the saved Points:
new_start = edge_to_reverse.end new_end = edge_to_reverse.start edge_to_reverse.erase! new_edge = ents.add_edges new_start.position, new_end.position
this work quite well, but the face is beeing erased when deleting the old edge. Not a big deal, I just added the face again using the find_faces-method:
new_edge.find_faces
So that is nearly what I wanted to achieve, but there is (at least) one problem: if there is a face with a hole in it, the find_faces method might eventually fill this hole with a face.
any suggestions?
-
Make use of the
EdgeUse
objects in theLoop
s for the face.
That will give you all the info you need about an edge in relationship to a given face and the loop that edge belongs to. -
I used EdgeUses, but they are useless...
At least for my purpose. The reason is, that the "next"-method doesn´t necessarily seem to return an edge which is adjacent to the edge on which the method is called.
I solved my problem like this:
first I wrote a method to traverse through the edges of a loop in one direction until returning to the first edge.
While doing so, I saved all edges in an Array, but before I wrapped the edges in a class "EdgeWrapper". This class has three attributes: the edge-object and two vertices called "start" and "end". EgdeWrapper.start is initialized with EdgeWrapper.edge.start an EdgeWrapper.end with EdegWrapper.edge.end. If I want to change the edge orientation i can assign EdgeWrapper.edge.start to EdgeWrapper.end and EgdeWrapper.egde.end to EdgeWrapper.start.Of course creating a class inherited from "Edge" with additional start and end vertices would also have been possible (and maybe better), but for my needs the above works fine.
-
@tafkab76 said:
At least for my purpose. The reason is, that the "next"-method doesn´t necessarily seem to return an edge which is adjacent to the edge on which the method is called.
I never seen that behaviour. I use it often when I need to traverse the loops of faces and know the direction of the edge in relatioship to the face. They've always been in a sorted order.
Sounds like your wrapper re-created the purpose of
EdgeUse
andLoop
...What is the task you're trying to solve. I gather you want to get the edges and vertices in a sorted order - and you've been trying to actually swap the direction of the edge instead of sorting the data. But why?
Maybe a sample code of where you're not getting a sorted set from
EdgeUse
orLoop
? -
I already deleted the old code, but it was something like this:
edgeUses = loop.edgeuses firstEdge=edgeUses[0] currentEdgeUse = firstEdgeUse nextEdgeUse = currentEdgeUse.next while (currentEdgeUse.edge.end != firstEdgeUse.edge.start) endPoint = currentEdgeUse.edge.end if ((endPoint != nextEdgeUse.edge.start) && (endPoint != nextEdgeUse.edge.end)) puts "current Edge and next Edge not connected!" end ... wrap nextEdgeUse.edge and swap start and end if necessary ... currentEdgeUse = nextEdgeUse nextEdgeUse = currentEdgeUse.next end #of loop
This code does not reflect using the wrapper class. just assume that edge.start and edge.end are in correct (continous) order. My point is, that using that code on the six faces of a cube the if-statement was true several times which to me means, that you can´t be sure "next" returns an adjacent edge(use). (Of course I could be wrong!)
My goal is (simplified) to let the user redefine the coordinates of vertices. Therefore I pick one vertex (point 1) which can not be modified as a reference point and then the user can edit the coordinates of the next point (point 2) relatively to point 1, so point 2 also has fixed coordinates. Then the user can edit point 3 relatively to point 2 and so on.
This works fine, now I´m trying to deal with faces with holes in them, respectively faces with more than one loop.
-
I'm not following the code flow there...
This is a snipped that iterates over the edges in the outer loop of an face and ensures you're getting the vertices in the order of the loop:
<span class="syntaxdefault">face </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> Sketchup</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">selection</span><span class="syntaxkeyword">[</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">]<br /><br /></span><span class="syntaxdefault">for edgeuse in face</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">outer_loop</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">edgeuses<br /> vertices </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> edgeuse</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">edge</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">vertices<br /> vertices</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">reverse</span><span class="syntaxkeyword">!</span><span class="syntaxdefault"> if edgeuse</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">reversed</span><span class="syntaxkeyword">?<br /></span><span class="syntaxdefault"> start_vertex</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> end_vertex </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> vertices<br /> </span><span class="syntaxcomment"># ...<br /></span><span class="syntaxdefault"> face</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">parent</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">entities</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">add_text</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> </span><span class="syntaxstring">"#{edgeuse.edge}"</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> start_vertex</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">position</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">[</span><span class="syntaxdefault">5</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">5</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">5</span><span class="syntaxkeyword">]</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">end<br /></span>
-
@tafkab76 said:
My goal is (simplified) to let the user redefine the coordinates of vertices. Therefore I pick one vertex (point 1) which can not be modified as a reference point and then the user can edit the coordinates of the next point (point 2) relatively to point 1, so point 2 also has fixed coordinates. Then the user can edit point 3 relatively to point 2 and so on.
This works fine, now I´m trying to deal with faces with holes in them, respectively faces with more than one loop.
So what do you need to determine the edge direction for?
Just useloop.vertices
and you get an ordered set for all vertices in the face.<span class="syntaxdefault"><br /></span><span class="syntaxkeyword">for </span><span class="syntaxdefault">loop in face</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">loops<br /> vertices </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">loop</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">vertices<br />end<br /></span>
Hole loops goes the opposite direction than of the outer loop I believe. But you have
loop.outer?
to test for what type of loop you have. -
This one-liner makes all of the
face
outer_loop edges to be NOT 'reversed in the face'g=ents.add_group();face.outer_loop.edges.each{|e|g.entities.add_line(e.end,e.start) if e.reversed_in?(face)};g.explode if g.valid?
Note that
ents
is a premade reference toSketchup.active_model.active_entities
Theface.outer_loop.edges
and alsoface.outer_loop.vertices
should always return an ordered array ?
The loop edges/vertices arrays are ordered counter-clockwise for outer-loops and clockwise for other [inner] loops. -
Why on earth would modify geometry (very slow) when the API provides all the info to get the data in the order you want?
It's like using a sledgehammer to nail a screw.
And some times - when you have multiple faces being shared by the same edge you cannot have the edge oriented such that it follows the loop of all the connected faces. Extruded holes for instance - by the nature of inner and outer loops flows they'll be going in opposite directions.
-
I thought the OP wanted to change all edges of a given face's outer_loop to be "not-reversed in that face" - my code snippet does just that - over-drawing a reversed edge does not change it, clearly it can't be erased as the face vanishes with it, so exploding a correctly oriented grouped edge onto it will reverse it as desired... I'm unclear WHY he wants to do this, but he does...
If similarly oriented faces are sharing an edge, then it is impossible to get all of the edges of all faces to be "not-reversed" in every face.
The simplest example is to make two triangular faces with a common-edge.
If these two faces are similarly oriented [so that the fronts/backs match against the common-edge - e.g. both 'up'] then it is inevitable that one of those faces with have an edge that is 'reversed-in-that-face'.
Let's ensure that face no.1 has all of its outer_loop edges arranged ccws so that there is no reversal in any of its three edges...
Now face no.2 will now have that common-edge arranged in a clockwise direction, so face no.2 has at least one edge 'reversed-in-that-face', the other two edges can have any orientation/reversal it doesn't matter.
If you 'reset' the edges in face no.2, so that none of them are reversed, then the common-edge now becomes reversed in face no.1 - so it's not resolvable for all faces - it's inevitable that one face will have at least one reversed-edge.If the desire is simply to find the list of a face's outer loop edges "in order" then face.outer_loop.edges does this anyway ?
If the desire is simply to find the list of a face's outer loop vertices [from whence points can be produced] it arrives "in order" from face.outer_loop.vertices anyway ??My one-liner, with some tweaks, could be used to construct a 'temporary path of ccws ordered edges' [for example] inside a group...
g=ents.add_group();face.outer_loop.edges.each{|e|if e.reversed_in?(face);g.entities.add_line(e.end,e.start);else;g.entities.add_line(e.start,e.end);end}
The group 'g' can then be used as desired...
Obviously if [part of] that loop is a curve then this could be reflected in the grouped geometry, by extending the code to suit... I showed the simplest way... a one-liner is too limited to cg=heck for curve-ness etc and adjust the edges array accordingly... but it'd also be relatively straightforward... -
@tig said:
I thought the OP wanted to change all edges of a given face's outer_loop to be "not-reversed in that face" - my code snippet does just that - over-drawing a reversed edge does not change it, clearly it can't be erased as the face vanishes with it, so exploding a correctly oriented grouped edge onto it will reverse it as desired... I'm unclear WHY he wants to do this, but he does...
Which has been my point through this thread to find out why - because even though he asks for it doesn't mean it's what he really wants/needs. It sounds more like a symptom of his first attempt not working. From what I gather he wants the data in an ordered predictable manner - in which there is no need to change the geometry itself. Working out exactly what is the task here is important - otherwise we'd be devising very awkward solution for something that probably is much much easier and faster.
-
An example could be if the OP wants to use the edges for a followme type operation - but as I see it face.edges would do for that if if they are sometimes reversed, provided that the
extruded_face.normal
is parallel withface.edges.line[1]
...
The only need for a 'sort and/or reverse' of a selection of edges vertices to be in order, is when they are probably drawn earlier 'out of order' by the user, or they are unfaced or perhaps not all in the same faces' loops etc...
Since the OP specifically asked to make a non-reversed face.outer_loop.edges set that's what I've given him.
If the OP would like to explain simply, "is words", what he is trying to achieve... then, as tt says, we might be able to offer some effective ways to do it - perhaps without any of thisedge.reversed_in?(face)
tosh at all... -
@tig said:
If the OP would like to explain simply, "is words", what he is trying to achieve... then, as tt says, we might be able to offer some effective ways to do it - perhaps without any of this edge.reversed_in?(face) tosh at all...
There is this:
@tafkab76 said:
My goal is (simplified) to let the user redefine the coordinates of vertices. Therefore I pick one vertex (point 1) which can not be modified as a reference point and then the user can edit the coordinates of the next point (point 2) relatively to point 1, so point 2 also has fixed coordinates. Then the user can edit point 3 relatively to point 2 and so on.
But I'm not sure if I fully "get" it. As I mentioned, sounds like just getting the vertices from a Loop object is enough (they are ordered).
-
Since I now have working code I better not change it, but I´ll keep your advices in mind for further projects. I´m afraid I won´t be able to explain all my goals, since my English isn´t that good and it´s hard to explain just by text. (And actually I just wanted to know how to reverse edges, but of course any further information is welcome!)
Thanks for your support!
-
Performance will suffer greatly if you add/remove/recreate geometry to organize your data instead of just sorting it. The more entities in a context the slower it will be.
@tafkab76 said:
And actually I just wanted to know how to reverse edges,
Why do you want to reverse edges?
Advertisement