Внимание! При компиляции проекта прикладная библиотека должна быть обязательно отключена в менеджере библиотек
При компиляции проекта прикладная библиотека должна быть обязательно отключена в менеджере библиотек, иначе компилятор сообщит об ошибке. Исходные файлы этой простейшей библиотеки, а также сам исполняемый файл приложения Hello_KOMPAS.rtw находятся на прилагаемом к книге компакт-диске в папке Examples\Глава 6\Delphi Programming\FirstLib. При попытке компиляции исходных файлов на своем компьютере вы должны учитывать, что куда бы ни были скопированы исходники с диска, пути к файлам библиотек КОМПАС, указанные в настройках проекта, будут отличаться. По этой причине перед компиляцией обязательно отредактируйте эти пути (см. рис. 6.22) и лишь после этого выполняйте сборку библиотеки. Разработка мини-САПР зубчатых колес Для лучшего усвоения прочитанного материала разработаем мини-САПР, создающую по минимальному количеству исходных данных 3D-модель зубчатого колеса (как прямозубого, так и косозубого). В общих чертах задача такова: после вызова библиотеки пользователем появляется диалоговое окно, в котором он задает модуль, количество зубьев, ширину зубчатого венца, а также угол наклона зубьев колеса. По введенным параметрам, после нажатия кнопки Построение, библиотека должна сгенерировать трехмерную модель колеса. Выполните заготовку конструкторской библиотеки, как это было описано в предыдущем разделе. Чтобы немного облегчить себе задачу, вы можете воспользоваться готовым шаблоном, для чего скопируйте все исходные файлы предыдущего примера в новую директорию (назовем ее Gears3D) и сохраните проект под новым именем (Gears3D.dpr). Обязательно отредактируйте пути к файлам библиотек КОМПАС (то есть к папке Gears3D\dcu) в настройках проекта. Измените название библиотеки на Gears miniCAD и оставьте старый идентификатор библиотеки. Скопируйте из папки SDK\Include в каталог Gears3D\dcu еще один файл с описаниями констант, использующимися при инициализации различных интерфейсов, – ksConstTLB.pas. Затем можно, наконец, приступать к выполнению проекта. Поскольку взаимодействие с пользователем планируется осуществлять с помощью диалогового окна, в проект необходимо добавить диалоговую форму. Для этого выполните команду File → New → Form, после чего в инспекторе объектов настройте часть свойств формы (табл. 6.8), оставив остальные заданными по умолчанию. Таблица 6.8. Настройка свойств формы диалогового окна библиотеки После создания формы Delphi автоматически сгенерировал модуль (unit) с кодом ее описания. Удалите из этого модуля описание глобальной переменной GearsForm типа TGearsForm и сохраните модуль под именем BuildUnit.pas. Добавьте на форму по четыре текстовых метки (TLabel) и поля ввода (TEdit), а также две кнопки (TButton). Присвойте им заголовки Построение и Отмена. Разместите указанные элементы управления приблизительно так, как показано на рис. 6.24. Рис. 6.24. Форма будущего диалогового окна библиотеки
После создания формы необходимо обеспечить ее вывод в окне КОМПАС. Задача, на первый взгляд, сложная, но решается просто. Для вывода диалогового окна библиотеки нужно сделать следующее. 1. Получить дескриптор главного окна КОМПАС. 2. Запретить доступ пользователю к главному окну программы. 3. Создать объект диалогового окна и вывести его на экран в модальном режиме. 4. После закрытия пользователем окна библиотеки уничтожить окно и вернуть управление главным окном КОМПАС пользователю. 5. Обнулить дескриптор приложения. Реализовать эту последовательность действий лучше всего в процедуре точки входа в библиотеку (листинг 6.10). Листинг 6.10. Вывод диалогового окна библиотеки procedure LibraryEntry(command: WORD); pascal; var GearsForm: TGearsForm; begin kompas:= KompasObject(CreateKompasObject); if (kompas = nil) then exit; // получаем дескриптор главного окна КОМПАС Application.Handle:= kompas.ksGetHWindow; // запрещаем доступ к главному окну kompas.ksEnableTaskAccess(0); // создаем объект диалогового окна GearsForm:= TGearsForm.Create(Application); GearsForm.ks:= kompas; // выводим диалог на экран GearsForm.ShowModal; // удаляем объект GearsForm.Free; // возвращаем доступ к окну kompas.ksEnableTaskAccess(1); Application.Handle:= 0; kompas:= nil; end; В приведенном фрагменте кода есть одна, на первый взгляд, непонятная строка – GearsForm.ks:= kompas;. В действительности, здесь все просто. Поскольку обработка построения зубчатого колеса будет выполнена внутри класса формы TGearsForm, то для того, чтобы в нем не получать заново указатель на интерфейс KompasObject, этот указатель передается внешней переменной ks класса TGearsForm. Разумеется, эту переменную (типа KompasObject) необходимо предварительно добавить в раздел public описания класса формы. Перед этим подключите в разделе uses модуля BuildUnit следующие файлы (модули): ksTLB, ksAuto, ksConstTLB, LDefin3D, LDefin2D и math (последний не относится к КОМПАС API, это стандартный модуль математических функций Delphi). Скомпилируйте проект и подключите полученную библиотеку Gears3D.rtw к КОМПАС. Запустите ее и убедитесь, что после выполнения ее единственной команды в центре главного окна появляется созданное нами диалоговое окно. Перейдем к реализации обработчиков щелчка на кнопках. Начнем со второй (Отмена), поскольку ее обработчик чрезвычайно прост. Щелкните дважды в редакторе форм на кнопке Отмена и в обработчике, автоматически созданном в редакторе кода, введите всего одну строку, закрывающую форму (листинг 6.11). Листинг 6.11. Обработчик щелчка на кнопке Отмена procedure TGearsForm.Button2Click(Sender: TObject); begin if CloseQuery then Close; end; Процедура обработки нажатия кнопки Построение намного сложнее. Условно ее можно разделить на три части. 1. Расчет геометрических параметров зубчатого колеса по введенным исходным данным. 2. Создание пустого документа КОМПАС-Деталь. 3. Собственно построение модели зубчатого колеса. Программное построение модели колеса реализуем такой последовательностью трехмерных операций. 1. Сначала программно в плоскости XOY создается эскиз, содержащий контур половины сечения колеса (такой же, какой мы выполняли при моделировании вручную в гл. 3). На основании этого эскиза выполняется операция вращения, формирующая заготовку зубчатого колеса. 2. Далее в плоскости YOZ строится второй эскиз с четырьмя окружностями, над которыми выполняется операция вырезания в два направления. Таким образом, мы получим отверстия в диске. 3. Следующим шагом является выполнение выреза между зубьями в венце колеса. Для построения выреза воспользуемся первым из способов, предложенных в гл. 3. Напомню, этот способ заключается в построении выреза с помощью операции Вырезать по сечениям. При этом в модели колеса строится ряд эскизов-сечений, плоскости которых удалены от боковой поверхности колеса на величину l = i · b / (n с – 1) (где b – ширина колеса, n с – количество сечений или эскизов, i – порядковый номер эскиза). Для нашей библиотеки достаточно будет трех эскизов: по два на торцевых плоскостях колеса и один посредине – на плоскости YOZ. Это значит, что библиотека должна будет построить две вспомогательные плоскости, удаленные в обе стороны от плоскости YOZ на половину ширины венца зубчатого колеса. В каждой из трех плоскостей (двух вспомогательных и ортогональной YOZ) будет создано изображение эскиза выреза между зубьями, повернутое относительно вертикальной оси на угол α = 2 · l · tg β / d к, где β – угол наклона линии зуба, d к – делительный диаметр зубчатого колеса (обоснование этой зависимости приведено в гл. 3). Для первой плоскости вместо l необходимо подставить 0, для второй (YOZ) – b/2, для третьей – b. 4. В завершении создается ось на пересечении плоскостей XOZ и XOY. Относительно этой оси формируется массив по концентрической сетке вырезов между зубьями колеса. Количество копий устанавливается равным количеству зубьев колеса. Начнем с первого этапа реализации построения: расчета геометрических характеристик создаваемого колеса (листинг 6.12). Листинг 6.12. Расчет параметров колеса procedure TGearsForm.Button1Click(Sender: TObject); var // раздел объявления переменных // все объекты приведенных интерфейсов используются при построении doc3: ksDocument3D; iPart: ksPart; PlaneXOY: ksEntity; PlaneXOZ: ksEntity; PlaneYOZ: ksEntity; SketchEntity: ksEntity; iSketchDef: ksSketchDefinition; doc: ksDocument2D; r: reference; iBaseRotatedEntity: ksEntity; Color: ksColorParam; iBaseRotatedDef: ksBaseRotatedDefinition; iSketch1Entity: ksEntity; iSketch1Def: ksSketchDefinition; iCutExtrusion: ksEntity; iCutExtrusionDef: ksCutExtrusionDefinition; iOffsetPlaneEntity: ksEntity; iOffsetPlaneDef: ksPlaneOffsetDefinition; iSketch2Entity: ksEntity; iSketch2Def: ksSketchDefinition; iSketch3Entity: ksEntity; iSketch3Def: ksSketchDefinition; iOffsetPlane1Entity: ksEntity; iOffsetPlane1Def: ksPlaneOffsetDefinition; iSketch4Entity: ksEntity; iSketch4Def: ksSketchDefinition; iCutLoftEntity: ksEntity; iCutLoftDef: ksCutLoftDefinition; Collect: ksEntityCollection; iAxis: ksEntity; iAxis2PlDef: ksAxis2PlanesDefinition; iCircularCopy: ksEntity; iCirCopyDef: ksCircularCopyDefinition; Collect1: ksEntityCollection; // геометрические параметры колеса module: double; Lm, Dm: double; Dv: double; b_k, c: double; d_k, d_fk, d_ak: double; delta0: double; z: integer; beta: double; Dotv: double; alfa1, alfa2: double; begin Hide; // прячем диалоговое окно // считываем параметры, введенные пользователем в окне module:= StrToFloat(Edit1.Text); z:= StrToInt(Edit2.Text); Lm:= StrToFloat(Edit3.Text); beta:= StrToFloat(Edit4.Text); // диаметр отверстия под вал Dv:= round(Lm/1.4); // ширину маточины и ширину колеса принимаем равными b_k:= Lm; // диаметр маточины Dm:= 1.8*Dv; // толщина диска, соединяющего маточину с ободом c:= round(0.35*b_k); // толщина обода delta0:= round(2.5*module/cos(DegToRad(beta))); d_k:= module*z; // делительный диаметр колеса d_ak:= d_k+2*module; // диаметр выступов d_fk:= d_k-2.5*module; // диаметр впадин // диаметр размещения центров отверстий в диске Dotv:= (d_fk – 2*delta0 + Dm)/2; // создание детали... // построение модели... Close; // закрываем форму end; Если сейчас собрать приложение и попробовать запустить библиотеку, ничего происходить не будет, потому что пока ничего не создается и не строится. Следующий этап построения намного более интересен – он заключается в программном создании документа КОМПАС-Деталь (листинг 6.13). В данном листинге раздел описания переменных и расчет параметров колеса пропущен, а приведен только фрагмент кода, реализующий создание документа-детали. В процедуру построения (обработчик нажатия кнопки Построение) этот фрагмент должен быть вставлен сразу после расчетов. Листинг 6.13. Создание документа детали // получаем указатель на интерфейс трехмерного документа doc3:= ksDocument3D(ks.Document3D()); // создаем документ // параметр false – в видимом режиме // параметр true – документ-деталь if doc3.Create(false, true) then begin // заполняем параметры документа doc3.author:= “Максим Кидрук”; doc3.comment:= “Зубчатое колесо”; doc3.drawMode:= 3; doc3.perspective:= true; doc3.UpdateDocumentParam(); end else exit; // проверяем, как прошла инициализация if (doc3 = nil) then begin ks.ksMessage(“Не удалось создать документ!”); exit; end; Откомпилировав и запустив приложение, вы сможете наблюдать, как после закрытия диалогового окна (нажатия кнопки Построение) программа сама создаст пустой документ КОМПАС-Деталь. В листинге 6.14 приведен с небольшими сокращениями код построения трехмерной модели. Недостающие фрагменты кода вы можете взять из файла Examples\Глава 6\Delphi Programming\Gears3D\BuildUnit.pas на диске. Фрагмент кода содержит достаточно подробные комментарии, поэтому, полагаю, разобраться в нем будет несложно. Листинг 6.14. Построение модели колеса // получаем указатель на интерфейс детали iPart:= ksPart(doc3.GetPart(pNew_Part)); if (iPart <> nil) then begin // интерфейсы ортогональных плоскостей PlaneXOY:= ksEntity(iPart.GetDefaultEntity(o3d_planeXOY)); PlaneXOZ:= ksEntity(iPart.GetDefaultEntity(o3d_planeXOZ)); PlaneYOZ:= ksEntity(iPart.GetDefaultEntity(o3d_planeYOZ)); // интерфейс эскиза (половина контура сечения колеса) iSketchEntity:= ksEntity(iPart.NewEntity(o3d_sketch)); if (iSketchEntity <> nil) then begin // интерфейс параметров эскиза iSketchDef:= ksSketchDefinition(iSketchEntity.GetDefinition); if (iSketchDef <> nil) then begin if (PlaneXOY <> nil) then begin // устанавливаем плоскость, // на которой создается эскиз iSketchDef.SetPlane(PlaneXOY); iSketchEntity.Create; // запускаем процесс редактирования эскиза // doc – указатель на интерфейс ksDocument2D doc:= ksDocument2D(iSketchDef.BeginEdit); if (doc <> nil) then begin // вычерчиваем изображение эскиза // с помощью методов интерфейса ksDocument2D // код пропущен end; // завершение редактирования эскиза iSketchDef.EndEdit; end; end; end; // интерфейс базовой операции вращения iBaseRotatedEntity:= ksEntity(iPart.NewEntity(o3d_baseRotated)); // интерфейс параметров цвета и визуальных свойств Color:= ksColorParam(iBaseRotatedEntity.ColorParam); Color.specularity:= 0.8; Color.shininess:= 1; if (iBaseRotatedEntity <> nil) then begin // интерфейс параметров вращения iBaseRotatedDef:= ksBaseRotatedDefinition(iBaseRotatedEntity.GetDefinition); if (iBaseRotatedDef <> nil) then begin // настройка параметров вращения iBaseRotatedDef.SetThinParam(false, dtNormal, 1, 1); iBaseRotatedDef.SetSideParam(true, 360); iBaseRotatedDef.toroidShapeType:= false; iBaseRotatedDef.SetSketch(iSketchEntity); // создаем операцию вращения // результат – заготовка зубчатого колеса iBaseRotatedEntity.Create; end; end; // интерфейс эскиза (отверстия в диске) iSketch1Entity:= ksEntity(iPart.NewEntity(o3d_sketch)); if (iSketch1Entity <> nil) then begin iSketch1Def:= ksSketchDefinition(iSketch1Entity.GetDefinition); if (iSketch1Def <> nil) then begin if (PlaneYOZ <> nil) then begin // размещаем эскиз на плоскости YOZ iSketch1Def.SetPlane(PlaneYOZ); iSketch1Entity.Create; doc:= ksDocument2D(iSketch1Def.BeginEdit); if (doc <> nil) then begin // изображение в эскизе – 4 окружности // создаются вызовом метода ksDocument2D::ksCircle doc.ksCircle(0, Dotv/2, 0.4*(d_fk/2-delta0-Dm/2), 1); doc.ksCircle(0, -Dotv/2, 0.4*(d_fk/2-delta0-Dm/2), 1); doc.ksCircle(Dotv/2, 0, 0.4*(d_fk/2-delta0-Dm/2), 1); doc.ksCircle(-Dotv/2, 0, 0.4*(d_fk/2-delta0-Dm/2), 1); end; iSketch1Def.EndEdit; end; end; end; // интерфейс операции Вырезать выдавливанием iCutExtrusion:= ksEntity(iPart.NewEntity(o3d_cutExtrusion)); if (iCutExtrusion <> nil) then begin // интерфейс параметров вырезания iCutExtrusionDef:= ksCutExtrusionDefinition(iCutExtrusion.GetDefinition); if (iCutExtrusionDef <> nil) then begin // настройка параметров iCutExtrusionDef.SetSketch(iSketch1Entity); // направление iCutExtrusionDef.directionType:= dtBoth; // величина вырезания по каждому из направлений iCutExtrusionDef.SetSideParam(true, etBlind, c/2, 0, false); iCutExtrusionDef.SetSideParam(false, etBlind, c/2, 0, false); iCutExtrusionDef.SetThinParam(false, 0, 0, 0); // создаем отверстия в диске iCutExtrusion.Create; end; end; // интерфейс смещенной плоскости iOffsetPlaneEntity:= ksEntity(iPart.NewEntity(o3d_planeOffset)); if (iOffsetPlaneEntity <> nil) then begin // интерфейс параметров смещенной плоскости iOffsetPlaneDef:= ksPlaneOffsetDefinition(iOffsetPlaneEntity.GetDefinition); if (iOffsetPlaneDef <> nil) then begin // величина, базовая плоскость и другие параметры смещения iOffsetPlaneDef.Offset:= b_k/2; iOffsetPlaneDef.SetPlane(PlaneYOZ); iOffsetPlaneDef.direction:= false; // делаем плоскость скрытой iOffsetPlaneEntity.Hidden:= true; // создаем вспомогательную плоскость iOffsetPlaneEntity.Create; end; end; // эскиз первого выреза между зубьями iSketch2Entity:= ksEntity(iPart.NewEntity(o3d_sketch)); if (iSketch2Entity <> nil) then begin iSketch2Def:= ksSketchDefinition(iSketch2Entity.GetDefinition); if (iSketch2Def <> nil) then begin // базовая плоскость – вспомогательная iOffsetPlaneEntity iSketch2Def.SetPlane(iOffsetPlaneEntity); iSketch2Entity.Create; doc:= ksDocument2D(iSketch2Def.BeginEdit); alfa1:= 360/z; doc.ksMtr(0, 0, 90, 1, 1); // вычерчивание изображения эскиза // вместо эвольвент для простоты // берем обычные дуги по трем точкам // код пропущен doc.ksDeleteMtr; iSketch2Def.EndEdit; end; end; // интерфейс второго эскиза выреза между зубьями iSketch3Entity:= ksEntity(iPart.NewEntity(o3d_sketch)); if (iSketch3Entity <> nil) then begin iSketch3Def:= ksSketchDefinition(iSketch3Entity.GetDefinition); if (iSketch3Def <> nil) then begin // строим на плоскости YOZ iSketch3Def.SetPlane(PlaneYOZ); iSketch3Entity.Create; doc:= ksDocument2D(iSketch3Def.BeginEdit); alfa2:= -RadToDeg(b_k*tan(DegToRad(beta))/d_k); doc.ksMtr(0, 0, 90, 1, 1); // вычерчивание изображения эскиза // вместо эвольвент для простоты // берем обычные дуги по трем точкам // код пропущен doc.ksDeleteMtr; iSketch3Def.EndEdit; end; end; // вторая смещенная плоскость iOffsetPlane1Entity:= ksEntity(iPart.NewEntity(o3d_planeOffset)); if (iOffsetPlane1Entity <> nil) then begin iOffsetPlane1Def:= ksPlaneOffsetDefinition(iOffsetPlane1Entity.GetDefinition); if (iOffsetPlane1Def <> nil) then begin // величина смещения та же iOffsetPlane1Def.Offset:= b_k/2; // направление противоположное iOffsetPlane1Def.direction:= true; iOffsetPlane1Def.SetPlane(PlaneYOZ); // делаем плоскость скрытой iOffsetPlane1Entity.Hidden:= true; // создаем смещенную плоскость iOffsetPlane1Entity.Create; end; end; // третий (последний) эскиз выреза между зубьями iSketch4Entity:= ksEntity(iPart.NewEntity(o3d_sketch)); if (iSketch4Entity <> nil) then begin iSketch4Def:= ksSketchDefinition(iSketch4Entity.GetDefinition); if (iSketch4Def <> nil) then begin // базовая плоскость – только что созданная смещенная iSketch4Def.SetPlane(iOffsetPlane1Entity); iSketch4Entity.Create; doc:= ksDocument2D(iSketch4Def.BeginEdit); alfa2:= -RadToDeg(2*b_k*tan(DegToRad(beta))/d_k); doc.ksMtr(0, 0, 90, 1, 1); // вычерчивание изображения эскиза // вместо эвольвент для простоты // берем обычные дуги по трем точкам // код пропущен doc.ksDeleteMtr; iSketch4Def.EndEdit; end; end; // интерфейс операции Вырезать по сечениям iCutLoftEntity:= ksEntity(iPart.NewEntity(o3d_cutLoft)); if (iCutLoftEntity <> nil) then begin // интерфейс параметров операции по сечениям iCutLoftDef:= ksCutLoftDefinition(iCutLoftEntity.GetDefinition); if (iCutLoftDef <> nil) then begin // интерфейс массива ksEntityCollection // коллекции эскизов для вырезания по сечениям Collect:= ksEntityCollection(iCutLoftDef.Sketchs); // добавляем эскизы в колекцию Collect.Add(iSketch2Entity); Collect.Add(iSketch3Entity); Collect.Add(iSketch4Entity); // создаем операцию по сечениям // результат – первый вырез между зубьями в венце колеса iCutLoftEntity.Create; end; end; // интерфейс вспомогательной оси на пересечении двух плоскостей iAxis:= ksEntity(iPart.NewEntity(o3d_axis2Planes)); if (iAxis <> nil) then begin // интерфейс параметров вспомогательной оси // на пересечении плоскостей iAxis2PlDef:= ksAxis2PlanesDefinition(iAxis.GetDefinition); if (iAxis2PlDef <> nil) then begin // задаем плоскости iAxis2PlDef.SetPlane(1, PlaneXOZ); iAxis2PlDef.SetPlane(2, PlaneXOY); // делаем ось невидимой iAxis.hidden:= true; // создаем вспомогательную ось iAxis.Create; end; end; // интерфейс операции Массив по концентрической сетке iCircularCopy:= ksEntity(iPart.NewEntity(o3d_circularCopy)); if (iCircularCopy <> nil) then begin // интерфейс параметров операции копирования по массиву iCirCopyDef:= ksCircularCopyDefinition(iCircularCopy.GetDefinition); if (iCirCopyDef <> nil) then begin // коллекция операций для копирования Collect1:= ksEntityCollection(iCirCopyDef.GetOperationArray); // операция всего лишь одна – вырезание зуба Collect1.Add(iCutLoftEntity); // количество копий, равно количеству зубьев iCirCopyDef.count2:= z; iCirCopyDef.factor2:= true; // ось копирования iCirCopyDef.SetAxis(iAxis); // создаем концентрический массив – колесо готово! iCircularCopy.Create; end; end; end; Если вы разобрались в приведенном фрагменте кода, добавьте его в создаваемый проект. Недостающие части скопируйте из файла модуля построения, который находится на прилагаемом к книге компакт-диске. В них нет ничего сложно, обычная последовательность ввода графических примитивов с помощью методов ksLineSeg, ksArcByAngle и ksCircle интерфейса ksDocument2D, просто они достаточно громоздки, чтобы приводить их полностью на страницах книги. Вновь соберите (перекомпилируйте) библиотеку. Перейдите в окно КОМПАС и запустите приложение из менеджера библиотек. Введите исходные данные для зубчатого колеса (например, модуль – 3, 5 мм, количество зубьев – 56, ширина зубчатого венца – 60 мм и угол наклона линии зубьев – 15°) и нажмите кнопку Построение.
|