RSS FEED

Select Faces with Similar Normals

The short script "Get Similarly Oriented" is a quick and dirty solution for selecting all the faces in a mesh/poly that have normals similar to the picked one (within a specified tolerance). Works both on editable poly and editable mesh objects.
try destroyDialog getFacesWithSimilarNormal catch()
rollout getFacesWithSimilarNormal "Get Similary Oriented" height:155 width:175
(
    ---------------------------------------------------------------------------------
    -- Layout Section
    ---------------------------------------------------------------------------------

    label lblVectorX "" width:125 pos:[15,7]
    label lblVectorY "" width:125 pos:[15,25]
    label lblVectorZ "" width:125 pos:[15,43]

    spinner spnPrecisionX "\xB1" width:42 range:[-1,1,0.1] scale:0.05 pos:[125,7]
    spinner spnPrecisionY "\xB1" width:42 range:[-1,1,0.1] scale:0.05 pos:[125,25]
    spinner spnPrecisionZ "\xB1" width:42 range:[-1,1,0.1] scale:0.05 pos:[125,43]

    checkBox chxLinkSpinners "Use .X Precision For All"
    checkBox chxSelectBackFace "Select Backfacing Faces"

    button btnGetNormal "Get Face Normal"
    button btnSelectFaces "   Select Faces   " enabled:false

    ---------------------------------------------------------------------------------
    -- Private Globals
    ---------------------------------------------------------------------------------

    local obj, obj_class, num_faces, norm_orig
    local get_face_selection, set_face_selection, get_face_normal
    local spinner_arr = #(spnPrecisionY, spnPrecisionZ)
    local label_arr = #(lblVectorX, lblVectorY, lblVectorZ)
    local label_str_arr = #("Vector .X:    ", "Vector .Y:    ", "Vector .Z:    ")

    ---------------------------------------------------------------------------------
    -- Functions
    ---------------------------------------------------------------------------------

    fn getFacesByNormal norm_orig norm_precision back_face =
    (
        local collected_faces = for i = 1 to num_faces
            where (local norm_vect = normalize (get_face_normal obj i)).x <= (norm_orig.x + norm_precision.x) AND norm_vect.x >= (norm_orig.x - norm_precision.x) AND
                norm_vect.y <= (norm_orig.y + norm_precision.y) AND norm_vect.y >= (norm_orig.y - norm_precision.y) AND
                norm_vect.z <= (norm_orig.z + norm_precision.z) AND norm_vect.z >= (norm_orig.z - norm_precision.z) collect i

        if back_face do
        (
            local collected_back_faces = for i = 1 to num_faces
                where (local norm_vect = - (normalize (get_face_normal obj i))).x <= (norm_orig.x + norm_precision.x) AND norm_vect.x >= (norm_orig.x - norm_precision.x) AND
                    norm_vect.y <= (norm_orig.y + norm_precision.y) AND norm_vect.y >= (norm_orig.y - norm_precision.y) AND
                    norm_vect.z <= (norm_orig.z + norm_precision.z) AND norm_vect.z >= (norm_orig.z - norm_precision.z) collect i
            join collected_faces collected_back_faces
        )
        collected_faces
    )

    ---------------------------------------------------------------------------------
    -- Event Handlers
    ---------------------------------------------------------------------------------

    on getFacesWithSimilarNormal open do
        for ctrl = 1 to 3 do
            label_arr[ctrl].text = label_str_arr[ctrl]

    on spnPrecisionX changed val do
        if chxLinkSpinners.checked do
            spinner_arr.value = val

    on chxLinkSpinners changed state do
    (
        spinner_arr.enabled = NOT state
        if state do
            spinner_arr.value = spnPrecisionX.value
    )

    on btnGetNormal pressed do
    (
        btnSelectFaces.enabled = false
        if (obj_class = classOf (obj = selection[1])) == Editable_Mesh OR obj_class == Editable_Poly do
        (
            if obj_class == Editable_Mesh then
            (
                get_face_normal = getFaceNormal
                get_face_selection = getFaceSelection
                set_face_selection = setFaceSelection
            )
            else
            (
                get_face_normal = polyOp.getFaceNormal
                get_face_selection = polyOp.getFaceSelection
                set_face_selection = polyOp.setFaceSelection
            )

            if (get_face_selection obj).numberSet == 1 then
            (
                num_faces = obj.numFaces
                norm_orig = normalize (get_face_normal obj ((get_face_selection obj) as array)[1])
                for lbl = 1 to 3 do
                    label_arr[lbl].text = (label_str_arr[lbl] + ((formattedPrint norm_orig[lbl] format:".3g") as string))

                btnSelectFaces.enabled = true
            )
            else messageBox "There must be 1 face selected for this script to work" title:"Error!"
        )
    )

    on btnSelectFaces pressed do
    (
        set_face_selection obj (getFacesByNormal norm_orig [spnPrecisionX.value, spnPrecisionY.value, spnPrecisionZ.value] chxSelectBackFace.checked)

        setCommandPanelTaskMode mode:#modify
        if obj_class == Editable_Mesh then subObjectLevel = 3 else subObjectLevel = 4
        completeRedraw()
    )
)
createDialog getFacesWithSimilarNormal
USAGE: Run the script, select an object. For editable mesh select a face, for editable poly select one polygon. Press "Get Face Normal" button and set up precision if needed. Tick "Select Backfacing Faces" if you want them to be selected. Press "Select Faces" and you are done.

similar normals dialog

DISCLAIMER: All scripts and snippets are provided as is under Creative Commons Zero (public domain, no restrictions) license. The author and this blog cannot be held liable for any loss caused as a result of inaccuracy or error within these web pages. Use at your own risk.

This Post needs Your Comment!

Return to top