Blender (jusqu'à 2.49)
Python
Import KMZ/KML, 
Google Earth 3 only
with Modules Mesh and NMesh 
 (french version)
    Début   Index
précédentScript Python
Spot and lampNext

 
The  Fill() function
The  Google Earth file format
To create meshes with Mesh modules  and fill    (updated : 2007/09/11 )
To create meshes with NMesh module but with faked fill() function (updated : 2006/05/25

External links

The  Fill() function

Attention, the script needs  3 conditions to use  correctly the fill function  : 
1/ At least one 3D window must be open in the the work space
2/ Work space must be set in "Global"  (the layer panel can be saw in the blender task bar, it 's ok)  and not in "Local"
3/ You have to make the import in Object modebut the vertex mode must be active


 
The  kmz file format

Attention, kmz has been modified . This script only imports  simple kmz format  not the last Google Earth 4 format 

Import by Mesh module and fill (tested on big  files : 30000 polygons )
 

__version__= "0.1.9k,  september, 11th, 2007" :  very short correction on the create_LINE function.
Download  the script  0.1.9k with build in zipfile 

__version__= "0.1.9j,  march, 27th, 2007" :  (oups! ) very short correction on a test to identify the kml 2.0 files...
Download  the script  0.1.9j with build in zipfile 

__version__ = "0.1.9i,  march, 5th, 2007" : a better method (again) to recognize google earth 4 format. Many changes to manag the use with python 2.5 in the current   Blender CVS without the complete installation of python (usefull under win32 system)
Download  the script  0.1.9i with build in zipfile 

__version__ = "0.1.9h,  february, 13th, 2007" : beter method to recognize google earth 4 format 
Download  the script  0.1.9h with build in zipfile 

__version__ = "0.1.9g,  february, 2007" :  modifs  but without any gain or speed up, in fact, just to avoid that the Mesh module could rot the RAM by the creation of a lot of pyobjects. 
Download  the script  0.1.9g with build in zipfile 


__version__ = "0.1.9f,  31 january , 2007" : modification of the asked by blender bundle scripts + one or two button to select the progression  indicators display .
Download  the script  0.1.9f with build in zipfile 


__version__ = "0.1.9c,  16 Aout , 2006" : modification of the   constant  for  conversion of latitude and longitude degres in meters . 
Download  the script  0.1.9c with build in zipfile 
 

__version__ = "0.1.9b,  12 Aout , 2006" :
Addition of dialogue panels  to manage the importation of the edges (not always necessary since they are sometime used only to  underline the forms already drawn with the polygons). 

   Note that this importation is made by default and  it is necessary to unset this option to make it inactive. 
Idem for the Double Remove option. 
It is now obligatory to press on button OK to launch the importation. 
Download  the script  0.1.9b with build in zipfile 

__version__ = "0.1.9,  11 Aout , 2006" :
Force to read all the linestrings even when there is no polygon
Download  the script  0.1.9 with build in zipfile 

__version__ = "0.1.8d,  August 10th, 2006" :
additional mesh for all the linestring found in the file 
Download  the script  0.1.8 with build in zipfile 

__version__ = "0.1.8c,  july 13th, 2006" :
a version for fussyness users 
Download  the script  0.1.8 with build in zipfile 

__version__ = "0.1.8,  june 25th, 2006" :
Removed an unused class in the included zipfile.py (the 0.1.8c is a version for fussyness users) 
Download  the script  0.1.8 with build in zipfile 

__version__ = "0.1.7,  june 14th, 2006" :
Force brute import for missed colors 
Download  the script  0.1.7 with build in zipfile 

__version__ = "0.1.6,  june 05th, 2006" :
Manage file with html code 
Download  the script  0.1.6 
Download  the script  0.1.6 with build in zipfile 

__version__ = "0.1.5,  june 04, 2006" :
Manage file with no geometry 
Download  the script  0.1.5 

__version__ = "0.1.4, 25 May 2006" :
Manage color by placemark 
Download  the script  0.1.4 

__version__ = "0.1.3, 20 May 2006" :
Manage placemark

__version__ = "0.1.2, 17 May 2006" :
Manage inner boundary
Download  the (older) script  0.1.2 +  build in zipfile.py 
 

#!BPY

""" Registration info for Blender menus
Name: 'KMZ/KML import''
Blender: 241
Group: 'Import'
Tip: 'Import geometry of .kml or .kmz 3D models'
"""

__author__ = "Jean-Michel Soler (jms)"
__version__ = "0.1.9, august, 11th, 2006"
__bpydoc__ = """\
       To read 3d geometry .kmz and .kml file 

       Caution  : the geometry data of the Google Earth's files on the web 
       are licended  and you can not load or use it in a personnal work .
       Be aware that the containt of the file you try to read must be free 
       or legaly your's .

  Attention, this script uses the Blender's intern fill() function to create 
  certain complex faces but to work correctly this function  needs a few 
  conditions :

  1/ At least one 3D window must be open in the the work space

  2/ Work space must be set in "Global"  (the layer panel can be saw in the blender task bar, it 's ok)  and not in "Local"

  3/ You have to make the import in Object modebut the vertex mode must be active. 
 

"""
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2006: jm soler, jmsoler_at_free.fr
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# --------------------------------------------------------------------------

import Blender
from Blender  import Window
import sys
from Blender import Mathutils
BLversion=Blender.Get('version')

try:
 import nt
 os=nt
 os.sep='\\'

except: 
 import posix
 os=posix
 os.sep='/'

def isdir(path):
 try:
  st = os.stat(path)
  return 1 
 except:
  return 0

def split(pathname):
 if pathname.find(os.sep)!=-1:
  k0=pathname.split(os.sep)
 else:
  if os.sep=='/':
   k0=pathname.split('\\')
  else:
   k0=pathname.split('/') 

 directory=pathname.replace(k0[len(k0)-1],'')
 Name=k0[len(k0)-1]
 return directory, Name

def join(l0,l1): 
 return  l0+os.sep+l1

os.isdir=isdir
os.split=split
os.join=join

def fonctionSELECT(nom):
 scan_FILE(nom)

def filtreFICHIER(nom):
 """
 Function  filtreFICHIER
 in  : string  nom , filename
 out : string of data   , if correct filecontaint 
 """
 if nom.upper().find('.KMZ')!=-1:
  from zipfile import ZipFile, ZIP_DEFLATED
  tz=ZipFile(nom,'r',ZIP_DEFLATED)
  t = tz.read(tz.namelist()[0])
  tz.close()
  t=t.replace('<br>','') 
  return t
 elif nom.upper().find('.KML')!=-1:
  tz=open(nom,'r')
  t = tz.read()
  tz.close()
  t=t.replace('<br>','')
  return t
 else : 
  return None
# ....
# needed to global call
# ....
OB = None 
SC = None 
ME=  None

POLYGON_NUMBER=0
DOCUMENTORIGINE=[]
UPDATE_V=[]
UPDATE_F=[]
POS=0
NUMBER=0
PLACEMARK=0

eps=0.0000001
npoly=0
gt1=Blender.sys.time()

def create_LINE(BROKEN_LINE,tv):
 me = Blender.Mesh.New('myMesh') 
 ob = Blender.Object.New('Mesh','myObj') 
 ob.link(me)
 sc = Blender.Scene.GetCurrent() 
 sc.link(ob)
 v=me.verts
 e=me.edges
 for bl in BROKEN_LINE:
  #print bl
  v.extend(bl)
  e.extend(v[-2],v[-1])
  v[-2].sel=1
  v[-1].sel=1 
 if tv :
  me.remDoubles(0.0001)

def cree_POLYGON(ME,TESSEL):
 global  OB, npoly, UPDATE_V, UPDATE_F, POS
 npoly+=1 
 for T in TESSEL: del T[-1]
 if npoly %100 == 1 : 
  print 'Pgon: ', npoly, 'verts:',[len(T) for T in TESSEL]

 if npoly %250 == 1 : 
  Blender.Window.RedrawAll()
  g2= Blender.sys.time()-gt1
  print int(g2/60),':',int(g2%60) 

 if len(TESSEL)==1 and len(TESSEL[0]) in [3,4] :
  if not UPDATE_F:
     POS=len(ME.verts)

  for VE in TESSEL[0]:
      UPDATE_V.append(VE)

  if len(TESSEL[0])==3:
     UPDATE_F.append([POS,POS+1,POS+2])
     POS+=3
  else :
     UPDATE_F.append([POS,POS+1,POS+2,POS+3])
     POS+=4
 else :
  if UPDATE_V : ME.verts.extend(UPDATE_V)
  FACES=[]
  if UPDATE_F:
   for FE in UPDATE_F:
    if len(FE)==3:
     FACES.append([ME.verts[FE[0]],ME.verts[FE[1]],ME.verts[FE[2]]]) 
    else :
     FACES.append([ME.verts[FE[0]],ME.verts[FE[1]],ME.verts[FE[2]],ME.verts[FE[3]]])
  if FACES:
    ME.faces.extend(FACES)
    FACES=[]
  UPDATE_F=[]
  UPDATE_V=[]
  EDGES=[]
  for T in TESSEL: 
   ME.verts.extend(T)
   for t in range(len(T),1,-1):
      ME.verts[-t].sel=1
      EDGES.append([ME.verts[-t],ME.verts[-t+1]])
   ME.verts[-1].sel=1
   EDGES.append([ME.verts[-1],ME.verts[-len(T)]])
   ME.edges.extend(EDGES)
  ME.fill()
  if npoly %500 == 1 :
   for v in ME.verts:
    v.sel=1
   ME.remDoubles(0.0)
  for v in ME.verts:
      v.sel=0
 TESSEL=[] 
 return ME,TESSEL

def cree_FORME(v,TESSEL):
   VE=[(v[0]-DOCUMENTORIGINE[0])* 85331.2,
       (v[1]-DOCUMENTORIGINE[1])* 110976.0,
       (v[2]-DOCUMENTORIGINE[2])  ]
   TESSEL.append(VE)

def active_FORME():
 global ME, UPDATE_V, UPDATE_F, POS, OB
 if len(UPDATE_V)>2 :
  #print UPDATE_V
  ME.verts.extend(UPDATE_V)
  FACES=[]
  #print UPDATE_F,  len(UPDATE_F)
  for FE in UPDATE_F:
   #print FE
   if len(FE)<4:
    FACES.append([ME.verts[FE[0]],ME.verts[FE[1]],ME.verts[FE[2]]]) 
   else :
    FACES.append([ME.verts[FE[0]],ME.verts[FE[1]],ME.verts[FE[2]],ME.verts[FE[3]]])
   #if len(ME.faces)%200==1 : print len(ME.faces) 
  if FACES: 
   ME.faces.extend(FACES)
 UPDATE_V=[]
 UPDATE_F=[]
 POS=0
 if len(ME.verts)>0:
  for v in ME.verts:
   v.sel=1
  ME.remDoubles(0.0)

def wash_DATA(ndata):
 if ndata!='':
  ndata=ndata.replace('\n',',')
  ndata=ndata.replace('\r','') 
  while ndata[-1]=='  ': 
   ndata=ndata.replace('  ',' ')
  while ndata[0]==' ': 
   ndata=ndata[1:]
  while ndata[-1]==' ': 
   ndata=ndata[:-1] 
  if ndata[0]==',':ndata=ndata[1:]
  if ndata[-1]==',':ndata=ndata[:-1]
  ndata=ndata.replace(',,',',') 
  ndata=ndata.replace(' ',',')
  ndata=ndata.split(',')
  for n in ndata :
   if n=='' : ndata.remove(n) 
 return  ndata 

def collecte_ATTRIBUTS(data):
  data=data.replace('  ',' ')
  ELEM={'TYPE':data[1:data.find(' ')]}
  t1=len(data)
  t2=0
  ct=data.count('="')
  while ct>0:
   t0=data.find('="',t2)
   t2=data.find(' ',t2)+1
   id=data[t2:t0]
   t2=data.find('"',t0+2)
   if id!='d':
    exec "ELEM[id]=\"\"\"%s\"\"\""%(data[t0+2:t2].replace('\\','/'))
   else:
    exec "ELEM[id]=[%s,%s]"%(t0+2,t2) 
   ct=data.count('="',t2)
  return ELEM

def contruit_HIERARCHIE(t,tv=0):
 global DOCUMENTORIGINE, OB , ME, SC 
 global NUMBER, PLACEMARK, POLYGON_NUMBER
 vv=[]
 TESSEL=[]
 BROKEN_LINE=[]
 OB = Blender.Object.New('Mesh') 
 SC.link(OB)
 ME= OB.getData(mesh=1)
 [O.select(0) for O in Blender.Scene.getCurrent().getChildren()]
 OB.select(1)

 t=t.replace('\t',' ')
 while t.find('  ')!=-1:
       t=t.replace('  ',' ')
 n0=0 
 t0=t1=0
 baliste=[]
 balisetype=['?','?','/','/','!','!']
 BALISES=['D',  #DECL_TEXTE',
      'D',  #DECL_TEXTE',
      'F',  #FERMANTE',
      'E',  #ELEM_VIDE',
      'd',  #DOC',
      'R',  #REMARQUES',
      'C',  #CONTENU',
      'O'   #OUVRANTE'
      ]

 TAGS = ['kml','Document','description','DocumentSource',
   'DocumentOrigin','visibility','LookAt',
  'Folder','name','heading','tilt','latitude',
  'longitude','range','Style','LineStyle','color',
  'Placemark','styleUrl','GeometryCollection',
  'Polygon','LinearRing','outerBoundaryIs',
  'altitudeMode','coordinates','LineString',
   'fill','PolyStyle','outline','innerBoundaryIs',
   'IconStyle', 'Icon', 'x','y' ,'w','href','h'
   ]

 STACK=[]
 latitude = float(t[t.find('<latitude>')+len('<latitude>'):t.find('</latitude>')])
 longitude = float(t[t.find('<longitude>')+len('<longitude>'):t.find('</longitude>')])
 DOCUMENTORIGINE=[longitude,latitude,0 ]

 GETMAT=0
 MATERIALS=[M.getName() for M in Blender.Material.Get()]
 while t1<len(t) and t0>-1 :
  t0=t.find('<',t0)
  t1=t.find('>',t0)
  ouvrante=0
  if t0>-1 and t1>-1:
   if t[t0+1] in balisetype:
    b=balisetype.index(t[t0+1])
    if t[t0+2]=='-': 
      b=balisetype.index(t[t0+1])+1
    balise=BALISES[b]
    #print STACK
    if b==2 and t[t0:t1].find(STACK[-1])>-1:
        parent=STACK.pop(-1)
   elif t[t1-1] in balisetype:
    balise=BALISES[balisetype.index(t[t1-1])+1]
   else:
    t2=t.find(' ',t0) 
    if t2>t1: t2=t1
    ouvrante=1
    NOM=t[t0+1:t2]
    if t.find('</'+NOM)>-1:
       balise=BALISES[-1]
    else:
       balise=BALISES[-2]
   if balise=='E' or balise=='O':
    if NOM not in TAGS :
     if NOM not in ['a','b','table','tr','td','div','hr']:
      TAGS.append(NOM)
     else :
      t0=t.find('</'+NOM,t0)
      t1=t.find('>',t0)
      if t0==-1 and t1==-1:
           break
    if  balise=='O' and NOM in TAGS: 

     STACK.append(NOM)

     if not PLACEMARK :
      if NOM.find('Style')==0:
       proprietes=collecte_ATTRIBUTS(t[t0:t1+ouvrante])
       #print proprietes
      if NOM.find('PolyStyle')==0: 
        GETMAT=1

      if NOM.find('color')==0 and GETMAT:
        COLOR=t[t2+1:t.find('</color',t2)]
        #print COLOR
        COLOR=[eval('0x'+COLOR[0:2]), eval('0x'+COLOR[2:4]), eval('0x'+COLOR[4:6]), eval('0x'+COLOR[6:])]
        #print COLOR 
        if 'id' in proprietes.keys() and proprietes['id'] not in MATERIALS:
         MAT=Blender.Material.New(proprietes['id'])
         MAT.rgbCol = [COLOR[3]/255.0,COLOR[2]/255.0,COLOR[1]/255.0] 
         MAT.setAlpha(COLOR[0]/255.0)
         MATERIALS.append(MAT.getName())
        GETMAT=0

     if NOM.find('Polygon')>-1:
      VAL=t[t2+2:t.find('</Polygon',t2)]
      n=VAL.count('<outerBoundaryIs>')+VAL.count('<innerBoundaryIs>')

     if NOM.find('LineString')>-1:
      VAL=t[t2+2:t.find('</LineString',t2)]
      #n=VAL.count('<outerBoundaryIs>')+VAL.count('<innerBoundaryIs>')
      #print STACK

     if NUMBER and NOM.find('Placemark')>-1 :
      PLACEMARK=1
      if t[t2:t.find('</Placemark',t2)].find('Polygon')>-1 and len(ME.verts)>0:
       active_FORME()
       OB.select(0) 
       #[O.select(0) for O in Blender.Object.Get()]
       OB = Blender.Object.New('Mesh')  # link mesh to an object
       SC = Blender.Scene.GetCurrent()          # link object to current scene
       SC.link(OB)
       ME=OB.getData(mesh=1)
       OB.select(1) 
     if NOM.find('styleUrl')>-1:
       material= t[t2+2:t.find('</styleUrl',t2)]
       if material in MATERIALS :
        ME.materials=[Blender.Material.Get(material)]
       else :
        SMat=t.find('<Style id="'+material)
        if SMat>-1 :
         SMatF=t.find('</Style',SMat)
         SPolSt=t[SMat:SMatF].find('<PolyStyle>')
         if t[SMat:SMatF].find('<color>',SPolSt)>-1:
          COLOR=t[SMat:SMatF][t[SMat:SMatF].find('<color>',SPolSt)+7:t[SMat:SMatF].find('</color>',SPolSt)]
          if len(COLOR)>0 : COLOR=[eval('0x'+COLOR[0:2]), eval('0x'+COLOR[2:4]), eval('0x'+COLOR[4:6]), eval('0x'+COLOR[6:])]
         else :
          #print material,'\n\n'
          COLOR=[255,255,255,255]
         MAT=Blender.Material.New(material)
         MAT.rgbCol = [COLOR[3]/255.0,COLOR[2]/255.0,COLOR[1]/255.0] 
         MAT.setAlpha(COLOR[0]/255.0)
         MATERIALS.append(MAT.getName())
         ME.materials=[Blender.Material.Get(material)]
     if NOM.find('coordinates')>-1:
      VAL=t[t2+2:t.find('</coordinates',t2)]
      if STACK[-2]=='DocumentOrigin' :
       DOCUMENTORIGINE=[float(V) for V in  VAL.replace(' ','').replace('\n','').split(',')]
      if STACK[-2]=='LinearRing'  :
       n-=1
       TESSEL.append([])
       VAL=wash_DATA(VAL) 
       vv=[[float(VAL[a+ii]) for ii in xrange(3)] for a in xrange(0,len(VAL),3)]
       if vv  : [cree_FORME(v,TESSEL[-1]) for v in vv]
       del VAL
       if n==0: ME,TESSEL= cree_POLYGON(ME,TESSEL)
      if STACK[-2]=='LineString'  :
       #print STACK, STACK[-2] 
       BROKEN_LINE.append([])
       VAL=wash_DATA(VAL) 
       vv=[[float(VAL[a+ii]) for ii in xrange(3)] for a in xrange(0,len(VAL),3)]
       if vv  : [cree_FORME(v,BROKEN_LINE[-1]) for v in vv]
       del VAL
    D=[] 
  else:
     break
  t1+=1
  t0=t1 
 print 'BROKEN_LINE', BROKEN_LINE 
 if BROKEN_LINE :
  create_LINE(BROKEN_LINE,tv)

def scan_FILE(nom):
  global NUMBER, PLACEMARK, SC, OB, ME, POLYGON_NUMBER

  dir,name=split(nom)
  name=name.split('.')
  result=0
  t=filtreFICHIER(nom)
  tag1 = Blender.Draw.Create(0)
  tag2 = Blender.Draw.Create(0)
  block = []
  block.append("Import from 2D source")
  block.append(("Force 2D import", tag1, "if no polygon found in the file"))
  block.append(("Remove double ", tag2, " "))
  POLYGON_NUMBER=t.count('<Polygon')
  print 'Number of Polygons :  ', POLYGON_NUMBER
  if POLYGON_NUMBER==0 :
   retval = Blender.Draw.PupBlock("KML/KMZ import", block)
   if not tag1.val :
    name = "WARNING %t| Sorry, the script can\'t find any geometry in this file ."  # if no %xN int is set, indices start from 1
    result = Blender.Draw.PupMenu(name)
    print '#----------------------------------------------'
    print '#  Sorry the script can\'t find any geometry in this' 
    print '#  file .'
    print '#----------------------------------------------'
    Blender.Window.RedrawAll()
    return
   else :
    SC = Blender.Scene.GetCurrent()
    PLACEMARK_NUMBER=t.count('<Placemark>')
    print 'Number of Placemark   :  ', PLACEMARK_NUMBER
    if PLACEMARK_NUMBER!=POLYGON_NUMBER :
     NUMBER=1
     PLACEMARK=0
    if t!='false':
     contruit_HIERARCHIE(t,tag2.val)
     #active_FORME()
  else:
   SC = Blender.Scene.GetCurrent()
   PLACEMARK_NUMBER=t.count('<Placemark>')
   print 'Number of Placemark   :  ', PLACEMARK_NUMBER
   if PLACEMARK_NUMBER!=POLYGON_NUMBER :
    NUMBER=1
    PLACEMARK=0
   if t!='false':
    contruit_HIERARCHIE(t)
    active_FORME()
  gt2=Blender.sys.time()-gt1
  print int(gt2/60),':',int(gt2%60) 

Blender.Window.FileSelector (fonctionSELECT, 'SELECT a .KMZ FILE')

  To create meshes with NMesh module . 

Use faked fill() function but only on polygons larger than 4 vertices . Really faster (amazing) on big files with only tris like the lady_liberty.kmz
  • __version__ = "0.0.5, 13 May 2006" 

  • Recover of the lost face .
  • __version__ = "0.0.9, 14 May 2006" 

  • Modified reading of the coordinates tet .
    The tris and quads polys are created normaly not by the fill() 
  • __version__ = "0.1.1, 16 May 2006

  • Import of   polygones with inner hole . 
  • __version__ = "0.1.2, 17 May 2006

  • Download the autonomous script  0.1.2 + build in zipfile.py 
    Bug of lost faces (it happens when the last read faces were tris or quads) and speed improvment (aroud 300% faster on file with only tris or quads) .
  • __version__ = "0.1.3, 20 May 2006

  • Download the 0.1.3 script 
    Use placemark division, crumble up import amazingly improves  the speed  (5 or 10 times, depend on the  number of pieces) 
  • __version__ = "0.1.4, 25 May 2006

  • Download the 0.1.4 script 
    management of the file where there is the same number of placemarks and polygons . 
#!BPY

""" Registration info for Blender menus: <- these words are ignored
Name: 'KMZ/KML import''
Blender: 241
Group: 'Import'
Tip: 'Import geometry of short google earth 3D models'
"""
____version__ = "0.1.4, 25 May 2006"
__bpydoc__ = """\
       To open .kmz file this script needs zipfile.py from the complete python 
"""
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2006: jm soler, jmsoler_at_free.fr
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# --------------------------------------------------------------------------

import Blender
from Blender  import Window
import sys
from Blender import Mathutils
BLversion=Blender.Get('version')
SHIFT=Blender.Window.Qual.LSHIFT

try:
    import nt
    os=nt
    os.sep='\\'

except: 
    import posix
    os=posix
    os.sep='/'

def isdir(path):
    try:
        st = os.stat(path)
        return 1 
    except:
        return 0

def split(pathname):
         if pathname.find(os.sep)!=-1:
             k0=pathname.split(os.sep)
         else:
            if os.sep=='/':
                k0=pathname.split('\\')
            else:
                k0=pathname.split('/') 

         directory=pathname.replace(k0[len(k0)-1],'')
         Name=k0[len(k0)-1]
         return directory, Name

def join(l0,l1): 
     return  l0+os.sep+l1

os.isdir=isdir
os.split=split
os.join=join

def fonctionSELECT(nom):
    scan_FILE(nom)

def filtreFICHIER(nom):
     """
     Function  filtreFICHIER
     in  : string  nom , filename
     out : string  t   , if correct filecontaint 
     """
     if nom.upper().find('.KMZ')!=-1:
             from zipfile import ZipFile, ZIP_DEFLATED
             tz=ZipFile(nom,'r',ZIP_DEFLATED)
             t = tz.read(tz.namelist()[0])
             tz.close()
             return t
     elif nom.upper().find('.KML')!=-1:
             tz=open(nom,'r')
             t = tz.read()
             tz.close()
             return t
     else : 
        return None

OB = Blender.Object.New('Mesh')  # link mesh to an object
SC = Blender.Scene.GetCurrent()          # link object to current scene
SC.link(OB)
ME=OB.getData()
OB.select(1) 

DOCUMENTORIGINE=[]
NUMBER=0

eps=0.0000001
npoly=0

def cree_POLYGON(ME,TESSEL):
   global  OB, npoly
   npoly+=1 
   for T in TESSEL:
     del T[-1]
   if npoly%150==1 : 
      print 'Pgon: ', npoly, 'vert:',[len(T) for T in TESSEL]

   if len(TESSEL) == 1 and  len(TESSEL[0]) in [3,4] :
       NF=Blender.NMesh.Face() 
       while len(TESSEL[0])>0 :
           ME.verts.append(TESSEL[0].pop(-1))
           NF.append(ME.verts[-1])
       ME.faces.append(NF)
   else :
      VL=[]
      for T in TESSEL:
         ME.update()
         orig=len(ME.verts)
         ME.verts.append(T.pop(0))
         ME.verts[-1].sel=1
         VL.append(len(ME.verts)-1)
         while len(T)>0 :
             ME.verts.append(T.pop(-1))
             VL.append(len(ME.verts)-1)
            ME.verts[-1].sel=1
             ME.addEdge(ME.verts[-2],ME.verts[-1])
         ME.addEdge(ME.verts[-1],ME.verts[orig])
         ME.update()
      Blender.Window.EditMode(1)
      winid = Blender.Window.GetScreenInfo(Blender.Window.Types.VIEW3D)[0]['id']
      Blender.Window.SetKeyQualifiers(Blender.Window.Qual.SHIFT)
      Blender.Window.QAdd(winid, Blender.Draw.FKEY,1)
      Blender.Window.QHandle(winid) 
      Blender.Window.SetKeyQualifiers(0)
      Blender.Window.QHandle(winid) 
      Blender.Window.EditMode(0)

      ME=OB.getData()
      for v in VL :
         ME.verts[v].sel=0
      ME.update()
   TESSEL=[] 
   return ME,TESSEL

def cree_FORME(v,TESSEL):
       VE=Blender.NMesh.Vert(
           (v[0]-DOCUMENTORIGINE[0])* 85331.2,
           (v[1]-DOCUMENTORIGINE[1])* 110976.0,
           (v[2]-DOCUMENTORIGINE[2])  )
       TESSEL.append(VE)

def active_FORME():
    global ME
    ME.update()

def wash_DATA(ndata):
   if ndata!='':
       ndata=ndata.replace('\n',',')
       ndata=ndata.replace('\r','') 
       while ndata[-1]=='  ': 
         ndata=ndata.replace('  ',' ')
       while ndata[0]==' ': 
         ndata=ndata[1:]
       while ndata[-1]==' ': 
         ndata=ndata[:-1] 
       if ndata[0]==',':ndata=ndata[1:]
       if ndata[-1]==',':ndata=ndata[:-1]
       ndata=ndata.replace(',,',',') 
       ndata=ndata.replace(' ',',')
       ndata=ndata.split(',')
       for n in ndata :
          if n=='' : ndata.remove(n) 
   return  ndata 

def collecte_ATTRIBUTS(data):
    data=data.replace('  ',' ')
    ELEM={'TYPE':data[1:data.find(' ')]}
    t1=len(data)
    t2=0
    ct=data.count('="')
    while ct>0:
        t0=data.find('="',t2)
        t2=data.find(' ',t2)+1
        id=data[t2:t0]
        t2=data.find('"',t0+2)
        if id!='d':
           exec "ELEM[id]=\"\"\"%s\"\"\""%(data[t0+2:t2].replace('\\','/'))
        else:
              exec "ELEM[id]=[%s,%s]"%(t0+2,t2) 
        ct=data.count('="',t2)
    return ELEM

def contruit_HIERARCHIE(t):
    global DOCUMENTORIGINE, OB , ME, SC
    global NUMBER

    vv=[]
    TESSEL=[]

    t=t.replace('\t',' ')
    while t.find('  ')!=-1:
          t=t.replace('  ',' ')
    n0=0 
    t0=t1=0
    baliste=[]
    balisetype=['?','?','/','/','!','!']
    BALISES=['D',  #DECL_TEXTE',
             'D',  #DECL_TEXTE',
             'F',  #FERMANTE',
             'E',  #ELEM_VIDE',
             'd',  #DOC',
             'R',  #REMARQUES',
             'C',  #CONTENU',
             'O'   #OUVRANTE'
             ]

    TAGS = ['kml','Document','description','DocumentSource',
        'DocumentOrigin','visibility','LookAt',
       'Folder','name','heading','tilt','latitude',
       'longitude','range','Style','LineStyle','color',
       'Placemark','styleUrl','GeometryCollection',
       'Polygon','LinearRing','outerBoundaryIs',
       'altitudeMode','coordinates','LineString',
        'fill','PolyStyle','outline','innerBoundaryIs',
        'IconStyle', 'Icon', 'x','y' ,'w','href','h'
        ]

    STACK=[]
    latitude = float(t[t.find('<latitude>')+len('<latitude>'):t.find('</latitude>')])
    longitude = float(t[t.find('<longitude>')+len('<longitude>'):t.find('</longitude>')])
    DOCUMENTORIGINE=[longitude,latitude,0 ]

    while t1<len(t) and t0>-1:
      t0=t.find('<',t0)
      t1=t.find('>',t0)
      ouvrante=0
      if t0>-1 and t1>-1:
          if t[t0+1] in balisetype:
             b=balisetype.index(t[t0+1])
             if t[t0+2]=='-': 
               b=balisetype.index(t[t0+1])+1
             balise=BALISES[b]
             if b==2 and t[t0:t1].find(STACK[-1])>-1:
                 parent=STACK.pop(-1)
          elif t[t1-1] in balisetype:
            balise=BALISES[balisetype.index(t[t1-1])+1]
          else:
            t2=t.find(' ',t0) 
            if t2>t1: t2=t1
            ouvrante=1
            NOM=t[t0+1:t2]
            if t.find('</'+NOM)>-1:
               balise=BALISES[-1]
            else:
               balise=BALISES[-2]
          if balise=='E' or balise=='O':
             if NOM not in TAGS and NOM!='a':
               TAGS.append(NOM)
             if  balise=='O' and NOM in TAGS: 
                 STACK.append(NOM)
                 if NOM.find('Polygon')>-1:
                    VAL=t[t2+2:t.find('</Polygon',t2)]
                    n=VAL.count('<outerBoundaryIs>')+VAL.count('<innerBoundaryIs>')

                 if  NUMBER and NOM.find('Placemark')>-1  :
                    if t[t2:t.find('</Placemark',t2)].find('Polygon')>-1:
                       active_FORME()
                       [O.select(0) for O in Blender.Object.Get()]
                       OB = Blender.Object.New('Mesh') 
                       print "New object : ",OB.name
                       SC = Blender.Scene.GetCurrent() 
                       SC.link(OB)
                       ME=OB.getData()
                       OB.select(1) 
                       Blender.Window.RedrawAll()

                 if NOM.find('coordinates')>-1:
                    VAL=t[t2+2:t.find('</coordinates',t2)]
                    if STACK[-2]=='DocumentOrigin' :
                       DOCUMENTORIGINE=[float(V) for V in  VAL.replace(' ','').replace('\n','').split(',')]
                    if STACK[-2]=='LinearRing'  :
                       n-=1
                       TESSEL.append([])
                       VAL=wash_DATA(VAL) 
                       vv=[[float(VAL[a+ii]) for ii in xrange(3)] for a in xrange(0,len(VAL),3)]
                       if vv!=[] : [cree_FORME(v,TESSEL[-1]) for v in vv]
                       del VAL
                       if n==0: ME,TESSEL=cree_POLYGON(ME,TESSEL)
             elif balise=='O' : 
                 STACK.append(None)
             D=[] 
      else:
         break
      t1+=1
      t0=t1 

def scan_FILE(nom):
  global NUMBER
  gt1=Blender.sys.time()
  dir,name=split(nom)
  name=name.split('.')
  result=0
  t=filtreFICHIER(nom)
  POLYGON_NUMBER=t.count('<Polygon')
  print 'Number of Polygons :  ', POLYGON_NUMBER,'\n\n'
  PLACEMARK_NUMBER=t.count('<Placemark')
  print 'Number of Placemark :  ', PLACEMARK_NUMBER,'\n\n'
  if PLACEMARK_NUMBER!=POLYGON_NUMBER:
      NUMBER=1
  [O.select(0) for O in Blender.Object.Get()]
  if t!='false':
     contruit_HIERARCHIE(t)
     active_FORME()
  print Blender.sys.time()-gt1

Blender.Window.FileSelector (fonctionSELECT, 'SELECT a .KMZ FILE')


External links
précédentScript Python
Spot and lampNext
Vers le  Haut de page

Les questions concernant cette page  peuvent être posées sur  :
 news://news.zoo-logique.org/3D.Blender

Livre en français
Blender : apprenez, pratiquez, Créez, livre, Ed. Campus Press, coll. Starter Kit
Blender Starter Kit

Forum
FAQ
Lexique
Didacticiels
Compilations
Blender2KT
Débuter
Modelage
Blender python
Materiaux
Lumière
Animation
API python (eng)
Archives nzn
Statistiques
Doc flash Sculptris
Galerie Sculptris

mon site de démos sur youtube