Create QR Code Annotations (Example)

Table of Contents

Background

QR codes are often used to attach information that is fault-tolerant and machine-readable. NX (currently) only offers the option of generating one-dimensional barcodes as annotations using a special character set. This post aims to show how QR codes can be easily inserted using an NX Open Journal in Python.

Requirements

The python package qrcode1 is required to encode the content. The system font Courier New must also be available.

Implementation

If a non-proportional font is selected for generating the annotation, the text can be composed of spaces and a square symbol (here Courier New, Geometric Shapes, Black Square) line by line. The point matrix for this can be determined from the content to be coded using the get_matrix method of the qrcode.QRCode class.

"""
Create QR Code Annotations in NX Example
Author: Jan Boettcher, www.ib-boettcher.de, 2020
"""
import qrcode
import NXOpen
import NXOpen.Annotations
import NXOpen.Drawings
import NXOpen.UF

def main():
    """
    Main task.
    """
    session: NXOpen.Session = NXOpen.Session.GetSession()
    work_part: NXOpen.Part = session.Parts.Work

    do_continue = True
    if work_part is None:
        NXOpen.UI.GetUI().NXMessageBox.Show(
            "nxqr", NXOpen.NXMessageBox.DialogType.Error, "No work part."
            )
        do_continue = False
    if do_continue:
        do_continue, text = get_text()   
    if do_continue:
        do_continue, position = pick_position()
    if do_continue:
        matrix = create_qr_matrix(text)
        text_array = create_nx_text(matrix)
        font_index = add_font(work_part)
        qr_prefs = {
            "GeneralTextFont": font_index,
            "GeneralTextLineSpacFactor": 0.00001,
            "GeneralTextSize": 1.0,
            "GeneralTextAspectRatio": 1.0,
        }
        old_prefs = switch_prefs(work_part, qr_prefs)
        create_annotation(work_part, position, text_array)
        switch_prefs(work_part, old_prefs)

def create_annotation(part, position, text_array):
    """
    Create the annotation.
    """
    drafting_note_builder = part.Annotations.CreateDraftingNoteBuilder(
        NXOpen.Annotations.SimpleDraftingAid.Null
        )
    drafting_note_builder.Origin.Origin.SetValue(
        NXOpen.TaggedObject.Null, NXOpen.View.Null, position
        ) 
    drafting_note_builder.Origin.SetInferRelativeToGeometry(False)
    drafting_note_builder.Text.TextBlock.SetText(text_array)
    drafting_note_builder.Commit()
    drafting_note_builder.Destroy()


def add_font(part: NXOpen.Part):
    """
    Add font for annotation.
    """
    courier_index = part.Fonts.AddFont(
        "Courier New", NXOpen.FontCollection.Type.Standard
        )
    return courier_index


def switch_prefs(part, prefs):
    """
    Store current annotation preferences and set some new.
    """
    pref_builder = part.SettingsManager.CreatePreferencesBuilder()

    annotation_style = pref_builder.AnnotationStyle
    lettering_style = annotation_style.LetteringStyle
    old_prefs = {
        "GeneralTextFont": lettering_style.GeneralTextFont,
        "GeneralTextLineSpacFactor": lettering_style.GeneralTextLineSpaceFactor,
        "GeneralTextSize": lettering_style.GeneralTextSize,
        "GeneralTextAspectRatio": lettering_style.GeneralTextAspectRatio,
    }
    lettering_style.GeneralTextFont  = prefs["GeneralTextFont"]
    lettering_style.GeneralTextLineSpaceFactor = prefs["GeneralTextLineSpacFactor"]
    lettering_style.GeneralTextSize = prefs["GeneralTextSize"]
    lettering_style.GeneralTextAspectRatio = prefs["GeneralTextAspectRatio"]
    pref_builder.Commit()
    pref_builder.Destroy()

    return old_prefs


def pick_position():
    """
    Ask user to pick a position.
    """
    response, view, point = NXOpen.UI.GetUI().SelectionManager.SelectScreenPosition(
        "Pick QR Position"
        )
    do_continue = response == NXOpen.Selection.DialogResponse.Pick
    return do_continue, point

def get_text():
    """
    Ask user for QR content.
    """
    message = "Enter Text"
    text = "Some Text"
    uf_session = NXOpen.UF.UFSession.GetUFSession()
    uf_session.Ui.LockUgAccess(NXOpen.UF.UFConstants.UF_UI_FROM_CUSTOM)
    text, length, response = uf_session.Ui.AskStringInput(message, text)
    uf_session.Ui.UnlockUgAccess(NXOpen.UF.UFConstants.UF_UI_FROM_CUSTOM)
    do_continue = response == 5 or response == 3
    return do_continue, text
   
def create_qr_matrix(text):
    """
    Create the QR Code matrix.
    """
    qr = qrcode.QRCode(
        version=None
    )
    qr.add_data(text)
    qr.make(fit=True)
    matrix = qr.get_matrix()
    return matrix

def create_nx_text(matrix):
    """
    Create annotation text from matrix.
    """
    text_array = []
    for row in matrix:
        text = ""
        for dot in row:
            if dot == True:
                text = text + "\u25A0"
            else :
                text = text + " "
        
        text_array.append(text)
    return text_array

if __name__ == '__main__':
    main()


  1. qrcode on pypi.org ( https://pypi.org/project/qrcode/↩︎

Related