Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Warning: unsupported shape SVGNODE [...]" #38

Closed
planetsLightningArrester opened this issue Jun 12, 2020 · 4 comments
Closed

"Warning: unsupported shape SVGNODE [...]" #38

planetsLightningArrester opened this issue Jun 12, 2020 · 4 comments
Labels
bug Something isn't working

Comments

@planetsLightningArrester

Hi.

I developed a simple PCB that I'd like to import in FreeCAD using this addon which seems to works great with some .kicad_pcb files from a KiCad project.

I can generate my EasyEDA file "input.json" an get the "output.kicad_pcb" in both Node library on my pc and the online converter. But FreeCAD can't open the file. As I pointed out it seems to work just fine with another directly generated .kicad_pcb files so I don't think the issue is the addon.

I got two warnings:

Running easyeda2kicad v1.8.0:
Reading file input.json...
Parsing content...
Detected EasyEDA board (PCB) file.
Warning: unsupported shape SVGNODE in footprint ggef90f9c042f2df78c
Warning: unsupported shape SVGNODE in footprint gge5701536e7eb809af
Writing output to input.kicad_pcb...
Conversion done!

I can make FreeCAD open the file if I open the "output.kicad_pcb" in KiCad and save it as another file. The input.json, output.kicad_pcb and the savedAsWorking.kicad_pcb files are attached. It may be an enhancement once it works to open the output in Kicad. But it would be really nice to have this converter to works just like a KiCad "Save as ..". Anyway thank you so much for your time and let me know if I can help you with more info.

inOutFiles.zip
SavedAsWorking.zip

Windows 10 Home
Chrome 83.0.4103.97
EasyEDA v6.3.53
Node v12.16.3
NPM v6.14.4

@urish urish added the bug Something isn't working label Jun 13, 2020
@urish
Copy link
Collaborator

urish commented Jun 13, 2020

Thanks for reporting! Does the FreeCAD plugin report any specific error?

@planetsLightningArrester
Copy link
Author

planetsLightningArrester commented Jun 13, 2020

Hi!
At first, it doesn't prompt any useful error just: "Incompatible file format". So I looked over the addon python files and it seems that it was just that the addon looks in the first line of the file for the kicad description like:

"(kicad_pcb (version 20171130) (host pcbnew "(5.1.6)-1")"

Which is in the second line of your generated file. This error is resolved just deleting the first empty line of the .kicad_pcb output file.

But loading the files still prompts a lot of errors. I'm pretty sure its because the addon uses regex expression expecting a specific indentation/spacing/formatting for the whole file. For example layer "F.SilkS", fp_text reference "R1" and every other layer/net_name and so must not have quotation marks. For the addon identifies it correctly it should be layer F.SilkS, fp_text reference R1. Change it all resolves some issues.

But the formatting issues are more complex. Following this error:

[' D1(at 0.762 1.016 0)(layer F.SilkS)\n      (effects (font (size 1.143 1.143) (thickness 0.152)) (justify left)'][]Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\franc\AppData\Roaming\FreeCAD\Mod\pcb\PCBbrd.py", line 66, in open
    importBRD(filename, wersjaFormatu[0])
  File "C:\Users\franc\AppData\Roaming\FreeCAD\Mod\pcb\PCBbrd.py", line 235, in importBRD
    plytka = plytkaPCB.generate(doc)
  File "C:\Users\franc\AppData\Roaming\FreeCAD\Mod\pcb\formats\PCBmainForms.py", line 134, in generate
    self.importParts()
  File "C:\Users\franc\AppData\Roaming\FreeCAD\Mod\pcb\formats\PCBmainForms.py", line 247, in importParts
    for i in self.wersjaFormatu.getParts():
  File "C:\Users\franc\AppData\Roaming\FreeCAD\Mod\pcb\formats\kicad_v3.py", line 833, in getParts
    i['EL_Name'] = dataName[0]
<class 'IndexError'>: list index out of range

