__author__ = "prantoShohan"
__version__ = "2024.05.19"
import rhinoscriptsyntax as rs
import ghpythonlib.treehelpers as TH
import Grasshopper as gh
import Rhino.Geometry as R
import random as rand
import math
DistGraph = TH.tree_to_list(DISTANCES_GRAPH, retrieve_base=lambda y: y)
NbrhdGraph = TH.tree_to_list(NEIGHBOURHOOD_GRAPH, retrieve_base=lambda y: y)
DG = DistGraph
if "NG" not in globals() or RESET:
NG = []
for n in range(len(NbrhdGraph)):
N = []
for m in range(len(NbrhdGraph[n])):
N.append(int(NbrhdGraph[n][m][1:]))
NG.append(N)
MetroId = 302
InfluenceFactor = {
#Demand per unit residential
"Residential_Residential" : 1/150,
"Residential_Educational" : 1/1500,
"Residential_Healthcare" : 1/400,
"Residential_SocioCultural" : 1/400,
#Demand for commercial from different landuses
"Residential_Commercial" : 1/50,
"Commercial_Commercial" : -1,
"Educational_Commercial" : 5,
"Healthcare_Commercial" : 3,
"SocioCultural_Commercial" : 2,
#Self distance
"Educational_Educational" : -1.5,
"Healthcare_Healthcare" : -1.5,
"SocioCultural_SocioCultural" : -1,
#With metro
"Metro_Residential" : 3,
"Metro_Commercial" : 5,
"Metro_Educational" : .5
}
DistanceFactor = {
#(B, d) d average walking distance(m)
"Residential_Residential" : (1.71, 756),
"Residential_Educational" : (2.01, 289),
"Residential_Healthcare" : (1.71, 756),
"Residential_SocioCultural" : (1.93, 289),
"Residential_Commercial" : (2.14, 128),
"Commercial_Commercial" : (2.14, 128),
"Educational_Commercial" : (2.14, 128),
"Healthcare_Commercial" : (2.14, 128),
"SocioCultural_Commercial" : (2.14, 128),
"Educational_Educational" : (2.01, 289),
"Healthcare_Healthcare" : (1.71, 756),
"SocioCultural_SocioCultural" : (2.14, 128),
"Metro_Residential" : (1.71, 756),
"Metro_Commercial" : (3, 756),
"Metro_Educational" : (3, 128)
}
class Block:
def __init__(self, position, id):
self.position = position
self.id = int(id[1:])
self.neighbours = []
self.capacity = 20
self.maxCapacity = 30
self.demand = {
"Residential" : 0.0,
"Commercial" : 0.0,
"Healthcare" : 0.0,
"Educational" : 0.0,
"SocioCultural" : 0.0
}
self.distribution = {
"Residential" : 0.0,
"Commercial" : 0.0,
"Healthcare" : 0.0,
"Educational" : 0.0,
"SocioCultural" : 0.0,
"Metro" : 0.0
}
def addNeighbour(self, nbr, distance):
self.neighbours.append((nbr, distance))
def addNeighbours(self, nbrList, distanceList, blockList):
assert(len(nbrList) == len(distanceList))
for i in range(len(nbrList)):
self.addNeighbour(blockList[nbrList[i] - 1], distanceList[i])
def findNearest(self, type):
distance = 500
closestId = 301
for nbr in self.neighbours:
if(nbr[0].distribution[type] > 1):
if (nbr[1] < distance):
closestId = nbr[0].id
distance = nbr[1]
return((closestId, distance))
def findNearestAll(self):
print("Commercial: ", self.findNearest("Commercial")[1], " id: ", self.findNearest("Commercial")[0])
print("Educational: ", self.findNearest("Educational")[1], " id: ", self.findNearest("Educational")[0])
print("Healthcare: ", self.findNearest("Healthcare")[1], " id: ", self.findNearest("Healthcare")[0])
print("SocioCultural: ", self.findNearest("SocioCultural")[1], " id: ", self.findNearest("SocioCultural")[0])
def evaluateDemand(self):
#print("##########Evaluating id:", self.id)
for nbr in self.neighbours:
if(nbr[1] != None):
#print("Against id: ", nbr[0].id, " Distance: ", nbr[1])
self.demand["Residential"] += nbr[0].distribution["Residential"] * InfluenceFactor["Residential_Residential"] * self.calculateDistanceFactor(nbr[1], "Residential_Residential")
self.demand["Residential"] += nbr[0].distribution["Metro"] * InfluenceFactor["Metro_Residential"] * self.calculateDistanceFactor(nbr[1], "Metro_Residential")
self.demand["Residential"] = min(10, max(-10, self.demand["Residential"]))
self.demand["Commercial"] += nbr[0].distribution["Metro"] * InfluenceFactor["Metro_Commercial"] * self.calculateDistanceFactor(nbr[1], "Metro_Commercial")
self.demand["Commercial"] += nbr[0].distribution["Residential"] * InfluenceFactor["Residential_Commercial"] * self.calculateDistanceFactor(nbr[1], "Residential_Commercial")
self.demand["Commercial"] += nbr[0].distribution["Commercial"] * InfluenceFactor["Commercial_Commercial"] * self.calculateDistanceFactor(nbr[1], "Commercial_Commercial")
self.demand["Commercial"] += nbr[0].distribution["Educational"] * InfluenceFactor["Educational_Commercial"] * self.calculateDistanceFactor(nbr[1], "Educational_Commercial")
self.demand["Commercial"] += nbr[0].distribution["Healthcare"] * InfluenceFactor["Healthcare_Commercial"] * self.calculateDistanceFactor(nbr[1], "Healthcare_Commercial")
self.demand["Commercial"] = min(10, max(-10, self.demand["Commercial"]))
self.demand["Educational"] += nbr[0].distribution["Metro"] * InfluenceFactor["Metro_Educational"] * self.calculateDistanceFactor(nbr[1], "Metro_Educational")
self.demand["Educational"] += nbr[0].distribution["Residential"] * InfluenceFactor["Residential_Educational"] * self.calculateDistanceFactor(nbr[1], "Residential_Educational")
self.demand["Educational"] += nbr[0].distribution["Educational"] * InfluenceFactor["Educational_Educational"] * self.calculateDistanceFactor(nbr[1], "Educational_Educational")
self.demand["Educational"] = min(10, max(-10, self.demand["Educational"]))
self.demand["Healthcare"] += nbr[0].distribution["Residential"] * InfluenceFactor["Residential_Healthcare"] * self.calculateDistanceFactor(nbr[1], "Residential_Healthcare")
self.demand["Healthcare"] += nbr[0].distribution["Healthcare"] * InfluenceFactor["Healthcare_Healthcare"] * self.calculateDistanceFactor(nbr[1], "Healthcare_Healthcare")
self.demand["Healthcare"] = min(10, max(-10, self.demand["Healthcare"]))
self.demand["SocioCultural"] += nbr[0].distribution["Residential"] * InfluenceFactor["Residential_SocioCultural"] * self.calculateDistanceFactor(nbr[1], "Residential_SocioCultural")
self.demand["SocioCultural"] += nbr[0].distribution["SocioCultural"] * InfluenceFactor["SocioCultural_SocioCultural"] * self.calculateDistanceFactor(nbr[1], "SocioCultural_SocioCultural")
self.demand["SocioCultural"] = min(10, max(-10, self.demand["SocioCultural"]))
occupiedSpace = self.distribution["Residential"] + self.distribution["Commercial"] * .5 + 5 * self.distribution["Educational"] + 5 * self.distribution["Healthcare"] + 3*self.distribution["SocioCultural"]
demandMultiplier = 1
if (occupiedSpace > self.capacity):
x = occupiedSpace - self.capacity
demandMultiplier = -(x/self.capacity) + 1
# demandMultiplier = min(1, max(-2, demandMultiplier))
self.demand["Residential"] *= demandMultiplier
self.demand["Commercial"] *= demandMultiplier
self.demand["Educational"] *= demandMultiplier
self.demand["Healthcare"] *= demandMultiplier
self.demand["SocioCultural"] *= demandMultiplier
#
# self.demand["Residential"] = min(10, max(-10, self.demand["Residential"]))
# self.demand["Commercial"] = min(10, max(-10, self.demand["Commercial"]))
# self.demand["Educational"] = min(5, max(-5, self.demand["Educational"]))
def evaluateDemandWithMetro(self):
# print("##########Evaluating id:", self.id)
for nbr in self.neighbours:
if(nbr[1] != None):
# print("Against id: ", nbr[0].id, " Distance: ", nbr[1])
# print("Residential_Residential","distribution",nbr[0].distribution["Residential"], "influence_factor:", InfluenceFactor["Residential_Residential"], "distance Factor:", self.calculateDistanceFactor(nbr[1], "Residential_Residential"))
self.demand["Residential"] += nbr[0].distribution["Residential"] * InfluenceFactor["Residential_Residential"] * self.calculateDistanceFactor(nbr[1], "Residential_Residential")
self.demand["Residential"] += nbr[0].distribution["Metro"] * InfluenceFactor["Metro_Residential"] * self.calculateDistanceFactor(nbr[1], "Metro_Residential")
self.demand["Commercial"] += nbr[0].distribution["Metro"] * InfluenceFactor["Metro_Commercial"] * self.calculateDistanceFactor(nbr[1], "Metro_Commercial")
self.demand["Commercial"] += nbr[0].distribution["Residential"] * InfluenceFactor["Residential_Commercial"] * self.calculateDistanceFactor(nbr[1], "Residential_Commercial")
self.demand["Commercial"] += nbr[0].distribution["Commercial"] * InfluenceFactor["Commercial_Commercial"] * self.calculateDistanceFactor(nbr[1], "Commercial_Commercial")
self.demand["Commercial"] += nbr[0].distribution["Educational"] * InfluenceFactor["Educational_Commercial"] * self.calculateDistanceFactor(nbr[1], "Educational_Commercial")
self.demand["Educational"] += nbr[0].distribution["Metro"] * InfluenceFactor["Metro_Educational"] * self.calculateDistanceFactor(nbr[1], "Metro_Educational")
self.demand["Educational"] += nbr[0].distribution["Residential"] * InfluenceFactor["Residential_Educational"] * self.calculateDistanceFactor(nbr[1], "Residential_Educational")
self.demand["Educational"] += nbr[0].distribution["Educational"] * InfluenceFactor["Educational_Educational"] * self.calculateDistanceFactor(nbr[1], "Educational_Educational")
def grow(self):
self.distribution["Residential"] += int(self.demand["Residential"] * 1)
self.distribution["Commercial"] += int(self.demand["Commercial"] * 1)
self.distribution["Educational"] += int(self.demand["Educational"] * 1)
self.distribution["Healthcare"] += int(self.demand["Healthcare"] * 1)
self.distribution["SocioCultural"] += int(self.demand["SocioCultural"] * 1)
self.distribution["Residential"] = max(0, self.distribution["Residential"])
self.distribution["Commercial"] = max(0, self.distribution["Commercial"])
self.distribution["Educational"] = max(0, self.distribution["Educational"])
self.distribution["Healthcare"] = max(0, self.distribution["Healthcare"])
self.distribution["SocioCultural"] = max(0, self.distribution["SocioCultural"])
if (self.distribution["Educational"] >= 1):
self.distribution["Commercial"] = 0
self.distribution["Residential"] = 0
self.distribution["Healthcare"] = 0
self.distribution["SocioCultural"] = 0
if (self.distribution["Healthcare"] >= 1):
self.distribution["Commercial"] = 0
self.distribution["Residential"] = 0
self.distribution["Educational"] = 0
self.distribution["SocioCultural"] = 0
def calculateDistanceFactor(self, distance, relationship):
#Distance influences P(d) = e^(-Bd)
#https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3377942/
distanceInfluence = math.e ** ( - DistanceFactor[relationship][0] * distance/1609.34 ) # meter to miles
return distanceInfluence
def __str__(self):
s = " ID: "+str(self.id) + ", Neighbours: "
for n in self.neighbours:
s += " id: "+str(n[0].id) + "- distance: "+str(n[1])
return s
################## ID = index+1 #################
def initial_influence():
for b in range(len(Blocks)):
Blocks[b].evaluateDemandWithMetro()
def demand_loop():
for b in range(len(Blocks)):
Blocks[b].evaluateDemand()
def grow_loop():
for b in range(len(Blocks)):
Blocks[b].grow()
def main():
demand_loop()
grow_loop()
# Instantiate or reset persistent counter variable
if "c" not in globals() or RESET:
c = 0
if "Blocks" not in globals() or RESET:
Blocks = []
for n in range(len(BLOCKS)):
Blocks.append(Block(BLOCKS[n], BLOCKS_ID[n]))
for b in range(len(Blocks)):
Blocks[b].addNeighbours(NG[b], DG[b], Blocks)
Blocks[MetroId-1].distribution["Metro"] = 1
Blocks[246].distribution["Metro"] = 1
initial_influence()
# Update the variable and component
if (c < ITERATIONS):
c = c + 1
main()
COUNTER = c
Points = []
Ids = []
RD = []
CD = []
ED = []
HD = []
SD = []
RDist = []
CDist = []
EDist = []
HDist = []
SDist = []
for p in Blocks:
Points.append(p.position)
Ids.append(p.id)
RD.append(p.demand["Residential"])
CD.append(p.demand["Commercial"])
ED.append(p.demand["Educational"])
HD.append(p.demand["Healthcare"])
SD.append(p.demand["SocioCultural"])
RDist.append(p.distribution["Residential"])
CDist.append(p.distribution["Commercial"])
EDist.append(p.distribution["Educational"])
HDist.append(p.distribution["Healthcare"])
SDist.append(p.distribution["SocioCultural"])
points = Points
ids = Ids
RESIDENTIAL_DEMAND = RD
COMMERCIAL_DEMAND = CD
EDUCATIONAL_DEMAND = ED
HEALTHCARE_DEMAND = HD
SOCIOCULTURAL_DEMAND = SD
RESIDENTIAL_DISTRIBUTION = RDist
COMMERCIAL_DISTRIBUTION = CDist
EDUCATIONAL_DISTRIBUTION = EDist
HEALTHCARE_DISTRIBUTION = HDist
SOCIOCULTURAL_DISTRIBUTION = SDist
Blocks[287].findNearestAll()
#Blocks = []
#
#for b in range(len(BLOCKS)):
# Blocks.append(Block(BLOCKS[b], BLOCKS_ID[b]))
#
#def findBlock(blocks, id):
# for b in blocks:
# if b.id == id:
# return b
# else:
# print ("not found")
#
#for n in range(len(Blocks)):
# for m in range(len(NbrhdGraph[n])):
# Blocks[n].addNeighbour(findBlock(Blocks, int(NbrhdGraph[n][m][1:])), DistGraph[n][m])
#
#
#print(Blocks[1])