В пользовательском интерфейсе WPF у меня есть узлы, связанные путями Безье, например:
Это может быть ... атомное http://nv3wrg.blu.livefilestore.com/y1pIGBd33lCC6lF-9H0MqgnL40BdNEoEemZDENzgpEI1IL2j4B-qb3qS3WlxMSys28IjqNngR7mdfvQBnPzerf4cFJQj9VqHBh4/acurve.png?psid=1
Когда пользователь перетаскивает узел, соединительные пути должны обновляться в режиме реального времени. Тем не менее, я заметил некоторое замедление (особенно если один узел подключен ко многим другим или несколько узлов перетаскиваются одновременно). Я профилировал это, и главная проблема, кажется, здесь:
Доказательство того, что я действительно использовал профилировщик, так что, пожалуйста, не будьте все как "OMG, преждевременная опификация; вы ДЕМОН !!" http://nv3wrg.blu.livefilestore.com/y1pjRfQYuN57yei5qdUxW4Dlh4vVCzPy8TcfEzlw_8cUicfOR6BwHCTntcQbQUspRAgBdKcItC0ZcEJbIWMKaYrCtDMOtCBKB4g/profile.png?psid=1
Эта функция вызывается каждый раз при изменении свойства источника или назначения. Кажется, что геометрия, составляющая путь, восстанавливается изнутри каждый раз, когда изменяется любая из контрольных точек. Возможно, если бы был способ предотвратить восстановление геометрии до тех пор, пока не будут установлены все соответствующие свойства зависимостей?
РЕДАКТИРОВАТЬ: Решение Марта использовать StreamGeometry ускорило его экспоненциально; функция нигде не близка к узкому месту. Небольшое размышление предполагает, что PathGeometry использует StreamGeometry внутри себя, и каждый раз, когда изменяется любое из свойств зависимостей, StreamGeometry пересчитывается. Таким образом, этот путь просто исключает посредника. Окончательный результат:
private void onRouteChanged()
{
Point src = Source;
Point dst = Destination;
if (!src.X.isValid() || !src.Y.isValid() || !dst.X.isValid() || !dst.Y.isValid())
{
_shouldDraw = false;
return;
}
/*
* The control points are all laid out along midpoint lines, something like this:
*
* --------------------------------
* | | | |
* | SRC | CP1 | |
* | | | |
* --------------------------------
* | | | |
* | | MID | |
* | | | |
* -------------------------------
* | | | |
* | | CP2 | DST |
* | | | |
* --------------------------------
*
* This causes it to be horizontal at the endpoints and vertical
* at the midpoint.
*/
double mx = (src.X + dst.X) / 2;
double my = (src.Y + dst.Y) / 2;
Point mid = new Point(mx, my);
Point cp1 = new Point(mx, src.Y);
Point cp2 = new Point(mx, dst.Y);
_geometry.Clear();
_shouldDraw = true;
using(StreamGeometryContext ctx = _geometry.Open())
{
ctx.BeginFigure(src, false, false);
ctx.QuadraticBezierTo(cp1, mid, true, false);
ctx.QuadraticBezierTo(cp2, dst, true, false);
}
}
Полный исходный код проекта доступен по адресу http://zeal.codeplex.com для любопытных.