Creating a new polygon feature class with specific coordinates in PyScripter - geometry

I am trying to create a new polygon feature class containing a single square polygon with the following coordinates: (0,0),(0,1000),(1000,0), AND (1000,1000), but my script keeps hitting a "VauleError: too many values to unpack" at the line "ID, X, Y = string.split(line, " ")"
Here is the rest of my script:
import arcpy
import fileinput
import string
import os
from arcpy import env
env.workspace = "E:/UNIVERSITY/Exercise08"
env.overwriteOutput = True
outpath ="E:/UNIVERSITY/Exercise08"
newfc = "Results/newpolygon.shp"
arcpy.CreateFeatureclass_management(outpath, newfc, "Polygon")
infile = "E:/UNIVERSITY/Exercise08/challengecoordinates.txt"
cursor = arcpy.da.InsertCursor(newfc, ["SHAPE#"])
array = arcpy.Array()
for line in fileinput.input(infile):
ID, X, Y = string.split(line, " ")
array.add(arcpy.Point(X, Y))
cursor.insertRow([arcpy.Polygon(array)])
fileinput.close()
del cursor

The line 01 0 0 0 1000 1000 1000 1000 0 won't unpack correctly, splitting on space will make a list of 9 elements from that line, and you're only assigning 3: (id, x, y).
Instead, you should take the line, and break it up into the parts you need for each component:
parts = line.split(" ")
id = parts[0] # 01
coord1 = "({},{})".format(parts[1], parts[2]) # 0 0 in input, output (0, 0)
<...>
coord4 = "({},{})".format(parts[7], parts[8]) # 1000 0 in input, output (1000, 0)
From there you should be able to join together your coordinates into the WKT that you described.

Related

Compact graph-vizualization using pydot

I would like to visualize a "linear" directed graph with the layout like that:
All the in- and out-degrees are 1 (except the first and last, of course). The length of the labels are different, so I can't calculate easily, how many nodes will fit in one row or the other. The code I have so far is this.
import networkx as nx
from networkx.drawing.nx_pydot import to_pydot
G = nx.DiGraph()
G.add_node("XYZ 1.0")
for i in range(1, 20):
G.add_node(f'XYZ 1.{i}', style='filled', fillcolor='skyblue')
G.add_edge(f'XYZ 1.{i-1}', f'XYZ 1.{i}')
# set defaults
G.graph['graph'] = {'rankdir': 'LR'}
G.graph['node'] = {'shape': 'rectangle'}
G.graph['edges'] = {'arrowsize': '4.0'}
pydt = to_pydot(G)
prog = 'dot'
file_name = f'nx_graph_{prog}.png'
pydt.write(file_name, prog=prog, format="png")
So far I use networkx in a project that needs to be run in a Python docker container, so I would like to use pydot and Networkx, if it is possible.
In some of the graphviz programs I can set coordinates if I understand correctly, but for setting coordinates I should know the widths of the boxes to avoid overlapping boxes.
I managed to find a way to do this with pydot. We can create a dot file with the coordinates with the write_dot function. Reading it back, we can get the coordinates that dot program created (and also the widths, heights). We can somehow calculate the new coordinates and modify them in the networkx Digraph. Converting again to pydot.Dot object, and at the end, we can use neato with the -n option to create the graph, that way we use the coordinates we have set. A working code can be seen below.
import networkx as nx
from networkx.drawing.nx_pydot import to_pydot
import pydot
from typing import List
G = nx.DiGraph()
G.add_node(0, label="XYZ 1.0")
for i in range(1, 20):
G.add_node(i, label=f'XYZ 1.{i}')
G.add_edge(i - 1, i)
# set defaults
G.graph['graph'] = {'rankdir': 'LR'}
G.graph['node'] = {'shape': 'rectangle'}
G.graph['edges'] = {'arrowsize': '4.0'}
pydt = to_pydot(G)
dot_data = pydt.create_dot()
pydt2 = pydot.graph_from_dot_data(dot_data.decode('utf-8'))[0]
def get_position(node):
pydot_node = pydt2.get_node(str(node))[0]
return [float(i) for i in pydot_node.get_attributes().get("pos")[1:-1].split(',')]
def fix_position(position: List, w: float = 1000, shift: float = 80):
x_orig, y_orig = position
n = int(x_orig / w)
y = y_orig - n * shift
remain_x = x_orig - n * w
if n % 2 == 0:
x = remain_x
else:
x = w - remain_x
return x, y
def refresh_coordinates_using_x():
for node in G.nodes:
position = get_position(node)
x, y = fix_position(position)
pos = f'"{x},{y}!"'
G.nodes[node]['pos'] = pos
refresh_coordinates_using_x()
pydt3 = to_pydot(G)
file_name = f'nx_graph_neato.png'
pydt3.write(file_name, prog=["neato", "-n"], format="png")
If you want to calculate the position of the nodes based on the widths, you need to know, that while the coordinates are in points, the widths are in inches. 1 inch is 72 points.
The result will be similar to this one.

