The answer is actually simpler than you might think!
struct Point
x::Float64
y::Float64
end
struct Line
points::Vector{Point}
end
Line(s::Point, t::Point) = Line([Point(s.x+i*(t.x-s.x)/1000,s.y+i*(t.y-s.y)/1000) for i=0:1000]) # Aside: this is a function. You could also define it as a long-form function.
Then, for example
julia> s = Point(1,1)
Point(1.0, 1.0)
julia> t = Point(8,9)
Point(8.0, 9.0)
julia> Line(s,t)
Line(Point[Point(1.0, 1.0), Point(1.007, 1.008), Point(1.014, 1.016), Point(1.021, 1.024), Point(1.028, 1.032), Point(1.035, 1.04), Point(1.042, 1.048), Point(1.049, 1.056), Point(1.056, 1.064), Point(1.063, 1.072) … Point(7.937, 8.928), Point(7.944, 8.936), Point(7.951, 8.943999999999999), Point(7.958, 8.952), Point(7.965, 8.96), Point(7.972, 8.968), Point(7.979, 8.975999999999999), Point(7.986, 8.984), Point(7.993, 8.992), Point(8.0, 9.0)])
If you want to get the s and t back, then you can just grab them from the array of points. In fact, one "Julian" way to do this would be just to use multiple dispatch and add methods for the Line type to first and last, e.g.
julia> import Base.first
julia> first(l::Line) = first(l.points)
first (generic function with 42 methods)
julia> import Base.last
julia> last(l::Line) = last(l.points)
last (generic function with 36 methods)
julia> first(l)
Point(1.0, 1.0)
julia> last(l)
Point(8.0, 9.0)
Now if you want to make this more general, to allow points of any type rather than just Float64, then you could simply write
struct Point{T}
x::T
y::T
end
struct Line{T}
points::Vector{Point{T}}
end
instead, to make these structs parametric.