# Python FillAllHoles

**URL:** <https://discourse.mcneel.com/t/python-fillallholes/19426>\
**Category:** Scripting\
**Created:** [April 27, 2015, 3:57pm UTC](https://discourse.mcneel.com/t/python-fillallholes/19426 "2015-04-27T15:57:48Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![radio412](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/radio412/32/18475_2.png) [@radio412](https://discourse.mcneel.com/u/radio412)\
**Post date:** [April 27, 2015, 3:57pm UTC](https://discourse.mcneel.com/t/python-fillallholes/19426/1 "2015-04-27T15:57:48Z")

</div>

Hello,

I have the following script which exports obj files, working well. However on export when I display the obj file I am getting holes in the meshes when displayed in webGL. I do not understand if I am simply decimating the mesh to much. They seem to appear rather randomly, but I understand I am using a one size fits all export which may not be ideal.

Regardless, I found if I create the mesh manually in the GUI I can then also select an option to fill all holes. This fixes the issue, but I would like to incorporate a fill all holes step in my export. I don’t understand at what point I would do this step. Do I need to write a script which adds the mesh to the Rhino environment to access the command? The command I found is FillMeshHoles: [http://docs.mcneel.com/rhino/5/help/en-us/commands/fillmeshholes.htm](http://docs.mcneel.com/rhino/5/help/en-us/commands/fillmeshholes.htm) when the mesh is selected.

The script:

```
    import os
    import scriptcontext
    import rhinoscriptsyntax as rs
    
    
    print "//export run started/////////////"
    
    # this function via mcneel/rhinoscriptsyntax
    #https://github.com/mcneel/rhinoscriptsyntax/blob/master/Scripts/rhinoscript/layer.py
    def layerNames(sort=False):
        rc = []
        for layer in scriptcontext.doc.Layers:
            if not layer.IsDeleted: rc.append(layer.FullPath)
        if sort: rc.sort()
        return rc
    
    def GetDAESettings():
        e_str = ""
        return e_str
    
    def GetOBJSettings():
        e_str = "_Geometry=_Mesh "
        e_str+= "_EndOfLine=CRLF "
        e_str+= "_ExportRhinoObjectNames=_ExportObjectsAsOBJGroups "
        e_str+= "_ExportMeshTextureCoordinates=_Yes "
        e_str+= "_ExportMeshVertexNormals=_Yes "
        e_str+= "_CreateNGons=_No "
        e_str+= "_ExportMaterialDefinitions=_No "
        e_str+= "_YUp=_No "
        e_str+= "_WrapLongLines=Yes "
        e_str+= "_VertexWelding=_Welded "
        e_str+= "_WritePrecision=8 "
        e_str+= "_Enter "
    
        e_str+= "_DetailedOptions "
        e_str+= "_JaggedSeams=_No "
        e_str+= "_PackTextures=_No "
        e_str+= "_Refine=_Yes "
        e_str+= "_SimplePlane=_Yes "
    
        e_str+= "_AdvancedOptions "
        e_str+= "_Angle=70 "
        e_str+= "_AspectRatio=0 "
        e_str+= "_Distance=0.0 "
        e_str+= "_Density=0.4 "
        e_str+= "_Grid=0 "
        e_str+= "_MaxEdgeLength=0 "
        e_str+= "_MinEdgeLength=0.0001 "
    
        e_str+= "_Enter _Enter"
    
        return e_str

def GetSTLSettings():
    eStr = "_ExportFileAs=_Binary "
    eStr+= "_ExportUnfinishedObjects=_Yes "
    eStr+= "_UseSimpleDialog=_No "
    eStr+= "_UseSimpleParameters=_No "
    eStr+= "_Enter _DetailedOptions "
    eStr+= "_JaggedSeams=_No "
    eStr+= "_PackTextures=_No "
    eStr+= "_Refine=_Yes "
    eStr+= "_SimplePlane=_No "
    eStr+= "_AdvancedOptions "
    eStr+= "_Angle=15 "
    eStr+= "_AspectRatio=0 "
    eStr+= "_Distance=0.01 "
    eStr+= "_Grid=16 "
    eStr+= "_MaxEdgeLength=0 "
    eStr+= "_MinEdgeLength=0.0001 "
    eStr+= "_Enter _Enter"
    return eStr

settingsList = {
    'GetDAESettings': GetDAESettings,
    'GetOBJSettings': GetOBJSettings,
    'GetSTLSettings': GetSTLSettings
}

fileName = rs.DocumentName()
filePath = rs.DocumentPath().rstrip(fileName)

arrLayers = layerNames(False)

def initExportByLayer(fileType="obj", visibleonly=False, byObject=False):
    for layerName in arrLayers:
        layer = scriptcontext.doc.Layers.FindByFullPath(layerName, True)
        if layer >= 0:
            layer = scriptcontext.doc.Layers[layer]
            save = True;
            if visibleonly:
                if not layer.IsVisible:
                    save = False
            if rs.IsLayerEmpty(layerName):
                save = False
            if save:
                cutName = layerName.split("::")
                cutName = cutName[len(cutName)-1]
                objs = scriptcontext.doc.Objects.FindByLayer(cutName)
                if len(objs) > 0:
                    if byObject:
                        i=0
                        for obj in objs:
                            i= i+1

                            saveObjectsToFile(cutName+"_"+str(i), [obj], fileType)
                    else:
                        saveObjectsToFile(cutName, objs, fileType)

def saveObjectsToFile(name, objs, fileType):
    rs.EnableRedraw(False)
    if len(objs) > 0:
        settings = settingsList["Get"+fileType.upper()+"Settings"]()
        rs.UnselectAllObjects()
        for obj in objs:
            obj.Select(True)
        name = "".join(name.split(" "))
        command = '-_Export "{}{}{}" {}'.format(filePath+fileType+"/", name, "."+fileType.lower(), settings)
        rs.Command(command, True)
        rs.EnableRedraw(True)

initExportByLayer("obj",True, False)

print "//export run ended/////////////"
```

---

<div class="post-metadata">

**Author:** ![dale](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/dale/32/685184_2.png) [@dale](https://discourse.mcneel.com/u/dale)\
**Post date:** [April 27, 2015, 4:02pm UTC](https://discourse.mcneel.com/t/python-fillallholes/19426/2 "2015-04-27T16:02:58Z")

</div>

> [@radio412](#):
>
> I have the following script which exports obj files, working well. However on export when I display the obj file I am getting holes in the meshes when displayed in webGL.

If you export the OBJ file and then re-import back into Rhino, do you see holes? How are you generating your WebGL? Have you seen this?

[http://www.food4rhino.com/project/iris?ufh](http://www.food4rhino.com/project/iris?ufh)

---

<div class="post-metadata">

**Author:** ![radio412](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/radio412/32/18475_2.png) [@radio412](https://discourse.mcneel.com/u/radio412)\
**Post date:** [April 27, 2015, 4:16pm UTC](https://discourse.mcneel.com/t/python-fillallholes/19426/3 "2015-04-27T16:16:05Z")

</div>

I do not see holes on re-import. 😕

I had not seen that plugin. I am following a very similar workflow using three.js.

---

<div class="post-metadata">

**Author:** ![clement](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/clement/32/759176_2.png) [@clement](https://discourse.mcneel.com/u/clement)\
**Post date:** [April 27, 2015, 5:15pm UTC](https://discourse.mcneel.com/t/python-fillallholes/19426/4 "2015-04-27T17:15:50Z")

</div>

> [@radio412](#):
>
> \_WrapLongLines=Yes

What happens if you set this to \_No ? Also one note, if your mesh has custom texture coordinates assigned, you might set the `_VertexWelding` to `_Unmodified`.

- 

c.

---

<div class="post-metadata">

**Author:** ![gabrielPresents](https://avatars.discourse-cdn.com/v4/letter/g/0ea827/32.png) [@gabrielPresents](https://discourse.mcneel.com/u/gabrielPresents)\
**Post date:** [November 3, 2016, 9:11am UTC](https://discourse.mcneel.com/t/python-fillallholes/19426/5 "2016-11-03T09:11:35Z")

</div>

Try to use UnifyMeshNormals. Even though a mesh is closed it can appear open before you unify the mesh normals.
