How do I get 10 equally spaced points along a CGLine in SwiftUI?

I have written some code for an interactive canvas here and it all compiles and works correctly:

import SwiftUI

extension CGPoint: Hashable {
    public func hash(into hasher: inout Hasher) {
        hasher.combine(x)
        hasher.combine(y)
    }
}

struct Line {
    var points = [CGPoint]()
    var color: Color = .red
    var lineWidth: Double = 10.0
}

struct CharacterCanvas: View {
    @State private var currentLine = Line()
    @State private var lines: [Line] = []
    
    var body: some View {
        Canvas(opaque: false, colorMode: .linear, rendersAsynchronously: false) { context, size in
            
            for line in lines {
                var path = Path()
                path.addLines(line.points)
                context.stroke(path, with: .color(line.color), lineWidth: line.lineWidth)
            }
            
        }
        .gesture(DragGesture(minimumDistance: 0, coordinateSpace: .local)
        .onChanged({ value in
            let newPoint = value.location
            currentLine.points.append(newPoint)
            self.lines.append(currentLine)
        }) .onEnded({ value in
            self.currentLine = Line()
        })
        )
        .frame(minWidth: UIScreen.main.bounds.size.width, minHeight: UIScreen.main.bounds.size.width)
        .border(.red)
        .padding()
        
        Button("Clear") {
            currentLine = Line()
            lines = []
        }
        
        ScrollView {
            Text("Screen Size: \(UIScreen.main.bounds.size.width)")
            
            VStack {
                if !lines.isEmpty {
                    ForEach(lines.last!.points, id: \.self) { point in
                        Text("\(point.x), \(point.y)")
                    }
                }
            }
        }
    }
}

#Preview {
    CharacterCanvas()
}

I now want to find 10 equally spaced points for each Line struct based on their points array so I can feed that into a CoreML model to classify the line type. How would I go about finding these 10 equally spaced points? I might also need to generate additional points if there are less than 10 points in the points array.

Thanks, Jesse

Accepted Reply

Pseudo-code:

total_length = 0
foreach line segment
    total_length += length(segment)

spacing = total_length / 9   // note not 10!

seg = first segment
seg_start = 0
seg_end = length(seg)

for point in 0 ... 9
  distance = point * spacing
  while distance > seg_end
    seg = next_segment
    seg_start = seg_end
    seg_end = seg_start + length(seg)
  end while

  frac = (distance - seg_start) / length(seg)
  pos = lerp(start(seg), end(seg), frac)
  output pos
end for

Replies

Pseudo-code:

total_length = 0
foreach line segment
    total_length += length(segment)

spacing = total_length / 9   // note not 10!

seg = first segment
seg_start = 0
seg_end = length(seg)

for point in 0 ... 9
  distance = point * spacing
  while distance > seg_end
    seg = next_segment
    seg_start = seg_end
    seg_end = seg_start + length(seg)
  end while

  frac = (distance - seg_start) / length(seg)
  pos = lerp(start(seg), end(seg), frac)
  output pos
end for