Snap Angles of PolyCurve

Hi,

Before I use the geometry from Revit I want to do some basic validation of the input and I want to correct a PolyCurve/the Vertices of the Polycurve, so that angles that are close to 90 degrees, but not exactly 90, are snapped to 90 degrees, within a given tolerance. More generally I guess it could be to snap every angel to the nearest x degrees given as input, and return the new vertices. The vertices should be in the same plane, but the solution needs to work independent of the planes orientation / coordinate system. Any suggestions on how this can be implemented? My vertices are structured like this [[Vertices],[Vertices]] and I want the output of the function the be on the same format.

Hi Eirik,

We’ll need more details to be able to help.

Hi Japhy,

So I got bunch of PolyCurves / PolyLineCurves that I get from Revit. I want to use this as basis for the geometry I want to build, but first I want to clean the data so I can reduce potential errors down the road. So here is an example of my original curve: outer_boundaries: [<Rhino.Geometry.PolyCurve object at 0x00000261C7BB7500>]. What I want is to take this curve and both round coordinates and snap angles of the polycurve, so the result is a polycurve where all angles close to 90 degrees but not exactly 90 degrees have been corrected so they are indeed 90 degrees. In addition I want to round all points to reduce floating point errors. So I have extracted all vertices and rounded to 3 decimal points, thinking that rounding first can reduce noise before correcting the angles.

At vertex 2: angle ≈ 89.75°

At vertex 3: angle ≈ 89.68°

At vertex 4: angle ≈ 90.32°

So now I want to correct the angles that are slightly off. Guessing a python node is best suited for the task, but any approach is welcome. The loops should all be planar, but the solution still needs to work in a 3d space independent of the coordinate axes.

Below is the same polycurve as above where all vertices has been extracted and rounded [(x,y,z),(x,y,z)…]

outer_boundaries_vertices_rounded_decimal: [[(Decimal(‘10001.932’), Decimal(‘1358.406’), Decimal(‘3000.000’)), (Decimal(‘10022.447’), Decimal(‘-3266.594’), Decimal(‘3000.000’)), (Decimal(‘13027.135’), Decimal(‘-3266.594’), Decimal(‘3000.000’)), (Decimal(‘13061.362’), Decimal(‘2798.406’), Decimal(‘3000.000’)), (Decimal(‘10061.932’), Decimal(‘2798.406’), Decimal(‘3000.000’)), (Decimal(‘10061.932’), Decimal(‘2882.406’), Decimal(‘3000.000’)), (Decimal(‘1061.932’), Decimal(‘2882.406’), Decimal(‘3000.000’)), (Decimal(‘1061.932’), Decimal(‘1358.406’), Decimal(‘3000.000’)), (Decimal(‘10001.932’), Decimal(‘1358.406’), Decimal(‘3000.000’))]]

Hope that gave a little more context, just want a general approach to validate any polycurve obtained from revit to reduce potential errors down the road.

Was thinking something like this:

def enforce_perpendicularity(vertices, tol_deg=1.0):

    """
    Function snaps angles that are close to 90 degrees, but not exactly 90 degrees and within tol_deg of 90 degrees. Returns snapped_vertices. If no angles are changed, return same vertices as given as input
    """

return snapped_vertices

I can see getting the angle and then reconstructing the segments. There are a lot of variables such as seg length, identifying the correct side of the angle to go by,…

Definitely some variables to keep track of, but should be possible. I think a vector based solution might work, and then use the dot product to calculate angle between the two vectors. Maybe with some sort of uv coordinates for the calculations and then conversion to 3d coordinates in the end. not sure. Would be great to have a built in feature that does this though. Have already use simplify to remove redundant points, but an additional node for rounding points and one for snapping angels would be great.