4

I have a list of vectors, a list of scalars and a start point represented by a tuple.

vecs = [(1,1), (2,3), (-1,1)]
scalars = [2, 3, 2]
start = (-5,0)

I have a function to add "k times" a vector to a point.

def add_vector(point, k, vec):
    return (point[0]+k*vec[0], point[1]+k*vec[1])

I would like to get the list of the points on the polyline such that :

result[0] = start
result[n+1] = add_vector(result[n], scalars[n], vecs[n]) 

I thought of using itertools.accumulate but the func argument must be a function of two arguments. Any ideas ?

Jacques Gaudin
  • 15,779
  • 10
  • 54
  • 75
  • Is it possible to accumulate x and then y? Combine x and y to become vector – Striker May 09 '16 at 14:10
  • @strike: that wouldn't be ideal since my points are actually a subclass of a tuple with added properties `point.x` and `point.y`, same for the vectors. – Jacques Gaudin May 09 '16 at 14:18
  • 1
    If your points are a subclass of tuple, why does your `add_vector` function not return an instance of that class? – holdenweb May 09 '16 at 14:20
  • @holdenweb: Good point. In the actual code it returns an instance of my `Point` class. I didn't show this in the question as I thought it would make it less clear. I can create an instance of `Point` from a `tuple` and a `tuple` from an instance of `Point` though. The list of vecs is already created as instances of `Point`. – Jacques Gaudin May 09 '16 at 14:27

3 Answers3

1

Just figured out I could create a generator function instead of using itertools.accumulate...

def accumulate_vector(start, scalars, vecs):
    prev = start
    yield start
    for k, vec in zip(scalars, vecs):
        prev = add_vector(prev, k, vec)
        yield prev
Jacques Gaudin
  • 15,779
  • 10
  • 54
  • 75
0

How about adding a helper function for add_vector (func() in the following code) :

from itertools import accumulate

def add_vector(point, k, vec):
    return (point[0]+k*vec[0], point[1]+k*vec[1])

def func(data1, data2): # data : a tuple (vector, scalar)
    vec1, k1 = data1
    vec2, k2 = data2
    return (add_vector(vec1, k2, vec2), k2)

vecs = [(1,1), (2,3), (-1,1)]
scalars = [2, 3, 2]
start = (-5,0)

temp = zip([start]+vecs, [1]+scalars)
result = [data[0] for data in accumulate(temp, func)]

print(result) # [(-5, 0), (-3, 2), (3, 11), (1, 13)]
hunminpark
  • 214
  • 3
  • 10
  • Thanks for your suggestion. The line `temp = zip([start]+vecs, [1]+scalars)` creates two lists which can potentially be quite long (1E5) though. – Jacques Gaudin May 09 '16 at 15:17
0

You could use numpy for vector calculations. Use numpy.dot function to multiply your scalars with your matrix of vectors. Finally add the start vector to the .dot product.

raptisth
  • 62
  • 3