Live Geometry
Опубликовано 01 марта 2010 г. 11:10 | Coding4Fun
Live Geometry – интерактивный дизайнер геометрических фигур, созданный с применением Silverlight. Его можно использовать для визуализации и решения геометрических задач, а также для того, чтобы сделать занятия по геометрии более интересными и интерактивными для учителей и учащихся. Он построен на основе механизма динамической генерации геометрических фигур с открытым исходным кодом под .NET, который интерактивные дизайнеры могут использовать так же, как игры используют движки, ускоряющие обсчет физики.
Автор: Кирилл Осенков (Kirill Osenkov),
инженер отдела контроля качества Visual Studio C# IDE, Microsoft
https://blogs.msdn.com/kirillosenkov
https://twitter.com/kirillosenkov
Исходный код: https://livegeometry.codeplex.com
Запустить программу: https://livegeometry.com
Сложность: средняя
Необходимое время: 1–3 часа
Затраты: бесплатно!
ПО: Silverlight 3 Tools, Visual C# Express 2008 или 2010
Оборудование: карандаш, бумага, ластик, линейка, компас (все это не обязательно и может быть сымитировано с помощью перечисленного выше программного обеспечения)
Интерактивный дизайнер геометрии
Это онлайновое приложение позволяет создавать интерактивные геометрические рисунки и изучать их прямо в браузере. Вот как оно выглядит (щелкните иллюстрацию, и запустится демонстрация; на компьютере должен быть установлен Silverlight):
UI, по сути, состоит из двух частей: панели со всеми доступными инструментами (наверху) и области рисования (ниже). Щелкните кнопку Samples , чтобы загрузить начальную страницу для обучения. Вы можете сразу же взаимодействовать с этим рисунком – просто выберите инструмент Drag и перетащите любую из трех желтых точек. Также можно перетаскивать любой квадрат, стрелку или текстовые метки. Live Geometry позволяет перетаскивать практически что угодно, и, если вы создаете новый инструмент или фигуру, то можете легко добавить поддержку перетаскивания.
Как и обычные веб-страницы, рисунки могут содержать гиперссылки на другие рисунки. Щелкните любую ссылку, чтобы перейти к другому примеру. Рисунки из этого учебного пособия хранятся в сети в виде XML-файлов. Его начальная страница, которая была показана на иллюстрации выше, хранится по ссылке https://livegeometry.com/demo/demo.xml.
Вы можете сохранить любой рисунок на диск в виде файла с расширением .lgf (сокращение от Live Geometry file), который в основном содержит XML, и впоследствии вновь открыть его.
Чтобы создать новый рисунок, щелкните кнопку New . Для нанесения пары точек выберите инструмент Point и щелкните пару раз в любом месте рисунка. Чтобы вычертить сегмент или линию, выберите соответствующий инструмент на панели, а затем щелкните две точки, которые вы хотите соединить. При выборе инструмента в нижнем левом углу показывается подсказка, как им пользоваться.
Подробнее о том, как пользоваться инструментами и что можно сделать поинтереснее с существующими инструментами, смотрите в пятиминутном видеоролике здесь. Вы также можете перейти к учебному пособию Samples и просмотреть рисунки-примеры.
Встраивание геометрических рисунков в ваш веб-сайт
Вы можете встроить Silverlight-приложение Live Geometry в собственный веб-сайт. Пример того, как это сделать, вы найдете, перейдя на сайт https://livegeometry.com, – щелкните там View Source в своем браузере. Встраивание Silverlight осуществляется с помощью тега object:
HTML
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="https://livegeometry.com/LiveGeometry.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="3.0.40624.0" />
<param name="autoUpgrade" value="true" />
<a href="https://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">
<img src="https://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>
</a>
</object>
При сборке проекта Silverlight весь сгенерированный вывод упаковывается в файл с расширением .xap. Наиболее актуальный XAP-пакет для Live Geometry всегда публикуется по ссылке https://livegeometry.com/LiveGeometry.xap, так что вы можете просто ссылаться на него или разместить файл .xap на любом другом веб-сервере.
Чтобы при запуске Live Geometry открывала какой-либо рисунок, а не показывала пустое окно, можно передавать подходящие параметры через initParams:
HTML
<object data="data:application/x-silverlight-2,"
type="application/x-silverlight-2" width="800" height="600">
<param name="source" value="LiveGeometry.xap"/>
<param name="initParams"
value="LoadFile=https://livegeometry.com/demo/demo.xml,ShowToolbar=false" />
Заметьте, что ShowToolbar = false используется для скрытия панели инструментов.
Если вы публикуете собственный рисунок на вашем веб-сайте, вам следует знать об одном подвохе. Чтобы Live Geometry могла загрузить его, в корне вашего веб-сервера должен содержаться файл crossdomain.xml. Более подробные сведения о том, как встраивать собственные рисунки в веб-страницы, читайте здесь: Кривые Безье и производители автомобилей (EN).
Исходныйкод
Программа Live Geometry написана с применением Silverlight 3 и C# 3.0 (Visual Studio 2008). Также доступны версии проектов для Visual Studio 2010. Кроме того, вы можете скомпилировать настольную WPF-версию этого приложения, используя тот же исходный код.
Загрузив исходный код с сайта CodePlex по ссылке https://livegeometry.codeplex.com/SourceControl/list/changesets, вы увидите следующую структуру папок:
1. Main
- DynamicGeometryLibrary
- Samples
- SilverlightClient
- WPFClient
2. Reference – предыдущие версии (устаревший код)
Основная библиотека DynamicGeometry – гибкая и расширяемая инфраструктура, позволяющая легко добавлять новые типы фигур и функциональность. В настоящее время Live Geometry поддерживает два клиентских интерфейса – WPF и Silverlight, – которые совместно используют общую библиотеку DynamicGeometry.
Чтобы открыть решение на основе Silverlight, используйте Main\SilverlightClient\SilverlightClient.sln, а чтобы открыть решение на основе WPF – Main\WPFClient\WPFClient.sln.
Любое выбранное вами решение содержит два проекта: один – для UI, а другой – для библиотеки DynamicGeometry.
Для сборки и запуска в Visual Studio укажите соответствующий клиентский проект как стартовый (щелкните правой кнопкой мыши нужный проект в Solution Explorer и выберите Set As Startup), а затем нажмите F5.
Реализациямеханизмадинамическойгеометрии
Библиотека динамической геометрии (DynamicGeometry) содержит реализации всех инструментов и фигур, которые вы видите на панели инструментов, а также набора общих сервисов, таких как загрузка/сохранение, отмена, браузер свойств, стили, оценка выражений и т. д.:
Однако основным классом библиотеки является Drawing; он определен в Drawing.cs. Этот класс представляет один документ: геометрический рисунок, который можно в любой момент отобразить на холсте.
Определение фигур
Для примера вообразим, что инструмент Segment пока не реализован и что нам нужно добавить его поддержку. Все реализации фигур размещаются в папке Figures, поэтому мы переходим в \Figures\Lines\ и добавляем файл Segment.cs с таким содержимым:
C#
namespace DynamicGeometry
{
public class Segment : LineBase, ILine
{
[PropertyGridVisible]
public double Length
{
get
{
return Coordinates.Length;
}
}
public override double GetNearestParameterFromPoint(System.Windows.Point point)
{
// ...
}
public override IFigure HitTest(System.Windows.Point point)
{
var boundingRect =
Coordinates.GetBoundingRect().Inflate(CursorTolerance);
return boundingRect.Contains(point) ? base.HitTest(point) : null;
}
public override Tuple<double, double> GetParameterDomain()
{
return Tuple.Create(0.0, 1.0);
}
}
}
В библиотеке уже содержится несколько удобных базовых классов для линий (LineBase), окружностей (CircleBase), точек (PointBase) и фигур (ShapeBase<T>). Вот как выглядит схема дерева наследования для этих классов:
Мы наследуем от LineBase и переопределяем несколько методов.
HitTest определяет, находится ли некая точка (например, курсор мыши) над фигурой. В базовом классе LineBase уже определена логика, позволяющая узнавать, находится ли курсор над линией, но в нашем случае нужно добавить дополнительное ограничение и проверять, находится ли точка еще и между двумя конечными точками сегмента.
ParameterDomain используется, когда точка помещается в сегмент, но в этот статье мы его проигнорируем.
Наконец, мы объявляем свойство Length и помечаем его атрибутом [PropertyGridVisible].
Сетка свойств
Когда вы выбираете фигуру, а затем инструмент Drag, приложение Live Geometry отображает элемент управления «сетка свойств», позволяющий просматривать и изменять свойства выбранной фигуры:
Как видите, значение свойства Length теперь отображается в самом верху списка. Поскольку мы определили свойство Length только для чтения, пользователь не сможет изменять его значение. Все это достигается простым добавлением к свойству атрибута [PropertyGridVisible]. Остальные свойства на экранном снимке были объявлены точно так же (и наследуют от LineBase и его базовых классов). Например, Locked – это булево свойство в FigureBase – базовом классе всех фигур. Кнопки Delete, Edit style и Create new style напрямую сопоставлены с методами, как и редакторы свойств со свойствами фигуры.
Элемент управления «сетка свойств» позволяет отображать и изменять свойства, а также вызывать методы любого .NET-объекта, а не только фигур. Подробнее о сетке свойств, ее реализации и различных элементах управления «редакторы» читайте здесь: UI без кода, или XAML: PropertyGrid, DataForm и др. (EN).
Поведения
Простого объявления класса Segment в проекте недостаточно для того, чтобы он появился на панели инструментов и стал активным. Кнопки на панели инструментов в Live Geometry переводят холст (область рисования) в специальный режим Behavior. Когда вы щелкаете кнопку Segment, холст переходит в режим создания сегмента. Этот режим описывается классом SegmentCreator (пример кода содержится в \Figures\Lines\SegmentCreator.cs):
C#
using System.Windows;
using System.Windows.Media;
namespace DynamicGeometry
{
public class SegmentCreator : FigureCreator
{
protected override DependencyList InitExpectedDependencies()
{
return DependencyList.PointPoint;
}
protected override IFigure CreateFigure()
{
return Factory.CreateSegment(Drawing, FoundDependencies);
}
public override string Name
{
get { return "Segment"; }
}
public override string HintText
{
get
{
return "Click (and release) twice to connect two points with a segment.";
}
}
public override Color ToolButtonColor
{
get
{
return Color.FromArgb(255, 205, 255, 128);
}
}
public override FrameworkElement CreateIcon()
{
return IconBuilder.BuildIcon()
.Line(0.25, 0.75, 0.75, 0.25)
.Point(0.25, 0.75)
.Point(0.75, 0.25)
.Canvas;
}
}
}
Вот и все! Теперь, когда этот класс присутствует в проекте, на панели появится новый инструмент, и он будет работать ожидаемым образом. Но учтите одну маленькую деталь: новый инструмент по умолчанию появится в конце панели, однако в файле \Behaviors\BehaviorOrderer.cs можно указать порядок добавления инструментов на панель:
C#
private static List<Type> orders = new List<Type>()
{
typeof(Dragger),
typeof(FreePointCreator),
typeof(MidpointCreator),
typeof(ReflectionCreator),
typeof(SegmentCreator),
typeof(RayCreator),
...
С помощью механизма отражения Live Geometry сканирует сборку в поисках всех типов, наследующих от Behavior, и автоматически подключает их к панели инструментов.
Поэтому, чтобы добавить новую фигуру, от вас обычно требуется определить класс самой фигуры, например Bezier.cs, а также соответствующее поведение и кнопку на панели инструментов (скажем, BezierCreator.cs). Большинство инструментов наследует от общего базового класса FigureCreator, который предоставляет основную часть функциональности.
Действия
По большей части библиотека динамической геометрии берет на себя все операции Undo/Redo (отменить/вернуть), так что ваша новая фигура будет автоматически поддерживать неограниченное количество операций отмены и восстановления. Live Geometry использует еще один из моих .NET-проектов с открытым исходным кодом – Undo Framework, который можно скачать с https://undo.codeplex.com. Подробнее об Undo Framework см. здесь: Undo Framework (EN).
В папке Actions содержатся классы для поддержки наиболее распространенных отменяемых операций:
Элементыуправления
В папке Controls хранятся пользовательские элементы управления, применяемые в проекте. На данный момент это ColorPicker с https://silverlightcontrib.codeplex.com. Подробнее о селекторе цвета (color picker) см. здесь: ColorPicker Control для WPF/Silverlight (EN).
Выражения
Содержимое папки Expressions обеспечивает поддержку синтаксического разбора арифметических выражений и уравнений, таких как sin(x). Эта функциональность используется инструментами «график функции» (function plot) и «линейный график» (line plot): . Подробнее об оценке математических выражений читайте здесь.
Макросы
Содержимое папки Macros позволяет определять свои разновидности фигур в период выполнения, даже не закрывая приложение. Инструменты, определенные пользователем, добавляются в конец панели и сохраняются между сеансами работы с приложением на основе изолированного хранилища Silverlight Isolated Storage.
Сериализация
Содержимое папки Serialization обеспечивает поддержку записи фигур в XML-поток и чтения их оттуда. Обычно ваши фигуры сериализуются автоматически, поэтому для большинства нестандартных фигур вам не потребуется писать какой-либо код сериализации. Однако это позволяет переопределять соответствующие методы.
C#
void WriteXml(XmlWriter writer);
void ReadXml(XElement element);
Тем самым у вас появляется возможность вводить дополнительную логику сериализации для своей фигуры.
Стили
Вы можете определить стиль рисования фигуры (например, сплошной линией, точечной линией, в виде формы или стиль для текста), создав новый стиль либо выбрав один из существующих:
Затем вы можете назначить этот стиль нескольким фигурам и изменить этот стиль, так чтобы все фигуры автоматически обновили свой внешний вид (по аналогии с таблицами стилей CSS).
Заключение
Live Geometry – бесплатная программа с открытым исходным кодом. Вы можете изучать этот код, добавлять свои функции или создать собственный дизайнер, редактор векторной графики, приложение САПР или даже игру, использующую механизм динамической генерации геометрических фигур из Live Geometry. Так как приложение рассчитано на .NET, вы можете использовать любой .NET-совместимый язык вроде C#, VB, F#, IronPython или IronRuby. Поддержка Silverlight позволяет легко сделать ваше приложение доступным в сети.
Детали реализации Live Geometry вы можете изучить в документации этого проекта на сайте CodePlex: https://livegeometry.codeplex.com/documentation
Приглашаю всех к обсуждению Live Geometry на форуме, сообщайте мне об ошибках, высказывайте предложения и отзывы! Благодарю!
Обавторе
Кирилл Осенков – тестер в группе Microsoft Visual Studio. Он занимается тестированием многих функций C# IDE (IntelliSense, Refactorings, навигации, иерархии вызовов, выделением текста, форматированием и др.). В свободное время Кирилл работает над своими .NET-проектами с открытым исходным кодом, доступными на CodePlex: https://livegeometry.codeplex.com, https://undo.codeplex.com, https://structurededitor.codeplex.com и др.
Кирилл ведет блог https://blogs.msdn.com/kirillosenkov и блог на Twitter https://twitter.com/kirillosenkov.