Solving cars moving in multiple lanes simulation problem

I am trying to simulate cars moving in multiple lanes in python. The problem is like this:
The number of cars, the roadlength, the probability and vmax are all input values.
Rules:
1. If vi < vmax, increase the velocity vi of car i by one unit, that is, vi → vi + 1. This change models the process of acceleration to the maximum velocity.
2. Compute the distance to the next car in the same lane and the distance to the cars in both (if there are 2) lanes next to the car.
If d=max([d1,d2,d3]) and vi ≥ d, then reduce the velocity to vi = d − 1 to prevent crashes and switch lane to the lane where the distance to the next car is d (if there are multiple choose one at random or whichever you want).
Else (meaning there is at least one lane next to the car's lane or it could be the same lane that the car is in where d > vi) go in that lane and don't change the velocity of the car if there is more than one lane, pick one at random.
3. With probability p, reduce the velocity of a moving car by one unit: vi → vi − 1, only do this when v > 0 to avoid negative velocities
4. Update the position xi of car i so that xi(t + 1) = xi(t) + vi
Also the path of the cars is circular, meaning there will be cars in front and behind.
Below is my attempt to solve the problem. Don't get confused over the variables theta and r. theta is just the position and r is the lane.
My attempt:
from matplotlib import pyplot as plt
import random
import math
from matplotlib import animation
import numpy as np
from operator import attrgetter
roadLength = 100
numFrames = 200
nlanes = 3
numCars = 20
posss =[]
theta = []
r = []
color = []
probability = 0.5
vmax = 1
cars=[]
class Car:
def __init__(self, position, velocity, lane):
self.position = position
self.velocity = velocity
self.lane = lane
def pos(car,k):
rand = random.uniform(0,1)
if car[k].velocity < vmax:
car[k].velocity += 1
dist = 0
if car[k].lane == 1:
temp_lanes_between = [0,1]
if car[k].lane == nlanes and nlanes != 1:
temp_lanes_between = [-1 ,0]
if 1 < car[k].lane < nlanes:
temp_lanes_between = [-1 ,0, 1]
iterator = []
for p in range(k+1, numCars):
iterator.append(p)
#if car[k+1].position - car[k].position <= car[k].velocity and car[k].lane == car[k+1].lane:
for p in range(k):
iterator.append(p)
for s in iterator:
if car[s].lane - car[k].lane in temp_lanes_between:
temp_lanes_between.remove(car[s].lane - car[k].lane)
distance = min([abs((car[s].position - car[k].position) % roadLength), roadLength - abs((car[s].position - car[k].position) % roadLength)])
if dist < distance:
dist = distance
l = car[s].lane
if dist <= car[k].velocity:
break
if temp_lanes_between:
j=random.randrange(0, len(temp_lanes_between))
car[k].lane += temp_lanes_between[j]
if temp_lanes_between == [] and dist <= car[k].velocity:
car[k].velocity = dist - 1
car[k].lane = l
if rand < probability and car[k].velocity > 0:
car[k].velocity = car[k].velocity - 1
car[k].position = car[k].position + car[k].velocity
return car[k].position
for i in range(numCars):
cars.append(Car(i, 0, 1))
theta.append(0)
r.append(1)
color.append(i)
posss.append(i)
fig = plt.figure()
ax = fig.add_subplot(111)
point, = ax.plot(posss, r, 'o')
ax.set_xlim(-10, 1.2*numFrames)
ax.set_ylim(-2, nlanes + 3)
def animate(frameNr):
sort_cars = sorted(cars, key=attrgetter("position"))
for i in range(numCars):
pos(sort_cars,i)
for k in range(numCars):
theta[k]=cars[k].position
r[k]=cars[k].lane
print(theta)
print(r)
point.set_data(theta, r)
return point,
def simulate():
anim = animation.FuncAnimation(fig, animate,
frames=numFrames, interval=100, blit=True, repeat=False)
plt.show()
simulate()
I get error saying: "local variable 'l' referenced before assignment" in the line where car[k].lane = l . I know that they mean that l doesn't have any value and therefore I get this error. But I don't see how this is possible. Every time pos() is run it should always go through the line l = car[s].lane and there it gets assigned a value. Maybe there are more errors in the code above but I have really given it my best shot and I don't know what to do.
Thanks in advance!

How could I set the staring and ending points randomly in a grid that generates random obstacles?

I built a grid that generates random obstacles for pathfinding algorithm, but with fixed starting and ending points as shown in my snippet below:
import random
import numpy as np
#grid format
# 0 = navigable space
# 1 = occupied space
x = [[random.uniform(0,1) for i in range(50)]for j in range(50)]
grid = np.array([[0 for i in range(len(x[0]))]for j in range(len(x))])
for i in range(len(x)):
for j in range(len(x[0])):
if x[i][j] <= 0.7:
grid[i][j] = 0
else:
grid[i][j] = 1
init = [5,5] #Start location
goal = [45,45] #Our goal
# clear starting and end point of potential obstacles
def clear_grid(grid, x, y):
if x != 0 and y != 0:
grid[x-1:x+2,y-1:y+2]=0
elif x == 0 and y != 0:
grid[x:x+2,y-1:y+2]=0
elif x != 0 and y == 0:
grid[x-1:x+2,y:y+2]=0
elif x ==0 and y == 0:
grid[x:x+2,y:y+2]=0
clear_grid(grid, init[0], init[1])
clear_grid(grid, goal[0], goal[1])
I need to generate also the starting and ending points randomly every time I run the code instead of making them fixed. How could I make it? Any assistance, please?.
Replace,
init = [5,5] #Start location
goal = [45,45] #Our goal
with,
init = np.random.randint(0, high = 49, size = 2)
goal = np.random.randint(0, high = 49, size = 2)
Assuming your grid goes from 0-49 on each axis. Personally I would add grid size variables, i_length & j_length
EDIT #1
i_length = 50
j_length = 50
x = [[random.uniform(0,1) for i in range(i_length)]for j in range(j_length)]
grid = np.array([[0 for i in range(i_length)]for j in range(j_length)])

How do I implement mean shift by using a grid of centroids?

This is for a class and I would really appreciate your help! I made some changes based on a comment I received, but now I get another error..
I need to modify an existing function that implements the mean-shift algorithm, but instead of initializing all the points as the first set of centroids, the function creates a grid of centroids with the grid based on the radius. I also need to delete the centroids that don't contain any data points. My issue is that I don't understand how to fix the error I get!
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-7-de18ffed728f> in <module>()
49 centroids = initialize_centroids(x)
50
---> 51 new_centroids = update_centroids(x, centroids, r = 1)
52
53 print(len(centroids))
<ipython-input-7-de18ffed728f> in update_centroids(data, centroids, r)
26 #print(len(centroids))
27 #print(range(len(centroids)))
---> 28 centroid = centroids[i]
29 for data_point in data:
30 if np.linalg.norm(data_point - centroid) < r:
IndexError: index 2 is out of bounds for axis 0 with size 2
I tried using the range of the input dataset as boundaries for a grid, with the points separated by the radius.
from sklearn import datasets
import numpy as np
import matplotlib.pyplot as plt
def initialize_centroids(data, r = 1):
'''Creates a grid of centroids with grid based on radius'''
data = np.array(data)
xi,yi = min(range(len(data))), max(range(len(data)))
mx = np.arange(xi,yi,r)
x,y = np.meshgrid(mx,mx)
centroids=np.vstack([x.ravel(), y.ravel()])
return centroids
#update centroids based on mean of points that fall within a specified radius of each centroid
def update_centroids(data, centroids, r = 1):
new_centroids = []
for i in centroids:
in_radius = []
centroid = centroids[i] #this is where the error occurs
for data_point in data:
if np.linalg.norm(data_point - centroid) < radius:
in_radius.append(data_point) #this list is appended by adding the new centroid to it if the above conition is satisfied.
new_centroid = np.mean(in_radius, axis=0)
#maybe another way to do the next part
new_centroids.append(tuple(new_centroid))
unique_centroids = sorted(list(set(new_centroids))) #for element in in_radius, if element in set skip else set.append(element(in_rad)). append does not work with set.
new_centroids = {i:np.array(unique_centroids[i]) for i in range(len(unique_centroids))}
return new_centroids
#test function on:
x, y = datasets.make_blobs(n_samples=300, n_features = 2, centers=[[0, 7], [0, -7], [5,7], [5, 0]])
centroids = initialize_centroids(x)
new_centroids = update_centroids(x, centroids, radius = 2)
print(len(centroids))
print()
print(len(new_centroids))
#code for plotting initially:
plt.scatter(x[:,0], x[:,1], color = 'k')
for i in range(len(new_centroids)):
plt.scatter(new_centroids[i][0], new_centroids[i][1], s=200, color = 'r', marker = "*")
#code for plotting updated centroids:
new_centroids = update_centroids(x, new_centroids, radius = 2)
plt.scatter(x[:,0], x[:,1], color = 'k')
for i in range(len(new_centroids)):
plt.scatter(new_centroids[i][0], new_centroids[i][1], s=200, color = 'r', marker = "*")
#code for iterations:
def iterate_to_conv(data, max_iter=100):
centroids = initialize_centroids(data)
iter_count = 0
while iter_count <= max_iter:
new_centroids = update_centroids(data, centroids, radius = 2)
centroids = new_centroids
iter_count += 1
return centroids
centroids = iterate_to_conv(x)
plt.scatter(x[:,0], x[:,1], color = 'k')
for i in range(len(centroids)):
plt.scatter(centroids[i][0], centroids[i][1], s=200, color = 'r', marker = "*")
The function needs to return the number of final centroids. I haven't gotten ahead far enough to know how the entire implementation of mean-shift would work with this function..
When you are running that loop: for i in centroids the i that is iterated through centroids isn't a number, it is a vector which is why an error is pops up. For example, the first i value might be equal to [0 1 2 0 1 2 0 1 2]. So to take an index of that doesn't make sense. What your code is saying to do is to take centroid = centroid[n1 n2 nk]. To fix it, you really need to change how your initialize centroid function works. Meshgrid also won't create an N dimensional grid, so your meshgrid might work for 2 dimensions but not N. I hope that helps.

Generalize the construction of a Greek-Roman Matrix - Python

I wrote a python program that has as input a matrix, in which, each element appears in each row and column once. Elements are only positive integers.
e.g.
0,2,3,1
3,1,0,2
1,3,2,0
2,0,1,3
Then i find all possible traversals. They are defined as such:
choose an element from the first column
move on to the next column and
choose the element that is not in the same line from previous elements in traversal and the element has not the same value with previous elements in traversal.
e.g.
0,*,*,*
*,*,*,2
*,3,*,*
*,*,1,*
I have constructed the code that finds the traversals for matrices 4x4, but i have trouble generalizing it for NxN matrices. My code follows below. Not looking for a solution, any tip would be helpful.
import sys # Import to input arguments from cmd.
import pprint # Import for a cool print of the graph
import itertools # Import to find all crossings' combinations
# Input of arguments
input_filename = sys.argv[1]
# Create an empty graph
g = {}
# Initialize variable for the list count
i = 0
# Opens the file to make the transfer into a matrix
with open(input_filename) as graph_input:
for line in graph_input:
# Split line into four elements.
g[i] = [int(x) for x in line.split(',')]
i += 1
# Initialize variable
var = 0
# Lists for the crossings, plus rows and cols of to use for archiving purposes
f = {}
r = {}
c = {}
l = 0
# Finds the all the crossings
if len(g) == 4:
for x in range (len(g)):
for y in range (len(g)):
# When we are in the first column
if y == 0:
# Creates the maximum number of lists that don't include the first line
max_num = len(g) -1
for z in range (max_num):
f[l] = [g[x][y]]
r[l] = [x]
c[l] = [y]
l += 1
# When on other columns
if y != 0:
for z in range(len(g)):
# Initializes a crossing archive
used = [-1]
for item in f:
# Checks if the element should go in that crossing
if f[item][0] == g[x][0]:
if g[z][y] not in f[item] and z not in r[item] and y not in c[item] and g[z][y] not in used:
# Appends the element and the archive
f[item].append(g[z][y])
used.append(g[z][y])
r[item].append(z)
c[item].append(y)
# Removes unused lists
for x in range (len(f)):
if len(f[x]) != len(g):
f.pop(x)
#Transfers the value from a dictionary to a list
f_final = f.values()
# Finds all the combinations from the existing crossings
list_comb = list(itertools.combinations(f_final, i))
# Initialize variables
x = 0
w = len(list_comb)
v = len(list_comb[0][0])
# Excludes from the combinations all invalid crossings
while x < w:
# Initialize y
y = 1
while y < v:
# Initialize z
z = 0
while z < v:
# Check if the crossings have the same element in the same position
if list_comb[x][y][z] == list_comb[x][y-1][z]:
# Removes the combination from the pool
list_comb.pop(x)
# Adjust loop variables
x -= 1
w -= 1
y = v
z = v
z += 1
y += 1
x += 1
# Inputs the first valid solution as the one to create the orthogonal latin square
final_list = list_comb[0]
# Initializes the orthogonal latin square matrix
orthogonal = [[v for x in range(v)] for y in range(v)]
# Parses through the latin square and the chosen solution
# and creates the orthogonal latin square
for x in range (v):
for y in range (v):
for z in range (v):
if final_list[x][y] == g[z][y]:
orthogonal[z][y] = int(final_list[x][0])
break
# Initializes the orthogonal latin square matrix
gr_la = [[v for x in range(v)] for y in range(v)]
# Creates the greek-latin square
for x in range (v):
for y in range (v):
coords = tuple([g[x][y],orthogonal[x][y]])
gr_la[x][y] = coords
pprint.pprint(gr_la)
Valid traversals for the 4x4 matrix above are:
[[0123],[0312],[3210],[3021],[1203],[1032],[2130],[2301]]

Resources