I reached this method:

        def getParts(self):
        self.getElements()
        parts = []
        ###########
        for i in self.elements:
            if i['side'] == 1:
                i['side'] = "TOP"
            else:
                i['side'] = "BOTTOM"
            ####################################
            dataName = self.getAnnotations(re.findall(r'\(fp_text reference(.+?)\)\n\s+\)\n\s+\(', i['dataElement'], re.MULTILINE|re.DOTALL), mode='param')
            i['EL_Name'] = dataName[0]
            i['EL_Name']["text"] = "NAME"
            i['EL_Name']["x"] = i['EL_Name']["x"] + i["x"]
            i['EL_Name']["y"] = i['EL_Name']["y"] + i["y"]
            i['EL_Name']["rot"] = i['EL_Name']["rot"] - i["rot"]
            ####################################
            dataValue = self.getAnnotations(re.findall(r'\(fp_text value(.+?)\)\n\s+\)\n\s+\(', i['dataElement'], re.MULTILINE|re.DOTALL), mode='param')
            i['EL_Value'] = dataValue[0]
            i['EL_Value']["text"] = "VALUE"
            i['EL_Value']["x"] = i['EL_Value']["x"] + i["x"]
            i['EL_Value']["y"] = i['EL_Value']["y"] + i["y"]
            i['EL_Value']["rot"] = i['EL_Value']["rot"] - i["rot"]
            ####################################
            parts.append(i)
        #
        return parts

And dataName returns an empty list most of the time which rises index errors on the next line. The getAnnotations method is as follows.

    def getAnnotations(self, data, mode='anno'):
        adnotacje = []
        #
        for i in data:
            try:
                txt = re.search(r'\s(.*?)\s\(at', i).groups(0)[0].replace('"', '').replace('\r\n', '\n').replace('\r', '\n').replace('\\n', '\n')
                [x, y, rot] = re.search(r'\(at\s+([0-9\.-]*?)\s+([0-9\.-]*?)(\s+[0-9\.-]*?|)\)', i).groups()
                layer = re.search(r'\(layer\s+(.+?)\)', i).groups()[0]
                size = re.search(r'\(size\s+([0-9\.]*?)\s+[0-9\.]*?\)', i).groups()[0]
                justify = re.findall(r'( \(justify .*?\)|)\)', i)[-1].strip()
            except:
                continue
            #
            if rot == '':
                rot = 0.0
            else:
                rot = float(rot)
            
            if layer.startswith('F.') or (self.spisWarstw[layer] in [15, 21] and self.databaseType == "kicad") or (self.spisWarstw[layer] in [0, 33, 35, 37, 39, 40, 41, 42, 43, 44, 45, 47, 49] and self.databaseType == "kicad_v4"):
                side = 'TOP'
            else:
                side = 'BOTTOM'
            
            extra = re.findall(r'\(justify( [left|right]+|)( mirror|)\)', justify, re.DOTALL)
            if len(extra):
                if extra[0][0].strip() == 'right':
                    align = 'center-right'
                elif extra[0][0].strip() == 'left':
                    align = 'center-left'
                else:
                    align = 'center'
                
                if extra[0][1].strip() == 'mirror':
                    mirror = 2
                else:
                    mirror = 0
            else:
                align = 'center'
                mirror = False

            adnotacje.append({
                "text": txt,
                "x": float(x),
                "y": float(y) * (-1),
                "z": 0,
                "size": float(size),
                "rot": rot,
                "side": side,
                "align": align,
                "spin": False,
                "font": 'Proportional',
                "display": True,
                "distance": 1,
                "tracking": 0,
                "mirror": mirror,
                "mode": mode
            })
        #
        return adnotacje

So the file must follow the regex expressions so the addon can identify the parameters. It's not robust for files slightly different.

@urish
Copy link
Collaborator

urish commented Jun 13, 2020

Thanks for looking into this!

Removing the first empty line should be simple, but it seems like the correct solution would actually be to rewrite the parser of the FreeCAD-PCB addon to parse the file according to the the S-expression format (section 4 describes the format). It shouldn't be too hard - the JavaScript code that parses this format takes roughly 60 lines of code.

But IMHO, the best solution for you could just be to create a python script that will load the file in pcbnew, and then save it again under a different name. I believe that should take less than 10 lines of code, and will probably be the lowest hanging fruit here.

@planetsLightningArrester
Copy link
Author

I'll probably stick with Python script's solution. Thank you so much for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants