LDBoxer


RE: LDBoxer
#12
(2018-01-10, 7:41)Jarema Wrote: Roger that. I Take this in my free-time.

I have started fixing it myself, but the script now boxes every single part, so I must have made a mistake somewhere. Can you find the error?

Code:
'''
Created on 16 mar 2017
Updated on 10 jan 2018
@author: Jeremy Czajkowski
@author: Tore Eriksson <[email protected]>
@author: Michael Horvath
@license: GNU General Public License version 3
@version: 2017c
@note: A utility to help you replace LDraw parts with no visible studs or tubes with boxes.
       Saves rendering time and CPU power.
'''

import os
import sys
from macpath import dirname

__appname__ = "LDBoxer"
__version__ = "2017c"

NOTFOUND_MSG = "FileNotFoundError: [Errno 2] No such file or directory: '%s'"
INVALIDACCESS_MSG = "ImportError: Invalid access to %s."

CHKLST_INFILE = []
REPLACEDTOTAL_COUNT = 0

LDRAWPATH = MODELPATH = ""


def isBox(fil):    # mjh
    if fil[0:2].upper() == "B\\":
        return True
    else:
        return False


def ldLineType(ldline):
    result = -1;
    s = ldline.strip()
    if len(s)>0 :
        if s[0]=='0' : result = 0    # mjh
        if s[0]=='1' : result = 1    # mjh
        if s[0]=='2' : result = 2    # mjh
        if s[0]=='3' : result = 3    # mjh
        if s[0]=='4' : result = 4    # mjh
        if s[0]=='5' : result = 5    # mjh
    return result

def ldLineUpdate(ldline, ItemNr, NewVal):
    color1 = ldExtractFromLine(ldline, 2)
    x1 = float(ldExtractFromLine(ldline, 3))
    y1 = float(ldExtractFromLine(ldline, 4))
    z1 = float(ldExtractFromLine(ldline, 5))
    a1 = float(ldExtractFromLine(ldline, 6))
    b1 = float(ldExtractFromLine(ldline, 7))
    c1 = float(ldExtractFromLine(ldline, 8))
    d1 = float(ldExtractFromLine(ldline, 9))
    e1 = float(ldExtractFromLine(ldline, 10))
    f1 = float(ldExtractFromLine(ldline, 11))
    g1 = float(ldExtractFromLine(ldline, 12))
    h1 = float(ldExtractFromLine(ldline, 13))
    i1 = float(ldExtractFromLine(ldline, 14))
    fil = ldExtractFromLine(ldline, 15)
    
    if ItemNr == 2:
        color1 = NewVal
    if ItemNr == 3:
        x1 = float(NewVal)
    if ItemNr == 4:
        y1 = float(NewVal)
    if ItemNr == 5:
        z1 = float(NewVal)
    if ItemNr == 6:
        a1 = float(NewVal)
    if ItemNr == 7:
        b1 = float(NewVal)
    if ItemNr == 8:
        c1 = float(NewVal)
    if ItemNr == 9:
        d1 = float(NewVal)
    if ItemNr == 10:
        e1 = float(NewVal)
    if ItemNr == 11:
        f1 = float(NewVal)
    if ItemNr == 12:
        g1 = float(NewVal)
    if ItemNr == 13:
        h1 = float(NewVal)
    if ItemNr == 14:
        i1 = float(NewVal)
    if ItemNr == 15:
        fil = NewVal
    
    s = '1 ' + color1 + ' '
    s = s + FloatToLDraw(x1)+ ' '
    s = s + FloatToLDraw(y1)+ ' '
    s = s + FloatToLDraw(z1)+ ' '
    s = s + FloatToLDraw(a1)+ ' '
    s = s + FloatToLDraw(b1)+ ' '
    s = s + FloatToLDraw(c1)+ ' '
    s = s + FloatToLDraw(d1)+ ' '
    s = s + FloatToLDraw(e1)+ ' '
    s = s + FloatToLDraw(f1)+ ' '
    s = s + FloatToLDraw(g1)+ ' '
    s = s + FloatToLDraw(h1)+ ' '
    s = s + FloatToLDraw(i1)+ ' '
    s = s + fil
    return s

def ldExtractFromLine (ldline, post):
    post -= 1    # mjh
    t = []
    
    s = ldline.strip()
    iT = 0;    # mjh
    while s <> '':
        s = s.strip() + ' '
        i = 0    # mjh
        while s[i] <> ' ': i += 1
#         t[iT] = Copy(s, 1, i-1)
#         function Copy(const S: string; From: integer = 1; Count: integer = MaxInt): string;
        t.insert(iT, s[0:i])    # mjh
        iT += 1
        s = s[i+1:]    # mjh
    
    result = ''
    if post < iT: result = t[post]
    return result
    

def FloatToLDraw(inval):
    if (inval > -0.0001) and (inval < 0.0001): inval = 0
    return '%.5f' % (round(inval*10000)/10000)


def cmdReplace():
    replacedCount = 0
    for i in range(CHKLST_INFILE.__len__()):
        ldline = CHKLST_INFILE[i]
        if ldLineType(ldline) == 1 :
            fil = ldExtractFromLine(ldline, 15)
            if isBox(fil) == False : fil = strPrefix + fil
            fname = os.path.join(LDRAWPATH ,'Parts' ,fil)
            if os.path.exists(fname):
                ldline = ldLineUpdate(ldline, 15, fil)
                CHKLST_INFILE[i] = ldline + "\r\n"
                replacedCount += 1;
                global REPLACEDTOTAL_COUNT;
                REPLACEDTOTAL_COUNT += 1;
    if replacedCount>0 :
        CHKLST_INFILE.append("0 // Boxed {0} parts ({1})\r\n".format(replacedCount ,strPrefix))

