У меня есть следующие массивы PathPoints и PathTypes (формат: X, Y, Type):
-177.477900, 11021.670000, 1
-614.447200, 11091.820000, 3
-1039.798000, 10842.280000, 3
-1191.761000, 10426.620000, 3
-1591.569000, 10493.590000, 3
-1969.963000, 10223.770000, 3
-2036.929000, 9823.960000, 3
-2055.820000, 9711.180000, 3
-2048.098000, 9595.546000, 3
-2014.380000, 9486.278000, 3
Вот как физически выглядит этот GraphicsPath. Две дуги очень различимы:
Я знаю, что этот массив GraphicsPath.PathData был создан двумя командами AddArc. Пройдясь по коду в отладчике, я увидел, что первые 4 значения PathData были добавлены первой командой AddArc, а оставшиеся 6 точек добавлены второй командой AddArc.
Изучив необработанные массивы точек пути/типа пути (предварительно не зная, что это были 2 команды AddArc, чтобы я знал, что у меня есть 2 начальная и конечная точки), я хотел бы определить начальную и конечную точки каждой дуги.
Я пробовал несколько вычислений Безье, чтобы "воссоздать" точки в массиве, но не могу определить, как определить отдельные начальную и конечную точки. Похоже, что GDI+ объединяет начальную/конечную точку между дугами (это одна и та же точка, а дуги соединены), и я теряю тот факт, что одна дуга заканчивается, а другая начинается.
Любые идеи?
Ответ 1 · рейтинг 1 · Julio Themen
Используйте класс GraphicsPathIterator в сочетании с методом GraphicsPath.SetMarkers.
Например:
dim gp as new GraphicsPath
gp.AddArc(-50, 0, 100, 50, 270, 90) 'Arc1
gp.SetMarkers()
gp.AddArc(0, 25, 100, 50, 270, 90) 'Arc2
Dim iterator as New GraphicsPathIterator(gp)
Dim i as Integer = 0
Dim MyPts(3) As PointF
Dim temp as New GraphicsPath
Do until i > 2
iterator.NextMarker(temp)
MyPts(i) = temp.PathPoints(0)
MyPts(i + 1) = temp.GetLastPoint()
i += 2
Loop
'Free system resources...
iterator.Dispose()
temp.Dispose()
Arc1 -> start: MyPts(0); end: MyPts(1)
Arc2 -> start: MyPts(2); end: MyPts(3)
Надеюсь это поможет!
Ответ 3 · SiliconMind
Меня этот тоже сильно напрягал! У меня был путь, созданный вне моего контроля без маркеров, и я не мог определить конечные точки кривой.
В этом случае вы ожидаете, что кривая начинается с [i + 1], но это не так! Оказывается, GDI объединяет точки пути, вероятно, для того, чтобы сделать массив точек короче. В этом случае точками кривой являются: [0], [1], [2], [3].
Кажется, что если за PathPointType.Start или PathPointType.Line следует PathPointType.Bezier, то вы должны рассматривать PathPontType.Start или Path.PointType.Line как первую точку вашей кривой Безье, поэтому в вашем примере это должно быть так:
-177.47, 11021.67, 1 // Draw line to this point AND use it as a Bezier start!
-614.44, 11091.82, 3 // Second Bezier point
-1039.79, 10842.28, 3 // Third Bezier point
-1191.76, 10426.62, 3 // Fourth Bezier point AND first point of the next Bezier!
-1591.56, 10493.59, 3 // Second Bezier point
-1969.96, 10223.77, 3 // Third Bezier point
-2036.92, 9823.96, 3 // Fourth Bezier point AND first point of the next Bezier!
-2055.82, 9711.18, 3 // Second Bezier point
-2048.09, 9595.54, 3 // Third Bezier point
-2014.38, 9486.27, 3 // Fourth Bezier point
Таким образом, при анализе массива PathPoints по точкам необходимо также проверять текущие и последующие индексы. Документы по PatPointType могут пригодиться. В большинстве случаев вы, вероятно, можете игнорировать дополнительные данные, хранящиеся в битах, отличных от первых трех (эти три определяют Start, Line и Bezier). Единственным исключением является CloseSubpath, но это не имеет значения, если вы прислушаетесь к следующему совету.
Также стоит отметить, что если у вас есть сложный путь, состоящий из огромного количества PathPoints, может быть удобно разбить путь на куски, используя GraphicsPathIterator. Это упрощает всю процедуру, так как PathPointType.CloseSubpath можно игнорировать - это всегда будет последняя точка вашего GraphicsPath чанка.
Краткий обзор Reflector или здесь может быть полезно, если вы хотите лучше понять массив PointTypes.