hexagon logo

Multi Dimensional Array to Single Dimension Array

Here's something I always seem to forget when I need it and have to think a little bit to remember (so why not document it here for my future self ps. you're memory is deteriorating quickly future self!).

            ASSIGN/ARRAY_1=ARRAY({PNT69},{CIR16},{CIR17})
            ASSIGN/ARRAY_2=ARRAY({LIN12},{PLN6},{PLN7},{PLN8},{LIN13})
            ASSIGN/ARRAY_3=ARRAY({LIN14},{PLN9},{PLN10},{PLN11},{LIN15})
$$ NO,
            load as many arrays into below vvvv
            ASSIGN/MULTI_ARRAY=ARRAY(ARRAY_1,ARRAY_2,ARRAY_3)
$$ NO,
            Push all items in multi dimensional array into a single dimensional array.
            
            ASSIGN/SINGLE_ARRAY=0
            ASSIGN/CNT=1
            ASSIGN/O_CNT=1
            DO/
            ASSIGN/I_CNT=1
            DO/
            ASSIGN/SINGLE_ARRAY[CNT]=MULTI_ARRAY[O_CNT,I_CNT]
            ASSIGN/CNT=CNT+1
            ASSIGN/I_CNT=I_CNT+1
            UNTIL/I_CNT > LEN(MULTI_ARRAY[O_CNT])
            ASSIGN/O_CNT=O_CNT+1
            UNTIL/O_CNT > LEN(MULTI_ARRAY)