if __name__ == '__main__':
    if sys.argv.__len__() != 3:
        print "Invalid arguments"
        sys.exit(2)
        
    LDRAWPATH = sys.argv[1]    # mjh, don't change
    MODELPATH = sys.argv[2]    # mjh, don't change
    
    if not os.path.isdir(LDRAWPATH):
        print NOTFOUND_MSG % LDRAWPATH
        sys.exit(2)
        
    if not os.path.isfile(MODELPATH):
        print NOTFOUND_MSG % MODELPATH
        sys.exit(2)
    
    try:
        with open(MODELPATH ,"r") as f:
            for line in f:
                CHKLST_INFILE.append(line)
            f.close()
    except:
        CHKLST_INFILE = []
        print INVALIDACCESS_MSG % MODELPATH
        sys.exit(2)
    
    else:
        print __appname__ ,__version__ ,"processing" ,MODELPATH
        
        i = ii = iii = frg = 0
        x1 = y1 = z1 = a1 = c1 = g1 = i1 = x2 = y2 = z2 = x3 = y3 = z3 = 0.0
        s = ldline = fil = ""
        SkipThis = False
        StrLstCover = []
        StrListInfil = []
        
        """
         cmdFittingsClick STEP 1: Compile a list of locations (20x20LDU)
         Tops and Bottoms that are hiding (=covering) details from next part
         Save the list in StrListCover
        """
        for i in range(CHKLST_INFILE.__len__()):
            ldline = CHKLST_INFILE[i]
            if ldLineType(ldline) <> 1: continue
            
            frg = int(ldExtractFromLine(ldline, 2));
            if (frg>31) and (frg<48): continue
            
            if ldExtractFromLine(ldline, 7) <> '0' : continue
            if ldExtractFromLine(ldline, 9) <> '0' : continue
            if ldExtractFromLine(ldline, 10) <> '1' : continue
            if ldExtractFromLine(ldline, 11) <> '0' : continue
            if ldExtractFromLine(ldline, 13) <> '0' : continue
            
            fil = ldExtractFromLine(ldline ,15);
            if len(fil)<5: continue # just to be foolproof...
            """
             2010-03-20 also check if already boxed parts cover positions
             by removing B\, B\t, or B\B from examined file reference
            """
            if fil[0:3].upper() == "B\\T":    # mjh
                fil = fil[3:]    # mjh
            
            if fil[0:3].upper() == "B\\B":    # mjh
                fil = fil[3:]    # mjh
            
            if fil[0:2].upper() == "B\\":    # mjh
                fil = fil[2:]    # mjh
            
            if len(fil)<5 : continue
            
            fil = fil[0:(len(fil)-4)]    # mjh
            
            fil = os.path.join(LDRAWPATH ,'Parts' ,'B' ,fil + '.nfo')
            
            print "Searching for" ,fil
            if not os.path.exists(fil) : continue
            
            x1 = float(ldExtractFromLine(ldline ,3))
            y1 = float(ldExtractFromLine(ldline ,4))
            z1 = float(ldExtractFromLine(ldline ,5))
            a1 = float(ldExtractFromLine(ldline ,6))
            c1 = float(ldExtractFromLine(ldline ,8))
            g1 = float(ldExtractFromLine(ldline ,12))
            i1 = float(ldExtractFromLine(ldline ,14))
            
            NFOCONTENT = []
            try:
                with open(fil ,"r") as f:
                    for line in f:
                        NFOCONTENT.append(line)
                    f.close()
            except:
                NFOCONTENT = []
                print INVALIDACCESS_MSG % fil
            
            StrListInfil = []
            StrListInfil.extend(NFOCONTENT)
            for ii in range(StrListInfil.__len__()):
                ldline = StrListInfil[ii]
                s = ldExtractFromLine(ldline, 1)
                x2 = float(ldExtractFromLine(ldline, 2))
                y2 = float(ldExtractFromLine(ldline, 3))
                z2 = float(ldExtractFromLine(ldline, 4))
                
                if s=='Top' or s=='Stud' : s = 'T '
                if s=='Bottom' : s = 'B '
                
                x3 = x1 + x2*a1 + z2*c1
                y3 = y1 + y2
                z3 = z1 + x2*g1 + z2*i1
                s = s + FloatToLDraw(x3) + ' '
                s = s + FloatToLDraw(y3) + ' '
                s = s + FloatToLDraw(z3)
                StrLstCover.append(s)
        
        """
         END of cmdFittingsClick STEP 1
         The model file in chklstInfile has been scanned for locations
          meeting all the given criterias
         For example:
         This following line meets the criteria:
         1 15  240 -48 160  1 0 0  0 1 0  0 0 1  3005.dat
         The two lines from the file Parts\B\3005.nfo is used:
         Stud 0 0 0
         Bottom 0 24 0
         The output stored in StrListCover is the following two lines:
         T 240 -48 160
         B 240 -24 160
        """
        
        
        """
         cmdFittingsClick STEP 2: Replace all parts that can be fully boxed
          Checkbox all parts that has all stud and bottom locations covered
          according to StrListCover
        """

        for i in range(CHKLST_INFILE.__len__()):
            ldline = CHKLST_INFILE[i]
            if ldLineType(ldline) <> 1 : continue;
            frg = int(ldExtractFromLine(ldline, 2))
            if (frg>31) and (frg<48) : continue
            if ldExtractFromLine(ldline, 7) <> '0' : continue
            if ldExtractFromLine(ldline, 9) <> '0' : continue
            if ldExtractFromLine(ldline, 10) <> '1' : continue
            if ldExtractFromLine(ldline, 11) <> '0' : continue
            if ldExtractFromLine(ldline, 13) <> '0' : continue
            fil = ldExtractFromLine(ldline, 15)
            if len(fil)<5 : continue
            
            fil = fil[0:(len(fil)-4)]    # mjh
            
            fil = os.path.join(LDRAWPATH ,'Parts' ,'B' ,fil + '.dat')
            if not os.path.exists(fil):  continue
            
            fil = fil[0:(len(fil)-4)]
            fil = fil + '.nfo';
            if not os.path.exists(fil): continue
            x1 = float(ldExtractFromLine(ldline, 3))
            y1 = float(ldExtractFromLine(ldline, 4))
            z1 = float(ldExtractFromLine(ldline, 5))
            a1 = float(ldExtractFromLine(ldline, 6))
            c1 = float(ldExtractFromLine(ldline, 8))
            g1 = float(ldExtractFromLine(ldline, 12))
            i1 = float(ldExtractFromLine(ldline, 14))
            
            NFOCONTENT = []
            try:
                with open(fil ,"r") as f:
                    for line in f:
                        NFOCONTENT.append(line)
                    f.close()
            except:
                NFOCONTENT = []
                print INVALIDACCESS_MSG % fil
            
            StrListInfil = []
            StrListInfil.extend(NFOCONTENT)
            SkipThis = False
            for ii in range(StrListInfil.__len__()):
                ldline = StrListInfil[ii]
                s = ldExtractFromLine(ldline, 1)
                x2 = float(ldExtractFromLine(ldline, 2))
                y2 = float(ldExtractFromLine(ldline, 3))
                z2 = float(ldExtractFromLine(ldline, 4))
                if s =='Top' : continue
                if s =='Stud' : s = 'B '      # Scan for matching B
                if s =='Bottom' : s = 'T '    # Scan for matching T
                x3 = x1 + x2*a1 + z2*c1
                y3 = y1 + y2
                z3 = z1 + x2*g1 + z2*i1
                s = s + FloatToLDraw(x3) + ' '
                s = s + FloatToLDraw(y3) + ' '
                s = s + FloatToLDraw(z3)
                SkipThis == True
                for iii in range(StrLstCover.__len__()):
                    if s==StrLstCover[iii] : SkipThis = False
                if SkipThis : break
            if SkipThis : continue
    
        strPrefix = "B\\"
        cmdReplace()

        """
          END of cmdFittingsClick STEP 2
        """    
      
      
        """
          cmdFittingsClick STEP 3: Replace all parts that studs can be removed from
          (STEPs 3 & 4 should be easily baked into STEP 2...)
        """
        for i in range(CHKLST_INFILE.__len__()):
            ldline = CHKLST_INFILE[i]
            if ldLineType(ldline) <> 1: continue;
            frg = int(ldExtractFromLine(ldline, 2));
            if (frg>31) and (frg<48) : continue;
            if ldExtractFromLine(ldline, 7) <> '0' : continue
            if ldExtractFromLine(ldline, 9) <> '0' : continue
            if ldExtractFromLine(ldline, 10) <> '1' : continue
            if ldExtractFromLine(ldline, 11) <> '0' : continue
            if ldExtractFromLine(ldline, 13) <> '0' : continue
            fil = ldExtractFromLine(ldline, 15);
            if len(fil)<5 : continue
            fil = fil[0:(len(fil)-4)]    # mjh
            fil = os.path.join(LDRAWPATH ,'Parts' ,'B' ,fil + '.dat')
            if not os.path.exists(fil) : continue
            fil = fil[0:(len(fil)-4)]    # mjh
            fil = fil + '.nfo'
            if not os.path.exists(fil) : continue
            x1 = float(ldExtractFromLine(ldline, 3))
            y1 = float(ldExtractFromLine(ldline, 4))
            z1 = float(ldExtractFromLine(ldline, 5))
            a1 = float(ldExtractFromLine(ldline, 6))
            c1 = float(ldExtractFromLine(ldline, 8))
            g1 = float(ldExtractFromLine(ldline, 12))
            i1 = float(ldExtractFromLine(ldline, 14))
            
            NFOCONTENT = []
            try:
                with open(fil ,"r") as f:
                    for line in f:
                        NFOCONTENT.append(line)
                    f.close()
            except:
                NFOCONTENT = []
                print INVALIDACCESS_MSG % fil
            
            StrListInfil = []
            StrListInfil.extend(NFOCONTENT)
            SkipThis = False
            for ii in range (StrListInfil.__len__()) :
                ldline = StrListInfil[ii]
                s = ldExtractFromLine(ldline, 1)
                x2 = float(ldExtractFromLine(ldline, 2))
                y2 = float(ldExtractFromLine(ldline, 3))
                z2 = float(ldExtractFromLine(ldline, 4))
                if s =='Top' : continue
                #if s == 'Stud': continue
                if s =='Stud' : s = 'B '      # Scan for matching B
                if s =='Bottom' : continue
                #if s == 'Bottom': s = 'T '    # Scan for matching T
                x3 = x1 + x2*a1 + z2*c1
                y3 = y1 + y2
                z3 = z1 + x2*g1 + z2*i1
                s = s + FloatToLDraw(x3) + ' '
                s = s + FloatToLDraw(y3) + ' '
                s = s + FloatToLDraw(z3)
                SkipThis = True;
                for iii in range (StrLstCover.__len__()) :
                    if s==StrLstCover[iii] : SkipThis = False
                if SkipThis : break
            if SkipThis : continue
        strPrefix = 'B\\T'
        cmdReplace()
        """
          END of cmdFittingsClick STEP 3
        """
      
      
        """
         cmdFittingsClick STEP 4: Replace all parts that bottom details
          can be removed from
         (STEPs 3 & 4 should be easily baked into STEP 2...)
        """
        for i in range (CHKLST_INFILE.__len__()) :
            ldline = CHKLST_INFILE[i];
            if ldLineType(ldline) <> 1 : continue;
            frg = int(ldExtractFromLine(ldline, 2));
            if (frg>31) and (frg<48) : continue;
            if ldExtractFromLine(ldline, 7) <> '0' : continue;
            if ldExtractFromLine(ldline, 9) <> '0' : continue;
            if ldExtractFromLine(ldline, 10) <> '1' : continue;
            if ldExtractFromLine(ldline, 11) <> '0' : continue;
            if ldExtractFromLine(ldline, 13) <> '0' : continue;
            fil = ldExtractFromLine(ldline, 15);
            if len(fil)<5 : continue
            fil = fil[0:(len(fil)-4)]    # mjh
    
            fil = os.path.join(LDRAWPATH ,'Parts' ,'B' ,fil + '.dat')
            if not os.path.exists(fil) : continue
            fil = fil[0:(len(fil)-4)]    # mjh
            fil = fil + '.nfo'
          
            if not os.path.exists(fil) : continue
          
            x1 = float(ldExtractFromLine(ldline, 3))
            y1 = float(ldExtractFromLine(ldline, 4))
            z1 = float(ldExtractFromLine(ldline, 5))
            a1 = float(ldExtractFromLine(ldline, 6))
            c1 = float(ldExtractFromLine(ldline, 8))
            g1 = float(ldExtractFromLine(ldline, 12))
            i1 = float(ldExtractFromLine(ldline, 14))
            
            NFOCONTENT = []
            try:
                with open(fil ,"r") as f:
                    for line in f:
                        NFOCONTENT.append(line)
                    f.close()
            except:
                NFOCONTENT = []
                print INVALIDACCESS_MSG % fil
            
            StrListInfil = []
            StrListInfil.extend(NFOCONTENT)
            SkipThis = False
            for ii in range (StrListInfil.__len__()) :
                ldline = StrListInfil[ii];
                s = ldExtractFromLine(ldline, 1)
                x2 = float(ldExtractFromLine(ldline, 2))
                y2 = float(ldExtractFromLine(ldline, 3))
                z2 = float(ldExtractFromLine(ldline, 4))
                if s=='Top' : continue
                if s=='Stud' : continue
                if s=='Stud' : s = 'B '    # Scan for matching B
                #if s=='Bottom' : continue
                if s=='Bottom' : s = 'T '  # Scan for matching T
                x3 = x1 + x2*a1 + z2*c1
                y3 = y1 + y2
                z3 = z1 + x2*g1 + z2*i1
                s = s + FloatToLDraw(x3) + ' '
                s = s + FloatToLDraw(y3) + ' '
                s = s + FloatToLDraw(z3)
                SkipThis = True
                for iii in range (StrLstCover.__len__()) :
                    if s==StrLstCover[iii] : SkipThis = False
                if SkipThis : break
            if SkipThis : continue
        strPrefix = 'B\\B'
        cmdReplace()
        """
          END of cmdFittingsClick STEP 4
        """  
        
        print
        print "Boxed %d parts" % REPLACEDTOTAL_COUNT
                
        if REPLACEDTOTAL_COUNT>0 :      
        
        # 0 !LDOXER LEVEL info should also be automatically updated!
            CHKLST_INFILE.append("0 // Boxed Total {0} parts by {1} v{2}\r\n".format(REPLACEDTOTAL_COUNT ,__appname__ ,__version__))
            CHKLST_INFILE.append("0")

            try:
                dirname = os.path.dirname(MODELPATH)
                basename = "boxed_" + os.path.basename(MODELPATH)
                with open(os.path.join(dirname,basename) ,"wb") as f:
                    for line in CHKLST_INFILE:
                        f.write(line)
                    f.close()
            except Exception, ex:
                print ex.message
            else:
                print "Saved {0} in {1}".format(basename ,dirname)

