Serendipitous Map

JIANWEI LI
Data Mining the City
7 min readDec 11, 2017

Jianwei Li, Keli Wang, Xianyao Xia, Yanmin Bao

Maps can be really inductive with the limited information it provided. With the good purpose of simplifying people’s life, sometimes maps may skip some interesting details and fail to fulfill people’s diversified demands.

Do you realize that when you open the Google Map, your choices are actually are dictated by a series of options that you might not interested in, or you had been sick for.

Do you realize that when you go your regular jogging at the Dodge Fitness Center, you might miss a Vinyasa Yoga Class which is happening across the hallway?

We intend to create the Serendipitous Map for people to explore their potential interests along with their daily routines and in return offer a wide range of choices for them to make. We collect a series of events that taking place in each building in Columbia University and use that as a base to operate the BOTs.

The user can sketch freely on the map interface and our interface will return different event options based on the proximity of the user’s sketching location.By popping up the options randomly the user can have equal access to different resources and have a better understanding of the school events, some of which may not seem that obvious before.

The exploration can be realized by symbolizing the building with several blocks and people can freely draw their trails on the screen. When they enter one building, the corresponding block would be activated and the BOT would generate a question to help people locate themselves. If people pause a little bit one more question would be triggered to speculate people’s behavior and offer a list of things people can do in the building.

The major purpose of the Serendipitous Map is to make people aware of the invisible events in the surrounding environment and reassess the familiar space through an indiscriminate lens.

Methodology

  1. Create Database

We gather a list of Locations in the campus in a CSV file and import it into processing as a dictionary.

with open('dataofchineserestaurantswithtype.csv') as chinesept:
reader = csv.reader(chinesept)
header = reader.next()
dataDic={'id':[],
'name':[],
'lat':[],
'lon':[],
'rate':[],
'time':[],
'type':[],
'image':[]
}
for row in reader:
id = int(row[0])
lat = float(row[4])
lon = float(row[3])
name = row[1]
type = row[6]
data = {
'id': id,
'name': name,
'lat': lat,
'lon': lon,
'type':type
}
nyc.addMarker(lat, lon, RestaurantMarkerInvisible(data))
dataDic['id'].append(data['id'])
dataDic['name'].append(data['name'])
dataDic['lat'].append(data['lat'])
dataDic['lon'].append(data['lon'])
dataDic['type'].append(data['type'])
event = dataDic['passby'][3].split(",")

2. Function of BOT

Instead of only using BOTs to create the sentence for the subprocess Library, we add the draw function and the conditions within the BOTs. In the main python code, we correlate the building footprints and the messages from BOTs as an “invisibleBot”, which will shorten the calling time for the function.

class BOT(object):

def __init__(self, ind, name, x1, y1, x2, y2, passby):
self.ind = ind
self.name = name
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
self.passby = passby


def draw(self):
fill(0)
rect(self.x1, self.y1, self.x2 - self.x1, self.y2 - self.y1)

def generateSentence(self):
if mousePressed == True:
if self.x1 < mouseX and mouseX < self.x2 and self.y1 < mouseY and mouseY < self.y2:
sentence = "Are you going to " + str(self.name) + "?"
return sentence

def generatePassby(self):
if mousePressed == True:
if self.x1 < mouseX and mouseX < self.x2 and self.y1 < mouseY and mouseY < self.y2:
return self.passby

3. Interactive Sketch

User experience will be an important integration between the sketch and BOTs. The initial concept is to use basic draw function and we set a series of conditions to check user’s real-time location, start location, end location, sketching status and routine history.

dict={'x':[],'y':[]} # collecting the start point and end point
status = ["Runing"] # To check if the user is drawing a line or stop at a position
scan = [False]if mousePressed == True:
scan.append(True)
if scan[0]!=scan[-1]:

dict['x'].append(mouseX)
dict['y'].append(mouseY)

oX = dict['x'][0]
oY = dict['y'][0]

dX = dict['x'][-1]
dY = dict['y'][-1]

print oX,oY,dX,dY
if len(dict['x'])>1:
if dict['x'][-2] ==dict['x'][-1] and dict['y'][-2]==dict['y'][-1]:
status ="Here"

else:
status="Running"

# redraw the line to override the subprocess
i = 0
while i < len(dict['x'])-1:


line(dict['x'][i],dict['y'][i],dict['x'][i+1],dict['y'][i+1])
i+=1
line(dict['x'][-1],dict['y'][-1],dict['x'][-2],dict['y'][-2])
fill(61,87,100)
noStroke()
ellipse(dict['x'][-1],dict['y'][-1],4,4)
print status

Once the user is within the proximity of the selected buildings. Our embedded Bots will respond the sentence with the location. When the user’s sketching status is “Stop”, Bots will explode a series of special events happening inside of this building.

Code

from bot import *
import csv
import random
import subprocess
import time

def setup():
size(613, 770)
# background(100)
frameRate(20)
textAlign(CENTER,CENTER)

global img1, img2, img3, img4, img5, img6, img7, img8, img9, img10,imageList

img1 = loadImage("1.jpg")
img2 = loadImage("2.jpg")
img3 = loadImage("3.jpg")
img4 = loadImage("4.jpg")
img5 = loadImage("5.jpg")
img6 = loadImage("6.jpg")
img7 = loadImage("7.jpg")
img8 = loadImage("8.jpg")
img9 = loadImage("9.jpg")
img10 = loadImage("campusmap.jpg")
imageList = []
for i in range(9):
imageList.append("img"+str(i+1))
#print imageList

