'''---------------------------------------------------------------------------------- Tool Name: ArcGIS2EpanetMNT Version: ArcGIS 9.3 Author: Fabio Oliosi & Christophe Schwaar (SCAV VD) Date: 23.11.2009 Required Args: - An input Workspace - An input Conduite feature class - An output text file - An input MNT file - A diameter Field - A length Field - An roughness Field Description: Writes two new features classes (Node and Conduite_FromTo) Writes an Epanet text file. ----------------------------------------------------------------------------------''' #§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ # ARGUMENT ET DEFINITION DES VARIABLES #§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ import string, os, sys, locale, arcgisscripting gp = arcgisscripting.create() gp.overwriteoutput = 1 msgNotEnoughParams = "Incorrect number of input parameters." outFile = 0 try: if len(sys.argv) < 5: raise Exception, msgNotEnoughParams inFC = sys.argv[1] FCLocation = os.path.split(inFC)[0] inputFCCond = os.path.split(inFC)[1] outputEpanetFile = sys.argv[2] MNT_File = sys.argv[3] DiametreFieldName = sys.argv [4] LongueurFieldName = sys.argv [5] RugositeFieldName = sys.argv [6] # Recommandé de choisir Shape_length comme attribut pour la longueur de façon à éviter valeurs nulles outputFCCondFT = "Conduite_FromTo" outputFCNodeH = "NoeudHeight" # gp.workspace = FCLocation # if gp.Exists(outputFCCondFT): gp.delete_management(outputFCCondFT) if gp.Exists(outputFCNodeH): gp.delete_management(outputFCNodeH) Conduite_Temp = inputFCCond + "_Temp" Node_Temp = "Node_Temp" #§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ # CONDUITES : Ajout des champs FROM_PT et TO_PT aux conduites avec calcul de leur coordonnées #§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ # Créer la copie de travail de la FC des Conduites gp.Copy_management(inputFCCond, Conduite_Temp, "FeatureClass") # Ajouter et calculer le champ FROM_PT... gp.AddField_management(Conduite_Temp, "FROM_PT", "TEXT", "", "", "", "", "NULLABLE", "NON_REQUIRED", "") gp.CalculateField_management(Conduite_Temp, "FROM_PT", "!SHAPE.FIRSTPOINT!", "PYTHON", "") # Ajouter et calculer le champ TO_PT... gp.AddField_management(Conduite_Temp, "TO_PT", "TEXT", "", "", "", "", "NULLABLE", "NON_REQUIRED", "") gp.CalculateField_management(Conduite_Temp, "TO_PT", "!SHAPE.LASTPOINT!", "PYTHON", "") #§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ # CONDUITES : Ajout des champs NOEUD_I et NOEUD_J aux conduites #§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ # Ajoute le champ NOEUD_I et NOEUD_J gp.AddField_management(Conduite_Temp, "NOEUD_I", "DOUBLE", "", "", "", "", "NULLABLE", "NON_REQUIRED", "") gp.AddField_management(Conduite_Temp, "NOEUD_J", "DOUBLE", "", "", "", "", "NULLABLE", "NON_REQUIRED", "") #§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ # NOEUDS #§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ # Génération de la liste des noeuds: une liste des coordonnées FROM_PT et TO_PT de toutes les conduites est générée (chaîne de caractères) # Cela crée une liste de string "x y" mylist = [] inRows = gp.searchcursor(Conduite_Temp) inRow = inRows.next() while inRow: mypoint = inRow.GetValue("FROM_PT") mylist.append(mypoint) mypoint = inRow.GetValue("TO_PT") mylist.append(mypoint) inRow = inRows.next() #------------------------------------------------------- # Nettoyage de la liste des noeuds: la liste est ordonnée puis les doublons sont supprimés (point départ d'une conduite = point fin d'une autre) mylist.sort() count_to_last_one = len(mylist) stringedpoint = "999999999999999" i = 0 while count_to_last_one: if stringedpoint == mylist[i]: del mylist[i] else : stringedpoint = mylist[i] i = i + 1 count_to_last_one = len(mylist)-i # #------------------------------------------------------- # Création de la FC (feature class) des noeuds gp.CreateFeatureclass_management(FCLocation, Node_Temp, "point", "#", "", "", "#") gp.AddField_management(Node_Temp,"POINT_XY","TEXT") gp.AddField_management(Node_Temp,"ID_NUM","LONG") # outDesc = gp.describe(Node_Temp) shapefield = outDesc.ShapeFieldName # #------------------------------------------------------- # Remplissage de la FC des noeuds avec attribution des champs "système" x et y # Create insert cursor curline = gp.InsertCursor(Node_Temp) pnt = gp.createobject("point") # parse the points FC id = 0 for mypoint in mylist: id = id + 1 xy = mypoint.split(" ") pnt.id = id pnt.x = float(xy[0]) pnt.y = float(xy[1]) rowline = curline.newrow() rowline.SetValue("POINT_XY", mypoint) rowline.SetValue("ID_NUM", pnt.id) rowline.SetValue(shapefield, pnt) curline.insertrow(rowline) del mylist del curline del pnt # # #§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ # ATTRIBUTION DES ID NOEUDS DE DEBUT ET FIN AUX CONDUITES PAR JOINTURE SUR LES COORDONNEES # (NOEUDS ET FROM_PT TO_PT) #§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ # Création de la Layers temporaires pour les jointures TempFC1 = FCLocation + "\\Temp1" TempFC2 = FCLocation + "\\Temp2" TempFC3 = FCLocation + "\\Temp3" CondFC_Layer1 = "CondFC_Layer1" CondFC_Layer2 = "CondFC_Layer2" JoinFieldName_OBJECTID = "[" + Node_Temp + "_OBJECTID]" # #------------------------------------------------------- # Création et exploitation des jointures # pour le champ FROM_PT... gp.MakeFeatureLayer_management(Conduite_Temp, CondFC_Layer1, "", "", "") gp.AddJoin_management(CondFC_Layer1, "FROM_PT", Node_Temp, "POINT_XY", "KEEP_ALL") gp.CopyFeatures_management(CondFC_Layer1, TempFC1, "", "0", "0", "0") gp.copy_management(TempFC1, TempFC2) gp.RemoveJoin_management(CondFC_Layer1, Node_Temp) gp.delete_management(TempFC1) # Process: Calculate Field... gp.CalculateField_management(TempFC2, "NOEUD_I", "[Node_Temp_OBJECTID]", "VB", "") # Process: Delete Fields... gp.DeleteField_management(TempFC2, "Node_Temp_POINT_XY") gp.DeleteField_management(TempFC2, "Node_Temp_OBJECTID") gp.DeleteField_management(TempFC2, "ID_NUM_1") #---------------------------- # pour le champ TO_PT... gp.MakeFeatureLayer_management(TempFC2, CondFC_Layer2, "", "", "") gp.AddJoin_management(CondFC_Layer2, "TO_PT", Node_Temp, "POINT_XY", "KEEP_ALL") gp.CopyFeatures_management(CondFC_Layer2, TempFC1, "", "0", "0", "0") gp.copy_management(TempFC1, TempFC3) gp.RemoveJoin_management(CondFC_Layer2, Node_Temp) gp.delete_management(TempFC1) # Process: Calculate Field... gp.CalculateField_management(TempFC3, "NOEUD_J", "[Node_Temp_OBJECTID]", "VB", "") # Process: Delete Fields... gp.DeleteField_management(TempFC3, "Node_Temp_POINT_XY") gp.DeleteField_management(TempFC3, "Node_Temp_OBJECTID") gp.DeleteField_management(TempFC3, "ID_NUM_1") gp.DeleteField_management(TempFC3, "FROM_PT") gp.DeleteField_management(TempFC3, "TO_PT") #------------------------------------------------------- # Nettoyage des layers temporaires gp.copy_management(TempFC3, outputFCCondFT) gp.delete_management(TempFC2) gp.delete_management(TempFC3) gp.DeleteField_management(Node_Temp, "POINT_XY") gp.delete_management(Conduite_Temp) #§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ # ATTRIBUTION DES ALTITUDES AUX NEOUDS SUR BASE MNT (nécessite extension Spatial analyst) #§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ # Extraction des altitudes des noeuds # Check out any necessary licenses gp.CheckOutExtension("spatial") # Load required toolboxes... gp.AddToolbox("C:/ArcGIS/ArcToolbox/Toolboxes/Spatial Analyst Tools.tbx") # Process: Extract Values to Points... gp.ExtractValuesToPoints_sa(Node_Temp, MNT_File, outputFCNodeH, "NONE", "VALUE_ONLY") gp.delete_management(Node_Temp) #§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ # ECRITURE DU FICHIER TEXTE POUR EPANET #§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ except Exception, ErrorDesc: gp.AddError(ErrorDesc[0]) if outFile: outFile.close() gp.AddError(gp.getmessages(2)) #------------------------------------------------------- # Génération du fichier pour Epanet sepchar = " " Title0 = "[TITLE]" Title1 = "[JUNCTIONS]" Head01 = ";ID" + sepchar + "Elevation" + sepchar + "BaseDemand" + sepchar + "DemandPattern" + sepchar + ";Description" Title2 = "[PIPEs]" Head02 = ";ID" + sepchar + "Node1" + sepchar + "Node2" + sepchar + "Length" + sepchar + "Diamter" + sepchar + "Roughness" + sepchar + "LossCoefficient" + sepchar + "InitialStatus" + sepchar + ";Description" Title3 = "[COORDINATES]" Head03 = ";Node" + sepchar + "X-Coord" + sepchar + "Y_Coord" Title4 = "[VERTICES]" Head04 = ";Link" + sepchar + "X_Coord" + sepchar + "Y_Coord" outFile = 0 try: outFile = open(outputEpanetFile, "w") # Junction section inDesc = gp.describe(outputFCNodeH) inRows = gp.searchcursor(outputFCNodeH) inRow = inRows.next() outFile.write(Title0 + "\n\n") outFile.write(Title1 + "\n") outFile.write(Head01 + "\n") while inRow: feat = inRow.GetValue(inDesc.ShapeFieldName) if inDesc.ShapeType.lower() == "point": pnt = feat.getpart() ID = str(inRow.GetValue(inDesc.OIDFieldName)) Elevation = "0" Elevation = str(inRow.GetValue("RASTERVALU")) outLine = ID + sepchar + Elevation + ";\n" outFile.write(outLine) inRow = inRows.next() outFile.write("\n") inRow = inRows.reset() # PIPEs section inDesc = gp.describe(outputFCCondFT) inRows = gp.searchcursor(outputFCCondFT) inRow = inRows.next() outFile.write(Title2 + "\n") outFile.write(Head02 + "\n") ID = "" Node1 = "0" Node2 = "0" Length = "" Diameter = "100" Roughness = "0" LossCoefficient = "" InitialStatus = "" while inRow: feat = inRow.GetValue(inDesc.ShapeFieldName) if inDesc.ShapeType.lower() == "polyline": partnum = 0 partcount = feat.partcount while partnum < partcount: ID = str(inRow.GetValue(inDesc.OIDFieldName)) # ID = str(inRow.GetValue("ID_Num")) # Champs diametre et longueur sont définis comme arguments Length = str(inRow.GetValue(LongueurFieldName)) Diameter = str(inRow.GetValue(DiametreFieldName)) Node1 = str(int(inRow.GetValue("NOEUD_I"))) Node2 = str(int(inRow.GetValue("NOEUD_J"))) Roughness = str(inRow.GetValue(RugositeFieldName)) # Si diamètre nul attribution valeur de 100 mm if Diameter == "" or Diameter == "None": Diameter = "100" # Si rugosité vide attribution valeur de 0 pour forcer la réfléxion lors de la simulation if Roughness == "" or Roughness == "None": Roughness = "0" outLine = ID + sepchar + Node1 + sepchar + Node2 + sepchar + Length + sepchar + Diameter + sepchar + Roughness + ";\n" outFile.write(outLine) partnum += 1 inRow = inRows.next() outFile.write("\n") inRow = inRows.reset() # Coordinate section inDesc = gp.describe(outputFCNodeH) inRows = gp.searchcursor(outputFCNodeH) inRow = inRows.next() outFile.write(Title3 + "\n") outFile.write(Head03 + "\n") while inRow: feat = inRow.GetValue(inDesc.ShapeFieldName) if inDesc.ShapeType.lower() == "point": pnt = feat.getpart() outLine = str(inRow.GetValue(inDesc.OIDFieldName)) + sepchar + str(pnt.x) + sepchar + str(pnt.y) + ";\n" outFile.write(outLine) inRow = inRows.next() outFile.write("\n") inRow = inRows.reset() # Vertices section inDesc = gp.describe(outputFCCondFT) inRows = gp.searchcursor(outputFCCondFT) inRow = inRows.next() outFile.write(Title4 + "\n") outFile.write(Head04 + "\n") while inRow: feat = inRow.GetValue(inDesc.ShapeFieldName) if inDesc.ShapeType.lower() == "polyline": partnum = 0 partcount = feat.partcount while partnum < partcount: ID_Cond = str(inRow.GetValue(inDesc.OIDFieldName)) part = feat.getpart(partnum) part.reset() pnt = part.next() pnt_count = 0 while pnt: outLine = ID_Cond + sepchar + str(pnt.x) + sepchar + str(pnt.y) + "\n" outFile.write(outLine) pnt = part.next() pnt_count += 1 partnum += 1 inRow = inRows.next() outFile.write("\n") inRow = inRows.reset() # Final section outFile.write("[END]") outFile.flush() outFile.close() except Exception, ErrorDesc: gp.AddError(ErrorDesc[0]) if outFile: outFile.close() gp.AddError(gp.getmessages(2))