I'd say don't worry about ordering (until later). Take one triangle at a time, and look at its three edges in whatever sequence is given.
- If one edge crosses a given whole-number Z value, then exactly one other edge in that triangle will cross that same value, so you'll get exactly one iso-contour line segment per whole-number Z per triangle, and its position and angle in the overall XY coordinate space can be worked out.
- While a single vertex (XY point) can be shared among a variable number of triangles (2 to ...8? 9?), a given vertex pair (i.e. an edge) will appear in at most two triangles. (Edges appearing in only one triangle define the outer boundary of the XY plane being charted.)
- Putting those two things together, as you march through each triangle, watch for the case where you come to an edge you've seen before (of course, its end points will be presented in opposite order, relative to the first time you saw this edge). If you've already seen it, you already know if it crosses any whole-number Z value(s), and you have the coordinates of the end points for that iso-contour line in the adjacent (previously done) triangle.
- When you find the other edge(s) of the current triangle crossing the same whole-number Z value(s) -- these also may be edges you've seen before -- you have what you need to maintain a linked list of the nodes for the given iso-contour line, in addition to knowing the position and angle of each line segment.
For 2.4 million vertices (how many triangles?), it's a lot to keep track of, but it seems like just a matter of looping over triangles, and for each of those, looping over edges, keeping track of the edges you've done, and keeping a properly indexed list of iso-contour line segments as they come up, so that you know when you encounter each interior edge the second time, and can traverse the connections of linked contour lines.
Regarding that first point above, the logical possibilities are:
- None of the three edges contain a whole-number Z value
- One or more of the vertices is itself a whole-number Z value
- An edge contains just one whole-number Z value, so that value appears on one other edge (or may be the at the opposite vertex)
- An edge contains two or more whole-number Z values; either all those values will also appear on one other edge, or else they'll be divvied up among the other two edges (or one of them may be at the opposite vertex)
I hope you have a generous schedule (and are getting paid enough) for doing this. Sounds like a lot of work.
(updated wording in a couple bullet points)