[edit]

I updated the code with a few fixes.
Reply
« Next Oldest | Next Newest »



Messages In This Thread
LDBoxer - by Michael Horvath - 2016-08-27, 16:03
RE: LDBoxer - by Michael Horvath - 2016-08-27, 19:09
RE: LDBoxer - by Michael Horvath - 2016-08-27, 19:25
RE: LDBoxer - by Jarema - 2017-03-16, 20:54
RE: LDBoxer - by Michael Horvath - 2017-03-16, 23:01
RE: LDBoxer - by Jarema - 2017-03-17, 6:27
RE: LDBoxer - by Jarema - 2017-03-18, 13:30
RE: LDBoxer - by Michael Horvath - 2017-04-09, 6:21
RE: LDBoxer - by Michael Horvath - 2018-01-07, 19:18
RE: LDBoxer - by Jarema - 2018-01-10, 7:41
RE: LDBoxer - by Michael Horvath - 2018-01-10, 21:43
RE: LDBoxer - by Michael Horvath - 2018-01-10, 23:37
RE: LDBoxer - by Jarema - 2018-01-14, 9:05
RE: LDBoxer - by Michael Horvath - 2018-01-14, 11:44
RE: LDBoxer - by Jarema - 2018-01-14, 15:29
RE: LDBoxer - by Tore Eriksson - 2018-01-15, 22:15
RE: LDBoxer - by Michael Horvath - 2018-01-16, 0:28
RE: LDBoxer - by Tore Eriksson - 2018-01-16, 19:22
RE: LDBoxer - by Michael Horvath - 2018-01-16, 23:21
RE: LDBoxer - by Tore Eriksson - 2018-02-24, 11:07
RE: LDBoxer - by Michael Horvath - 2018-02-24, 17:34
RE: LDBoxer - by Michael Horvath - 2018-01-25, 2:22
RE: LDBoxer - by Michael Horvath - 2018-01-26, 9:52
RE: LDBoxer - by Michael Horvath - 2018-01-27, 8:45
RE: LDBoxer - by Jarema - 2018-01-27, 15:28
RE: LDBoxer - by Michael Horvath - 2018-01-30, 1:18
RE: LDBoxer - by Michael Horvath - 2018-02-02, 13:31

Forum Jump:


Users browsing this thread: 6 Guest(s)