global check, dict, status, senData

check = ["None"] # To check if you are inside the selected location
# To check if the user is drawing a line or stop at a position
status = ["Runing"]
senData = [] # collecting the location you had been passed through.
dict = {'x': [], 'y': []} # collecting the start point and end point

with open('final_csv.csv') as file:
reader = csv.reader(file)
header = reader.next()

dataDic = {'index': [],
'name': [],
'x1': [],
'y1': [],
'x2': [],
'y2': [],
'passby': []
}

for row in reader:
index = int(row[0])
name = row[1]
x1 = int(row[2])
y1 = int(row[3])+30
x2 = int(row[4])
y2 = int(row[5])+30
passby = row[6]
data = {
'index': index,
'name': name,
'x1': x1,
'y1': y1,
'x2': x2,
'y2': y2,
'passby': passby
}
dataDic['index'].append(data['index'])
dataDic['name'].append(data['name'])
dataDic['x1'].append(data['x1'])
dataDic['y1'].append(data['y1'])
dataDic['x2'].append(data['x2'])
dataDic['y2'].append(data['y2'])
dataDic['passby'].append(data['passby'])
event = dataDic['passby'][1].split(",")
print event

global invisableBox, sentence, subsentence
invisableBox = []
lengthlist = len(dataDic['index'])

for i in range(lengthlist):
h = BOT(dataDic['index'][i], dataDic['name'][i], dataDic['x1'][i], dataDic[
'y1'][i], dataDic['x2'][i], dataDic['y2'][i], dataDic['passby'][i])
invisableBox.append(h)

print dataDic['name']
print len(invisableBox)


def drawOutline():
for h in invisableBox:
h.draw()

# if mousePressed == True:
sentence = h.generateSentence()
passby = h.generatePassby()

def draw():

# image(img1,0,0)
# image(img2,300,0)
# image(img3,600,0)
# image(img4,0,200)
# image(img5,300,200)
# image(img6,600,200)
# image(img7,0,400)
# image(img8,300,400)
# image(img9,600,400)
image(img10, 0, 30)
textSize(20)
fill(0)

text("Let play Serendipitious Map!", width/2, 10)
#text("Let me tell you what to do.", 180, 20)

stroke(255)
strokeWeight(2)

global status

sentence = "Please Begin."

#if mousePressed == True:
#line(mouseX, mouseY, pmouseX, pmouseY)

if frameCount == 1:
subprocess.check_output(['say', '"%s"' % sentence])

# print invisableBox

for h in invisableBox:
h.draw()

# if mousePressed == True:
sentence = h.generateSentence()
passby = h.generatePassby()
imgIndex = h.generateImageIndex()
xPos = h.generateX()
yPos = h.generateY()
if sentence is not None:

check.append(sentence)
if check[-1] != check[-2]:
# status.append("Inside")
print sentence
senData.append(sentence)
textSize(18)
fill(0)
print status
if len(senData) == 1:
background(100)

events = passby.split(",")

event = random.choice(events)

fill(255)
text(sentence, width/2, 750)

getImage = imageList[imgIndex]
print getImage
print xPos
print yPos
#image(getImage, xPos, yPos)
subprocess.check_output(['say', '"%s"' % sentence])
if status == "Here":
fill(255, 0, 0)
text(event,width/2,450)
noStroke()
ellipse(10, 750, 3, 3)

subprocess.check_output(['say', '"%s"' % event])

elif senData[-1] != senData[-2]:
background(100)

events = passby.split(",")

event = random.choice(events)

fill(255)
text(sentence, width/2, 750)
getImage = imageList[imgIndex]
print getImage
print xPos
print yPos
#image(getImage, 50, 50)
subprocess.check_output(['say', '"%s"' % sentence])
if status == "Here":

fill(255, 0, 0)
text(event,width/2,450)
noStroke()
ellipse(10, 750, 3, 3)


subprocess.check_output(['say', '"%s"' % event])


scan = [False]
if mousePressed == True:
scan.append(True)

if scan[0] != scan[-1]:

dict['x'].append(mouseX)
dict['y'].append(mouseY)
# print dict['x']
# print dict['y']
# line(mouseX,mouseY,pmouseX,pmouseY)
oX = dict['x'][0]
oY = dict['y'][0]

dX = dict['x'][-1]
dY = dict['y'][-1]
# fill(255,0,0)
# ellipse(oX,oY,3,3)
# fill(255,0,0)
# ellipse(dX,dY,3,3)
print oX, oY, dX, dY
if len(dict['x']) > 1:
if dict['x'][-2] == dict['x'][-1] and dict['y'][-2] == dict['y'][-1]:
status = "Here"

else:
status = "Running"

# redraw the line to override the damn subprocess!
i = 0
while i < len(dict['x']) - 1:
stroke(196, 216, 226)

line(
dict['x'][i], dict['y'][i], dict['x'][i + 1], dict['y'][i + 1])
i += 1
line(
dict['x'][-1], dict['y'][-1], dict['x'][-2], dict['y'][-2])



else:

scan.append(False)
# print scan
dict['x'] = []
dict['y'] = []
background(100)
image(img10, 0, 30)
for h in invisableBox:
h.draw()

# if mousePressed == True:
sentence = h.generateSentence()
passby = h.generatePassby()
imgIndex = h.generateImageIndex()
xPos = h.generateX()
yPos = h.generateY()

Conclusion

We envision the Serendipitous Map can be an new type of the social interaction by sketching, participating and engaging.

Maps are biased, so why not explore yourself with your sketch.

--

--