You super users out there.. if you know a quicker, simpler, easier way to do this I would greatly appreciate it if you shared it below.

  • 2. What I do (not saying it's the best solution but it's my only goto solution that I thought up and have stuck to)... I measure the said feature export it's characteristics to a text file and then recreate it on the next OP via the builtin generic feature from the characteristics that were read in from the text file.


    Great stuff! That is some really fancy measuring routine programming. It sure took a moment for all that to sink in.

    I sometimes wish PC-DMIS had some way to concatenate arrays the way you can with strings.

    A few times now I have ended up trying something like this and then get reminded that it just doesn't work:
    ASSIGN/SARY[1..LEN(ARY1)]=ARY1

    When it comes to exporting the features characteristics, are you just exporting the names, coordinates, and vectors, or is there more to it than that? I don't suppose you can write a whole object to a text file.
  • Cris_C don't say I've never given you anything...

    $$ NO,
                _____________________________________________________________________________________________
                 
                                             Export OP20 data to .txt for OP30.
                _____________________________________________________________________________________________
                 
                Updated By: Kp61dude!
                Updated on: 20190820
                Update Reason: 'GETTEXT()' does not pull any information from Generic Features. I found a solution
                               to get this missing information. 'GETTEXT()' is doing the job of gathering this info
                               but again it doesn't for Generic types, the workaround is '.FTYPE' (returns INTEGER value of
                               feature type from a predefined PcDmis list, see PCD help). 
                               'MY_FTYPE' is loaded with, previously missing, string information (ie. "PLANE", "CIRCLE").
                               Logic 'If/LEN(MY_FTYPE) <= 0' was added and 'FTYPE' was changed to 'MY_FTYPE'.
                 
                Update on: 20200427
                Update Reason: Added "CYLINDER" to CASE
                 
                SUBROUTINE/WRITE_TO_TXT,
                    PART =  : INPUT: ROUTINES PART#,
                    SERIAL =  : INPUT: STRING OF TEXT FLOWED DOWN FROM PLC,
                    FNAME =  : INPUT: ARRAY OF FEATURE OBJECTS EX. ASSIGN TYPE ARRAY({F1},{F2},{F3}),
                    RETURN =  : RETURN: STRING OF FEATURE TYPE (IF NOT NULL),
                    APPEND = 0 : APPEND TO EXISTING FILE,
                     = 
                ASSIGN/DEBUG=0
                ASSIGN/SERNUM=RIGHT(SERIAL,LEN(SERIAL)-INDEX(SERIAL,"-"))
                ASSIGN/TXTFILE1="C:\USERS\PUBLIC\DOCUMENTS\WAI\PC-DMIS\2015.1\PN_"+PART+"_SN_"+SERNUM+".txt"
    $$ NO,
                 
                 
                IF/APPEND
    FPTR         =FILE/OPEN,TXTFILE1,APPEND
                END_IF/
                ELSE/
    FPTR         =FILE/OPEN,TXTFILE1,WRITE
                END_ELSE/
    $$ NO,
                 
                 
                IF/DEBUG
                  ASSIGN/LOG_FILE="c:\users\public\documents\wai\pc-dmis\2015.1\DEBUG_LOG.txt"
    DEBUGLOG     =FILE/OPEN,LOG_FILE,APPEND
                  FILE/WRITELINE,DEBUGLOG,"*********************************************"
                  FILE/WRITELINE,DEBUGLOG,"Started: " + SYSTEMTIME("hh:mm:ss tt") + ", " + SYSTEMDATE("MM'/'dd'/'yyyy")
                END_IF/
    $$ NO,
                 
                 
                DO/
                ASSIGN/COUNTER=COUNTER+1
                ASSIGN/MY_FTYPE=GETTEXT(486,0,FNAME[COUNTER]) + GETTEXT(63,0,FNAME[COUNTER])
                ASSIGN/MY_FTYPE=GETTEXT(486,0,MY_FTYPE) + GETTEXT(63,0,MY_FTYPE)
                IF/LEN(MY_FTYPE) <= 0
                  SELECT/FNAME[COUNTER].FTYPE
                    CASE/1
                      ASSIGN/MY_FTYPE=""
                      IF/DEBUG
                        FILE/WRITELINE,DEBUGLOG,COUNTER + ". MY_FTYPE IS NULL " + MY_FTYPE
                      END_IF/
                    END_CASE/
                    CASE/2
                      ASSIGN/MY_FTYPE="CIRCLE"
                      IF/DEBUG
                        FILE/WRITELINE,DEBUGLOG,COUNTER + ". MY_FTYPE IS CIRCLE " + MY_FTYPE
                      END_IF/
                    END_CASE/
                    CASE/4
                      ASSIGN/MY_FTYPE="LINE"
                      IF/DEBUG
                        FILE/WRITELINE,DEBUGLOG,COUNTER + ". MY_FTYPE IS LINE " + MY_FTYPE
                      END_IF/
                    END_CASE/
                    CASE/6
                      ASSIGN/MY_FTYPE="CYLINDER"
                      IF/DEBUG
                        FILE/WRITELINE,DEBUGLOG,COUNTER + ". MY_FTYPE is CYLINDER " + MY_FTYPE
                      END_IF/
                    END_CASE/
                    CASE/7
                      ASSIGN/MY_FTYPE="PLANE"
                      IF/DEBUG
                        FILE/WRITELINE,DEBUGLOG,COUNTER + ". MY_FTYPE is PLANE " + MY_FTYPE
                      END_IF/
                    END_CASE/
                    DEFAULT_CASE/
                      ASSIGN/MY_FTYPE=""
                      IF/DEBUG
                        FILE/WRITELINE,DEBUGLOG,COUNTER + ". MY_FTYPE is null and DEFAULT " + MY_FTYPE
                      END_IF/
                    END_DEFAULTCASE/
                  END_SELECT/
                END_IF/
                IF/FNAME[COUNTER].XYZ==0 AND FNAME[COUNTER].IJK==0
      $$ NO,
                  passing generic var value
                  FILE/WRITELINE,FPTR,"VAR<"+FNAME[COUNTER]+">"
                END_IF/
                ELSE/
                  SELECT/MY_FTYPE
                    CASE/"CIRCLE"
                      FILE/WRITELINE,FPTR,"CIRCLE"+FNAME[COUNTER].XYZ +";"+ FNAME[COUNTER].IJK +";"+ FNAME[COUNTER].D
                      IF/DEBUG
                        FILE/WRITELINE,DEBUGLOG,COUNTER + ". Wrote CIRCLE"
                      END_IF/
                    END_CASE/
                    CASE/"CYLINDER"
                      FILE/WRITELINE,FPTR,"CYLINDER"+FNAME[COUNTER].XYZ +";"+ FNAME[COUNTER].IJK +";"+ FNAME[COUNTER].D +";"+ FNAME[COUNTER].L
                      IF/DEBUG
                        FILE/WRITELINE,DEBUGLOG,COUNTER + ". Wrote CYLINDER"
                      END_IF/
                    END_CASE/
                    CASE/"PLANE"
                      FILE/WRITELINE,FPTR,"PLANE"+FNAME[COUNTER].XYZ +";"+ FNAME[COUNTER].IJK
                      IF/DEBUG
                        FILE/WRITELINE,DEBUGLOG,COUNTER + ". Wrote PLANE"
                      END_IF/
                    END_CASE/
                    CASE/"LINE"
                      FILE/WRITELINE,FPTR,"LINE"+FNAME[COUNTER].XYZ +";"+ FNAME[COUNTER].IJK+";"+FNAME[COUNTER].LENGTH
                      IF/DEBUG
                        FILE/WRITELINE,DEBUGLOG,COUNTER + ". Wrote LINE"
                      END_IF/
                    END_CASE/
                    DEFAULT_CASE/
                      FILE/WRITELINE,FPTR,FNAME[COUNTER].XYZ +";"+ FNAME[COUNTER].IJK
                      IF/DEBUG
                        FILE/WRITELINE,DEBUGLOG,COUNTER + ". Wrote DEFAULT (POINT)"
                      END_IF/
                    END_DEFAULTCASE/
                  END_SELECT/
                END_ELSE/
                IF/!FNAME.LEN==COUNTER
                  ASSIGN/RETURN=RETURN + MY_FTYPE + " "
                END_IF/
                ASSIGN/MY_FTYPE=""
                UNTIL/COUNTER==LEN(FNAME)
    $$ NO,
                 
                 
                FILE/CLOSE,FPTR,KEEP
                IF/DEBUG
                  FILE/WRITELINE,DEBUGLOG,"*********************************************"
                  FILE/CLOSE,DEBUGLOG,KEEP
                END_IF/
                ENDSUB/
    
  • $$ NO,
                _____________________________________________________________________________________________
                 
                                                 Import OP20 data and build.
                _____________________________________________________________________________________________
                             For more instructions on how to dimension features on main program that are built here
                             see: 'IDs for features within subroutines, basic scripts, or external routines'
                             in the PcD Help Files.
                 
                 
                           To dimension feature 'ISUB1/2/3/etc.'(created in sub) use "<Call Sub ID>:<FeatID>" ex..
                  
                In your main program it may look like something like this:
                (Use [n] after the call in case of multiple features, most likely the case for this one.)
                 
                                                  here vvv
                DIM LOC1= LOCATION OF POINT CS1:FRMSUB1[1]  UNITS=IN ,$
                GRAPH=OFF  TEXT=OFF  MULT=10.00  OUTPUT=BOTH  HALF ANGLE=NO
                AX    NOMINAL       +TOL       -TOL       MEAS        DEV     OUTTOL
                X       0.9012   100.0000   100.0000     0.9012     0.0000     0.0000 ----#-----
                END OF DIMENSION LOC1
                 
                 AND to create constructed data ex...(circle from 8 points)
                 
                CIR1       =FEAT/CIRCLE,CARTESIAN,IN,LEAST_SQR,NO
                            THEO/<0,0,0>,<0,0,1>,2.0615
                            ACTL/<0,0,0>,<0,0,1>,2.0615
                            CONSTR/CIRCLE,BF,2D,CS1:ISUB1[1],CS1:ISUB1[2],CS1:ISUB1[3],CS1:ISUB1[4],CS1:ISUB1[5],CS1:ISUB1[6],CS1:ISUB1[7],CS1:ISUB1[8],,
                            OUTLIER_REMOVAL/OFF,3
                            FILTER/OFF,UPR=0
                 
                If passing variables: load as many as you wish when using 'WRITE_TO_TEXT', this routine will return them all in RETUNVALS as an array type.
                ex...
                    'RETURNVALS[1]'
                    'RETURNVALS[2]'
                    'RETURNVALS[3]'
                    'RETURNVALS[4]'
                and so on.
                ____________________________________________________________________________________________
                SUBROUTINE/BUILD_FROM_TXT,
                    PART =  : INPUT; ROUTINES PART#,
                    SERIAL =  : INPUT; STRING OF TEXT FLOWED DOWN FROM PLC,
                    RETURN =  : OPTIONAL OUTPUT: STATUS MESSAGE,
                    DELYN = 1 : OPTIONAL INPUT: DELETE OR KEEP TXT FILE; DEFAULT AS DELETE,
                    RETURNVALS =  : OPTIONAL OUTPUT: PASS OP20 VAR DATA,
                     = 
                ASSIGN/SERNUM_OLD=RIGHT(SERIAL,LEN(SERIAL)-INDEX(SERIAL,"-"))
                ASSIGN/SERNUM=ELEMENT(2,"-",SERIAL)
                ASSIGN/IFN="C:\Users\Public\Documents\WAI\PC-DMIS\2015.1\PN_"+PART+"_SN_"+SERNUM+".txt"
    FILEYN     =FILE/EXISTS,IFN
                IF/FILEYN
    FPTR         =FILE/OPEN,IFN,READ
                  ASSIGN/I=0
                DO/
                ASSIGN/I=I+1
                ASSIGN/DD="D"+I
                ASSIGN/TYP=""
    L1         =FILE/READLINE,FPTR,{typ}+"<"+{dd.x}+","+{dd.y}+","+{dd.z}+">;<"+{dd.i}+","+{dd.j}+","+{dd.k}+">;"+{dd.d}+";"+{dd.l}
                IF/!L1=="EOF"
                  SELECT/TYP
                    CASE/"CIRCLE"
    ISUB2            =GENERIC/CIRCLE,DEPENDENT,CARTESIAN,OUT,$
                      NOM/XYZ,<DD.X,DD.Y,DD.Z>,$
                      MEAS/XYZ,<DD.X,DD.Y,DD.Z>,$
                      NOM/IJK,<DD.I,DD.J,DD.K>,$
                      MEAS/IJK,<DD.I,DD.J,DD.K>,$
                      DIAMETER/DD.D,DD.D
                    END_CASE/
                    CASE/"CYLINDER"
    ISUB4            =GENERIC/CYLINDER,DEPENDENT,CARTESIAN,OUT,$
                      NOM/XYZ,<DD.X,DD.Y,DD.Z>,$
                      MEAS/XYZ,<DD.X,DD.Y,DD.Z>,$
                      NOM/IJK,<DD.I,DD.J,DD.K>,$
                      MEAS/IJK,<DD.I,DD.J,DD.K>,$
                      DIAMETER/DD.D,DD.D,$
                      DISTANCE/DD.L,DD.L
                    END_CASE/
                    CASE/"PLANE"
    ISUB3            =GENERIC/PLANE,DEPENDENT,CARTESIAN,$
                      NOM/XYZ,<DD.X,DD.Y,DD.Z>,$
                      MEAS/XYZ,<DD.X,DD.Y,DD.Z>,$
                      NOM/IJK,<DD.I,DD.J,DD.K>,$
                      MEAS/IJK,<DD.I,DD.J,DD.K>
                    END_CASE/
                    CASE/"LINE"
    ISUB5            =GENERIC/LINE,DEPENDENT,CARTESIAN,$
                      NOM/XYZ,<DD.X,DD.Y,DD.Z>,$
                      MEAS/XYZ,<DD.X,DD.Y,DD.Z>,$
                      NOM/IJK,<DD.I,DD.J,DD.K>,$
                      MEAS/IJK,<DD.I,DD.J,DD.K>,$
                      DISTANCE/DD.D,DD.D
                    END_CASE/
                    CASE/"VAR"
                      ASSIGN/VARCOUNTER=VARCOUNTER+1
                      ASSIGN/HITS[VARCOUNTER]=I
                      ASSIGN/VARARRAY[I]=LEFT(DD.X,LEN(DD.X)-1)
                    END_CASE/
                    DEFAULT_CASE/
    ISUB1            =GENERIC/POINT,DEPENDENT,CARTESIAN,$
                      NOM/XYZ,<DD.X,DD.Y,DD.Z>,$
                      MEAS/XYZ,<DD.X,DD.Y,DD.Z>,$
                      NOM/IJK,<DD.I,DD.J,DD.K>,$
                      MEAS/IJK,<DD.I,DD.J,DD.K>
                    END_DEFAULTCASE/
                  END_SELECT/
                END_IF/
                UNTIL/L1=="EOF"
                IF/DELYN
                  FILE/CLOSE,FPTR,DELETE
                END_IF/
                ELSE/
                  FILE/CLOSE,FPTR,KEEP
                END_ELSE/
                END_IF/
                ASSIGN/T=VARCOUNTER
                ASSIGN/U=0
                IF/!T==0
                DO/
                ASSIGN/U=U+1
                ASSIGN/VALS[U]=VARARRAY[HITS[U]]
                UNTIL/U==T
                END_IF/
                ASSIGN/RETURNVALS=VALS
                ASSIGN/RETURN=IF(FILEYN,IFN +",  File found.",IFN +",  File not found.")
                ENDSUB/
    
  • Cris_C don't say I've never given you anything...


    Holy Cow! Astonished

    I did not expect that! Thanks man. You rule!

    I've got a lot of close code reading and head scratching in my near future.
  • above code can be cleaned up substantially but the meat and potatoes are there for ya'll to improve on. Happy coding!
  • you'll drill into it and realize its not that complicated...