А.Н. Юров М.В. Паринов А.В. Ачкасов К.В. Зольников В.Э. Меерсон ИНСТРУМЕНТАЛЬНЫЕ СРЕДСТВА ИНФОРМАЦИОННЫХ СИСТЕМ Учебное пособие Воронеж 2021 МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ «ВОРОНЕЖСКИЙ ГОСУДАРСТВЕННЫЙ ЛЕСОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ ИМЕНИ Г.Ф. МОРОЗОВА» А.Н. Юров М.В. Паринов А.В. Ачкасов К.В. Зольников В.Э. Меерсон ИНСТРУМЕНТАЛЬНЫЕ СРЕДСТВА ИНФОРМАЦИОННЫХ СИСТЕМ Учебное пособие Воронеж 2021 УДК 621.9.06.002 П27 Печатается по решению учебно-методического совета ФГБОУ ВО «ВГЛТУ» (протокол № от 2021 г.) Рецензенты: АО НИИЭТ Научно – технический совет; ученый секретарь Макаренко Ф.В. ФГБОУ ВО ВГТУ д-р техн. наук, проф. В.Ф. Барабанов Инструментальные средства информационных систем: учеб. пособие / А.Н. Юров, М.В. Паринов, А.В. Ачкасов, К.В. Зольников, В.Э. Меерсон Воронеж: М-во науки и высшего образования РФ, ФГБОУ ВО «ВГЛТУ». – Воронеж, 2021. – 83 с. В учебном пособии изложены общие положения, связанные с процессом технологий автоматизированного проектирования и разработкой прикладных библиотек под Компас 3D с применением языков высокого уровня. Приведенные методы и процессы позволяют успешно решать производственные задачи по созданию расчетного и инженерного программного обеспечения, используя специфику работы предприятия при решении конструкторских задач на стадии проектирования. Учебное пособие предназначено для студентов, обучающихся по направлению подготовки 09.03.02 “Информационные системы и технологии” по дисциплинам «Инструментальные средства информационных систем» и «Компьютерная графика и геометрия». Так же может быть использовано при обучении слушателей по соответствующим программам дополнительного профессионального образования. УДК 621.9.06.002 Ил. 58. Библиогр.: 14 назв. © Юров А.Н., Паринов М.В.,Ачкасов А.В., Зольников К.В., Меерсон В.Э. 2021 ISBN © ФГБОУ ВО «ВГЛТУ », 2021 3 ОГЛАВЛЕНИЕ ВВЕДЕНИЕ 4 1. СОЗДАНИЕ ПРОЕКТОВ ПРИКЛАДНЫХ БИБЛИОТЕК 7 КОМПАС В СРЕДЕ VISUAL C++ 7 2. РАБОТА С ГРАФИЧЕСКИМИ ОБЪЕКТАМИ НА ПЛОСКОСТИ 19 2.1. Функции для работы с графическими документами 25 2.2. Функции построения составных объектов 33 2.3. Функции ввода параметров 35 3. МЕТОДЫ И ИХ СОСТАВЛЯЮЩИЕ 37 ДЛЯ ПРОВЕДЕНИЯ ВСПОМОГАТЕЛЬНЫХ ПОСТРОЕНИЙ 37 3.1. Математические функции 37 3.2. Функции вычисления пересечений 39 3.3. Функции вычисления длин, расстояний, углов 40 4. РАБОТА С БАЗАМИ ДАННЫХ 43 5. ПРИМЕРЫ ПРОЕКТИРОВАНИЯ БИБЛИОТЕК В 2D 47 5.1. Построение графиков функций 47 5.2. Построение фигур 51 5.3. Построение эскизов 59 6. БАЗОВОЕ ТВЕРДОТЕЛЬНОЕ МОДЕЛИРОВАНИЕ ОБЪЕКТОВ В КОМПАС 3D 66 6.1. Построение твердотельных деталей посредством операций вращения и выдавливания67 ЗАКЛЮЧЕНИЕ 78 БИБЛИОГРАФИЧЕСКИЙ СПИСОК 79 4 ВВЕДЕНИЕ На данном этапе функционирования производственного комплекса доминирующими факторами развития научно-технического прогресса является повышение качества и сроков изготовления продукции. Высокие темпы научно-технического прогресса должны обеспечиваться разработкой, производством и массовым применением высокоэффективных машин, оборудования, приборов и технологических процессов. Объективным препятствием повышению качества проектов и сокращению сроков их разработки является несоответствие между сложностью объектов конструирования и устаревшими методами, и средствами их проектирования. Автоматизация проектирования особенно эффективна, когда от автоматизации выполнения отдельных инженерных расчетов переходят к комплексной автоматизации, создавая для этой цели системы автоматизированного проектирования (САПР). Как и другие направления автоматизированных систем, САПР технологии являются развивающимися проектами. Технический прогресс в соответствующей отрасли должен сопровождаться непрерывным обновлением в САПР математических моделей, нормативов, данных о материалах комплектующих изделий. САПР создается и функционирует в проектной организации как самостоятельная система. Она может быть связана с подсистемами и банками данных других автоматизированных систем. Системы автоматизированного проектирования имеют свои специфические особенности, принципы создания и развития, создаются в проектных, конструкторских, технологических организациях в целях: - повышения качества и технико-экономического уровня проектируемой и выпускаемой продукции; - повышения эффективности и надежности объектов проектирования, уменьшения затрат на их создание и эксплуатацию; - сокращения сроков, уменьшения трудоемкости проектирования и повышения качества проектной документации. Достижение целей создания САПР обеспечивается путем: 5 - совершенствования систематизации и унификации процессов проектирования на основе применения математических методов и средств вычислительной техники; - комплексной автоматизации проектных работ в проектной организации с необходимой перестройкой ее структуры и кадрового состава; - повышения качества управления проектированием; - применения эффективных математических моделей проектируемых объектов, комплектующих изделий и материалов; - использования методов многовариантного проектирования и оптимизации; - автоматизации трудоемких и рутинных проектных работ; - замены натурных испытаний и макетирования математическим моделированием. Автоматизация систем твердотельного моделирования заключается посредством создания отдельных модулей в виде программного обеспечения (ПО), расширяющие или позволяющие реализовать новые научно-технические задачи, касающиеся конкретной машиностроительной отрасли. Комплекс автоматизации системы КОМПАС 3D позволяет решать ряд поставленных задач путем включения в указанный программный продукт набора библиотек готовых элементов и схем, отвечающих требованиям машиностроительных отраслей, а также предоставить разработчикам (пользователям) инструментальные средства проектирования приложений (библиотек элементов, прикладных САПР) на базе КОМПАС. Создание дополнительных модулей с использованием программных интерфейсов КОМПАС позволяет обеспечить гибкий подход к задачам проектирования отдельного предприятия, учитывая его специфику работы. Таким образом обеспечивается более глубокая кастомизация при внедрении подобного рода программных продуктов линейки средств автоматизированного проектирования компании Аскон. Под библиотекой в системе КОМПАС понимается законченное приложение, решающее инженерную расчетно-графическую задачу, используя группу команд, предложенную разработчиком данной системы (API). Библиотеки реализуются в виде отдельных файлов, имеющие расширение «.rtw». По своей конструкции, с программной точки зрения, библиотеки 6 идентичны динамически подключаемым компонентам «.dll» в операционных системах MS Windows. Как известно, разрабатывать компоненты для операционной системы можно на любом языке программирования. Разработчики КОМПАС подготовили API и представили ряд примеров на известных языках программирования (Delphi, Visual Basic, C#, C++). Комплект документации с примерами носит название SDK и находится в директории с программой в одноименном каталоге «..\SDK». Система КОМПАС включает в свой состав 2D и 3D API. 2D API обеспечивает доступ к системе КОМПАС для формирования и обработки двумерных графических документов. 3D API обеспечивает доступ к системе КОМПАС для создания и редактирования трехмерных моделей. В пособии будут рассмотрены методы использования и приемы реализации с API 2D и даны рекомендации к проектированию в 3D для Visual C++, Visual Studio.NET (2013-2019), включая версии Express. Среды для подключения библиотек – Компас 3D. Все версии Компас, начиная с 2011 года, используют универсальный набор символов (UNICODE), представленный в виде двухбайтовой конструкции элементов. Такой подход позволяет применять национальные раскладки по набору символов вместо одного байта информации (ASCII), поэтому разработанные библиотеки в версии КОМПАС 9 и более ранних продуктах должны быть скомпонованы с учетом внесения соответствующих изменений в тексте программы прикладной библиотеки. Например, вывод сообщений в средах программирования на языке С++ для версии 9 имеет формат «::Message(buf);» , а для версий 10 -13 – «MessageT(_T("buf"));» 7 1. СОЗДАНИЕ ПРОЕКТОВ ПРИКЛАДНЫХ БИБЛИОТЕК КОМПАС В СРЕДЕ VISUAL C++ Создать прикладную библиотеку и подготовить ее к работе в системах КОМПАС можно двумя способами: воспользоваться мастером создания библиотек Visual C++ или изменить имеющиеся в директории «..\SDK\C++\ Visualc» рабочие проекты прикладных библиотек. Создание шаблона библиотеки при помощи мастера создания библиотек (Wizard), разработанного специалистами системы КОМПАС, производится легко - достаточно следовать инструкциям разработчика. Для подключения мастера создания библиотек необходимо скопировать файл LibraryWizard.awx в директорию «C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Template» или в папку Template аналогичной директории куда установлен MS Visual C++. После подключения мастера создания библиотек в окне нового проекта появиться новый пункт LibraryWizard. Пути к заголовкам библиотек (Include директориям) в опциях нового проекта по умолчанию настроены для папки «..\SDK\C++\Visualc», поэтому при создании проекта необходимо указать этот путь в location, как показано на рисунке 1. Рис. 1. Мастер создания прикладных библиотек системы КОМПАС в Visual C++ Используя опции генератора данных, мастер подготовит проект подключаемой для системы КОМПАС динамической библиотеки в среде Visual С++. 8 Пример кода на Visual С++ динамически подключаемой прикладной библиотеки с именем my_first_library представлен на листинге: // My_first_library.cpp - Библиотека на Visual C++ #include "stdafx.h" #include <afxdllx.h> #include "my_first_library.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // Специальная структура, используемая для инициализации DLL // --static AFX_EXTENSION_MODULE My_first_libraryDLL = { NULL, NULL }; HINSTANCE g_hInstance = NULL; IApplicationPtr newKompasAPI( NULL ); void OnProcessDetach();// Отключение библиотеки // Стандартная точка входа // Инициализация и завершение DLL // --extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { g_hInstance = hInstance; if (dwReason == DLL_PROCESS_ATTACH) { TRACE0("MY_FIRST_LIBRARY.AWX Initializing!\n"); AfxInitExtensionModule(My_first_libraryDLL, hInstance); new CDynLinkLibrary(My_first_libraryDLL); } else if (dwReason == DLL_PROCESS_DETACH) { TRACE0("MY_FIRST_LIBRARY.AWX Terminating!\n"); OnProcessDetach(); AfxTermExtensionModule(My_first_libraryDLL); } return 1; // ok } 9 // Получить доступ к API void GetNewKompasAPI() { if ( !( IApplication * )newKompasAPI ) { CString filename; if( ::GetModuleFileName(NULL, filename.GetBuffer(255), 255) ) { filename.ReleaseBuffer( 255 ); CString libname; libname = LoadStr( IDR_API7 ); // kAPI7.dll filename.Replace( filename.Right(filename.GetLength() (filename.ReverseFind('\\') + 1)), libname ); HINSTANCE hAppAuto = LoadLibrary( filename ); // идентификатор kAPI7.dll if( hAppAuto ) { // Указатель на функцию возвращающую интерфейс KompasApplication typedef LPDISPATCH ( WINAPI * FCreateKompasApplication )(); FCreateKompasApplication pCreateKompasApplication = (FCreateKompasApplication)GetProcAddress( hAppAuto, "CreateKompasApplication" ); if ( pCreateKompasApplication ) newKompasAPI = IDispatchPtr ( pCreateKompasApplication(), false ); // Получаем интерфейс Application FreeLibrary( hAppAuto ); }}}} // Задать идентификатор ресурсов unsigned int WINAPI LIBRARYID() {return IDR_LIBID;} // Головная функция библиотеки void WINAPI LIBRARYENTRY( unsigned int comm ) { switch ( comm ) { case 1: { // Выдача сообщения пользователю MessageT( _T("Успешный запуск прикладной библиотеки!") ); break; }}} // Завершение приложения void OnProcessDetach() { newKompasAPI = NULL; } // Загрузить строку из ресурса CString LoadStr( int strID ) { TCHAR temp[_MAX_PATH]; LoadString( My_first_libraryDLL.hModule, strID, temp, _MAX_PATH ); return temp; } 10 Аналогичный код на Delphi приведен в следующем листинге: library Vtulka; uses SysUtils, Classes, Forms, Unit1 in 'Unit1.pas' {Form1}; {$E rtw} {$R *.res} procedure Initialize(); begin try if Application = nil then // Если объект приложение удалён, то создаём заново Application := TApplication.Create(nil); if Application <> nil then begin // Поизводим его инициализацию Application.Initialize; // Создаём форму Application.CreateForm(TForm1, Form1); // Запускаем приложение Application.Run; // После завершения работы приложения освобождаем Application.Free(); Application := nil; end; except if Application <> nil then begin // Если есть исключения, то завершаем приложение Application.Terminate; Application.Free(); Application := nil; end; end; end; (*****************************************************) function LibraryName(): PChar; pascal; begin // Возвращаем имя приложения Result := PChar('Штуцер'); end; (*****************************************************) function LibraryId(): LongWord; pascal; begin // Возвращаем идентификатор библиотеки Result := 1000; end; (*****************************************************) procedure LibraryEntry(command: WORD); pascal; begin // При вызове входной функции инициализируем приложение Initialize(); end; (*****************************************************) exports LibraryName name 'LIBRARYNAME', LibraryId name 'LIBRARYID', LibraryEntry name 'LIBRARYENTRY'; begin end. 11 Для успешной компиляции и создания рабочего модуля библиотеки необходимо в файле «StdAfx.h» указать путь к директории, в которой находятся требуемые для успешной сборки проекта файлы (выделены жирным шрифтом). В среде разработки подключить заголовки (headers) c системными библиотеками (lib) SDK -в Visual C++6.0 «Tools->Options->Directories» и в разделе «Show directories for: Include files (Library files)» указать путь к соответствующим файлам, как показано на рисунке 2. #if !defined(AFX_STDAFX_H__6D497DCE_3F78_47BD_915C_D3B34AF32D89__INCLUDED_) #define AFX_STDAFX_H__6D497DCE_3F78_47BD_915C_D3B34AF32D89__INCLUDED_ #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers #include <afxwin.h> // MFC core and standard components #include <afxext.h> // MFC extensions #include <afxcmn.h> // MFC support for Windows 95 Common Controls #include <COMUTIL.H> #include <comdef.h> #pragma warning( disable : 4192 ) #include <libtool.h> #include <LHead3d.h> #import "g:\works2010\SDK\lib\ksConstants3D.tlb" no_namespace named_guids #import "g:\works2010\SDK\lib\ksConstants.tlb" no_namespace named_guids #import "g:\works2010\SDK\lib\kAPI2D5COM.tlb" no_namespace named_guids #import "g:\works2010\SDK\lib\kAPI3D5COM.tlb" no_namespace named_guids #import "g:\works2010\SDK\lib\kAPI7.tlb" no_namespace named_guids #pragma warning( once : 4192 ) #endif // !defined(AFX_STDAFX_H__6D497DCE_3F78_47BD_915C_D3B34AF32D89__INCLUDED_) 12 Рис. 2. Подключение заголовков и прикладных библиотек системы КОМПАС в Visual C++ При «ручном» способе разработки прикладных библиотек может потребоваться внесение некоторых модулей из папки «..SDK\Lib» непосредственно в дерево построения проекта (WorkSpace) (рисунок 3). При сборке библиотеки имеется возможность воспользоваться опциями управления проекта (Project->Settings->C++&Links& Resources) для изменения производительности программного кода, обеспечения его компактности, включения в раздел ресурсов национальной таблицы символов, отличных от латинских, изменение имени конечного файла (рисунок 4). При окончательной сборке библиотеки необходимо поменять в опции «Активная конфигурация» режим «Debug» на «Release»-это действие приведет к уменьшению объема выходного файла динамически подключаемого приложения за счет удаления отладочной информации о проекте (Build->Set Active Configuration). 13 Рис. 3. Включение в проект файлов kAPI2D5.lib и kAPI3D5.lib для работы с чертежами и моделями Рис. 4. Настройки проекта: изменение имени файла прикладной библиотеки Полученный шаблон прикладной библиотеки достаточно просто перенести на другие среды разработки компании Microsoft-так, например, в версии Visual Studio 2010. NET необходимо переоткрыть проект, войти в раздел Property Manager (Менеджер разработки текущего проекта) и явным образом задать пути к папкам API SDK, содержащие разделы с lib (библиотеки разработки) и include (заголовки исполняемых функций) файлами. Все вышеописанные действия представлены на рисунке 5. 14 Рис. 5. Сборка проекта в Visual Studio2010. Из приведенного выше примера большая часть кода представлена системным механизмом проектирования приложений, в котором реализованы общие принципы построения динамически подключаемых библиотек посредством технологии СОМ - наиболее широко используемой объектной модели для разработки рассредоточенных и действующих одновременно систем. Термин "СОМ" представляет собой сокращение фразы Competent Object Model - компонентная объектная модель. Основой указанной технологии является некотороя особенность, состоящая в том, что программы строятся из блоков, которые, в свою очередь, состоят из объектов. Само по себе это обстоятельство не является нововедением в области программостроения модульная архитектура и объектно-ориентированный подход к построению программ являются признанными стандартами достаточно давно. Особенностью является то, что представляют собой данные компоненты и объекты – в качестве блоков выступает непосредственно исполняемый двоичный код. Не "включаемые исходные тексты" компилируемые совместно с проектом, не "библиотеки стандартных программ", присоединяемые линкером, а непосредственно исполняемые файлы, которые никак не надо "связывать" со своим проектом - их достаточно зарегистрировать в операционной системе и они будут доступны любой программе исполняющейся на данной машине. Т.е. 15 их использование в своей программе производится "без использования операций сборки модуля". Такая технология не является новой и называется "динамическая загрузка", она давно известна и её преимущества очевидны. А модули, которые позволяют загружать себя таким образом, называются динамически подключаемыми библиотеками (DLL). И в системе, Windows такая технология известна с момента ее создания. DLL и есть тот самый "двоичный исполняемый модуль", который может быть присоединен к программе лишь на стадии её выполнения. Однако, если просто весь проект распределить по нескольким динамическим библиотекам, то "двоичные компоненты" не получатся потому что, важнейший признак "компонентности" уже появится - исполняемую программу можно будет собирать из отдельных частей без операций сборки модуля. Но вот DLL - не компонента, DLL есть так называемое место нахождения компонент, используемых в программе. Из программы вызываются вполне конкретные процедуры и функции, которые только расположены в DLL. Кроме того, вызовы процедур "из своего модуля" и "из DLL" - не одинаковые действия. Вызов процедуры, которая располагается внутри "своего" модуля требует знания только имени этой процедуры, а если процедура располагается в DLL, то нужно знать ещё и имя самой библиотеки. Модель же COM позволяет этого "не знать", т.е. вызов объектов COM из своей программы осуществляется без знания того, где они расположены. Достаточно знать имя объекта. Другое отличие COM, уже от привычных объектов в стиле объектно-ориентированного программирования (ООП), состоит в том, что объекты ООП известны только компилятору. Это - абстракции, в которых работает программист и которые компилятор превращает в двоичные структуры "данные + код". Объекты ООП существующие в разных единицах компиляции и, тем более, помещенные в разные двоичные модули, ничего не могут друг о друге "знать" просто потому, что их там нет и никогда не было. Не случайно заголовочные файлы, содержащие описания всех объектов проекта, подаются на вход именно компилятора - потом они уже никому не нужны. Объекты же COM - действительно существуют в двоичном виде как объекты. И в таком качестве “известны” всем приложениям, которым необходим доступ к элементам этих объектов. Возвращаясь к процессу проектирования библиотек, рассмотрим некоторые элементы программного кода на языке С++. В простейшем варианте 16 в прикладной библиотеке содержится одна базовая функция, представленная на листинге ниже и выводящая сообщение на экран. void WINAPI LIBRARYENTRY( unsigned int comm ) { switch ( comm ) { case 1: { //Выдача сообщения пользователю MessageT( _T("Тестовая команда 1") );break; } } } В функцию WINAPI LIBRARYENTRY включен множественный оператор выбора switch(), по которому можно организовать вызов отдельного набора команд, составленных на языке С++ и API системы КОМПАС, функций, членов классов, структур, шаблонов, добавление в библиотеку вставок текста на языке ассемблера и т.д. Листинг основной функции по расчету факториала, написанной на языке ассемблера: void WINAPI LIBRARYENTRY( unsigned int comm ) { TCHAR buf [255]; WORD iii; __asm { mov ax,1 xor bx,bx mov cx,8 label1: inc bx mul bx loop label1 mov iii,ax }; _stprintf( buf, _T("Factorial = %d"), iii ); MessageT( buf ); } Сообщение выводится на экран по команде «MessageT(buf);», где каждый символ представлен двухбайтовым значением и соответствует национальной таблице символов в Unicode. Использование Unicode требует коррекции функций и типов переменных как минимум в функциях, использующих MFC. Строковые константы в коде необходимо окружить дефайном _T, например: «char str[100]=“”;» заменяется на «TCHAR str[100]=_T(“”);». Таким образом, проект можно будет компилировать под Компас 10 в Unicode. В случае разработки библиотек под систему Компас 9 надо переключиться на неюникодную конфигурацию. Потребуется замена вызова неюникодных функций, работающих со строками на объявления, которые в зависимости от типа компиляции заменяются на юникодный или неюникодный аналог функции. Например: 17 strcmp strcpy atof. Данные функции в местах, где будет использоваться TCHAR*, надо заменить объявлениями из файла TCHAR.h. Примеры замен необходимо уточнить в документации. Вывод текстовых сообщений может быть выполнен не только с помощью специфического API КОМПАС, но и средствами разработки WinAPI, MFC, которые реализованы в интегрированной среде Visual C++: Пример: MessageBox(NULL,_T("Сообщение"),_T("Пример вывода"),MB_OK); AfxMessageBox(_T("Сообщение"),MB_ICONINFORMATION ,0); Для того чтобы перевести листинг программы в машинный код, необходимо выполнить компиляцию проекта, выбрав опцию «Build» в меню интегрированной среды, или нажать функциональную клавишу F7. Полученный файл с расширением .rtw можно подключить в окне менеджера библиотек Компас путем добавления описания прикладной библиотеки, как показано на рисунке 6. Рис. 6. Подключение разработанной прикладной библиотеки в окне менеджера библиотек Компас Результаты спроектированной библиотеки в Visual Studio 2010 представлены на рисунке 7, когда модуль уже подключен к менеджеру библиотек в Компас V12. 18 Рис. 7. Вывод сообщения средствами спроектированной прикладной библиотеки 19 2. РАБОТА С ГРАФИЧЕСКИМИ ОБЪЕКТАМИ НА ПЛОСКОСТИ Создание объектов на плоскости в КОМПАС осуществляется посредством вызова последовательности команд, представляющих собой API набора экспортных методов и классов. Ряд функций будет рассмотрен непосредственно в практических примерах проектируемых прикладных библиотек, приведенных далее по тексту, описания и примеры использования остальных команд можно взять из комплекта документации SDK, входящего в состав дистрибутива системы КОМПАС. Если документация в виде отдельной подпапки отсутствует в Вашей конфигурации, возможно, придется произвести повторную установку ПО КОМПАС и включить модуль с комплектом документации, информационной поддержкой, а также с примерами. В общем случае, спроектированная библиотека работает с новым или открытым документом, статус которого объявлен как активный (исключение составляют библиотеки расчетного уровня, использующие свои диалоговое окна ввода-вывода). В системе КОМПАС 3D доступны к разработке программным способом следующие документы: - чертеж; - фрагмент; - текстовый документ; - спецификация; - сборка; - деталь. В ряде случаев быстрее и проще создать нужный тип документа непосредственно в CAD/CAM системе, а потом пользоваться разработанной библиотекой. Такой подход будет использоваться в последующих примерах при изучении ряда функций. Однако в некоторых задачах требуется выбрать и создать определенный тип документа. Процесс такого создания документа, имеющего статус чертежа, в котором выполнены простейшие геометрические построения, приведен далее. Пример создания графического документа: 20 #include "stdafx.h" #include <afxdllx.h> #include "resource.h" #include <libtool.h> #include <ldefin2d.h> #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // Специальная структура используемая при инициализации DLL static AFX_EXTENSION_MODULE StepDLL = { NULL, NULL }; // Стандартная точка входа // Инициализация и завершение DLL extern "C" int APIENTRY DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved ) { UNREFERENCED_PARAMETER( lpReserved ); if ( dwReason == DLL_PROCESS_ATTACH ) { TRACE0( "DLL Initializing!" ); if ( !AfxInitExtensionModule( StepDLL, hInstance ) ) return 0; new CDynLinkLibrary( StepDLL ); } else if ( dwReason == DLL_PROCESS_DETACH ) { TRACE0( "DLL Terminating!" ); AfxTermExtensionModule( StepDLL ); } return 1; } // Задать идентификатор ресурсов unsigned int WINAPI LIBRARYID() { return IDR_LIBID; } // Описания используемых функций void WorkDocument(); // Головная функция библиотеки void WINAPI LIBRARYENTRY( unsigned int comm ) 21 { //Прототип вызываемой функции //по работе с документом WorkDocument(); } // Работа с документом void WorkDocument() { //Заполнение структуры создаваемого документа DocumentParamT DocsStruct; TCHAR str[]=_T("Чижов М.И.,Паринов М.В.,Рыжков В.А., Юров А.Н."); //Определение имени проекта lstrcpy( DocsStruct.fileName, _T("c:\\FirstDoc.cdw") ); //Комментарий к документу lstrcpy( DocsStruct.comment,_T("Документ создан в ознакомительных целях")); //Информация о создателе lstrcpy( DocsStruct.author, str); //Режим отображения документа: 0 - видимый, 1 - скрытый DocsStruct.regim = 0; //Тип документа - чертеж стандартный DocsStruct.type = lt_DocSheetStandart; //Формат листа 0( А0 ) ... 4( А4 ) DocsStruct.sheet.stPar.format = 4; //Кратность формата DocsStruct.sheet.stPar.multiply = 1; //Расположение штампа DocsStruct.sheet.stPar.direct = 0; //Тип штампа из указанной библиотеки для спецификации DocsStruct.sheet.shtType = 1; //Имя библиотеки оформления (Graphic.lyt) DocsStruct.sheet.layoutName[0] = _T('\0'); //Создаем документ формата А4 reference rDocument = CreateDocumentT( &DocsStruct ); //Определим константы для расположения //для позиционирования треугольника на плоскости const double x_pos=50; const double y_pos=150; //Отрисовка контрольных точек Point (0+x_pos, 0+y_pos, 1); Point (50+x_pos, 67+y_pos, 1); Point (100+x_pos, 10+y_pos, 1); //Отрисовка сторон треугольника LineSeg( 0+x_pos, 0+y_pos, 50+x_pos, 67+y_pos, 1 ); LineSeg( 50+x_pos, 67+y_pos, 100+x_pos, 10+y_pos, 1 ); LineSeg( 100+x_pos, 10+y_pos, 0+x_pos, 0+y_pos, 1 ); //Сохраним документ SaveDocument( 0, "c:\\FirstDoc.cdw" ); // Закрыть документ //CloseDocument( rDocument ); } 22 Рис. 8. Сборка и компоновка прикладной библиотеки в интегрированной среде разработки Microsoft Visual Studio 2010 Разработка библиотеки была выполнена в среде Visual Studio 2010, включала ряд файлов, кроме исходного кода, которые требовались для подключения вспомогательных средств и хранения ресурсов приложения. Среда разработки представлена на рисунке 8. Листинг прикладной библиотеки подробно прокомментирован в исходном коде, однако ряд моментов следует рассмотреть подробнее. В основной части управления проектом «void WINAPI LIBRARYENTRY(unsigned int comm)» имеется единственная функция WorkDocument(), в которой изложены основы создания и управления параметрами документа. Для того, чтобы вывести на экран рабочее поле чертежа (фрагмента), необходимо заполнить значениями ряд разделов структуры DocumentParamT с последующим отображением документа на экране ЭВМ посредством следующей команды CreateDocumentT. В языке С++ структурой называется составной тип данных, который состоит из элементов разных типов. В API КОМПАС понятие структуры носит аналогичный характер, поэтому работа с типами данных осуществляется по тем же принципам. Формат структуры параметров документа DocumentParamT: regim –режим (0-видимый, 1-невидимый); fileName- имя файла документа; comment- комментарий к документу; author- автор документа; 23 type- тип документа. Типы в системе КОМПАС могут принимать следующие значения: -lt_DocSheetStandart- чертеж стандартного формата (1) ; -lt_DocSheetUser- чертеж нестандартного формата (2) ; -lt_DocFragment- фрагмент (3) ; -lt_DocSpc- спецификация (4) ; -lt_DocPart3D- деталь(5) ; -lt_DocAssemble3D- сборка(6) ; -lt_DocTxtStandart- текстовый документ стандартный (7) ; -lt_DocTxtUser- текстовый документ нестандартный (8); -lt_DocSpcUser- спецификация - нестандартный формат (9). sheet- Структура параметров оформления. Компоненты данной структуры отвечают за формат листа, кратность формата, расположение штампа, тип штампа и прочие. После создания документа можно приступить к проектированию. В примере приведен вариант построения треугольника с помощью графических примитивов: LineSeg -создание отрезка прямой линии и Point -создание точки. Формат команды LineSeg следующий: reference LineSeg (double x1, double y1,double x2,double y2, unsigned int style) где, x1, y1- координаты первой точки отрезка; x2, y2- координаты второй точки отрезка; style. Параметр style может иметь следующие значения для выбора системного стиля линии: 1 - основная линия; 2 - тонкая линия; 3 - осевая линия; 4 - штриховая линия; 5 - для линии обрыва; 6 - вспомогательная линия; 7 - утолщенная; 8 - штрихпунктирная линия с двумя точками; 9 - штриховая толстая линия; 10 - осевая толстая линия; 24 11 - тонкая линия, включаемая в штриховку; 12 - ISO штриховая линия; 13 - ISO штриховая линия (дл. пробел); 14 - ISO штрихпунктирная линия (дл. штрих); 15 - ISO штрихпунктирная линия (дл. штрих 2 пунктира); 16 - ISO штрихпунктирная линия (дл. штрих 3 пунктира); 17 - ISO пунктирная линия; 18 - ISO штрихпунктирная линия (дл. и кор. штрихи); 19 - ISO штрихпунктирная линия (дл. и 2 кор. штриха) ; 20 - ISO штрихпунктирная линия; 21 - ISO штрихпунктирная линия (2 штриха); 22 - ISO штрихпунктирная линия (2 пунктира); 23 - ISO штрихпунктирная линия (3пунктира); 24 - ISO штрихпунктирная линия (2 штриха 2 пунктира); 25 - ISO штрихпунктирная линия (2 штриха 3 пунктира). Формат команды Point следующий: reference Point (double x, double y, unsigned int style), где, x,y-координаты построения точки; style. Параметр style может иметь следующие значения: 0 – точка; 1 – перекрестие; 2 – х-точка; 3 – квадрат; 4 – треугольник; 5 – окружность; 6 – звезда; 7 – перечеркнутый квадрат; 8 – утолщенный плюс. Запись документа на логический раздел физического накопителя осуществляется командой SaveDocument путем указания рабочего пути для сохранения данных, а завершение работы с документом реализуется вызовом инструкции «CloseDocument». Результат работы созданной прикладной библиотеки показан на рисунке 9. 25 Рис. 9. Создание чертежа программным способом средствами API системы КОМПАС 2.1. Функции для работы с графическими документами В предыдущем разделе были рассмотрены команды, отвечающие за построение отрезков и точек, относящиеся к простейшим геометрическим примитивам. Дополнительный набор команд, отвечающий за геометрические построения в системе КОМПАС, позволяет подготовить графический документ любого уровня сложности, хотя на программном уровне такое решение вопроса не всегда является тривиальным. Далее будут рассмотрены некоторые графические функции с описанием внутренней структуры и приведены примеры их использования в разрабатываемых прикладных библиотеках. Команда PointArraw позволяет отобразить значок в графическом документе. Формат команды следующий: PointArraw (double x, double y, double ang, unsigned char term) где, x,y- координаты точки привязки значка; ang- угол поворота значка; term-тип стиля отображения. Стиль представлен целочисленным типом, который может принимать следующие значения: 0- без значка; 1- стрелка изнутри; 26 2- стрелка снаружи; 3- засечка с продолжением кривой (с "хвостиком"); 4- верхняя половина стрелки изнутри; 5- нижняя половина стрелки изнутри; 6- большая (7 мм) стрелка изнутри; 7- стрелка для размера высоты 8- (штрихи длиной 4 мм, расположенные под углом 45 градусов) ; 9- треугольник по направлению кривой; 10окружность радиусом 2 мм тонкой линией; 11обозначение фиктивного центра в виде большого "креста"; 12знак склеивания; 13знак пайки; 14знак сшивания; 15знак соединения внахлестку металлическими скобами; 16знак углового соединения металлическими скобами; 17знак монтажного шва; 18засечка без продолжения кривой (без "хвостика"); 19треугольник по текущей СК - для базы; 20закрытая стрелка изнутри; 21закрытая стрелка снаружи; 22открытая стрелка изнутри; 23открытая стрелка снаружи; 24стрелка 90 град. изнутри; 25стрелка 90 град. снаружи; 26точка; 27точка маленькая. Пример использования: PointArraw (50,100,90,20); Результат работы функции показан на рисунке 10. Рис. 10. Построение элемента с помощью команды PointArraw Команда Line позволяет вывести на экран прямую линию, проходящую через указанную точку под некоторым углом. Формат команды следующий: 27 Line (double x, double y, double ang), где x,y-координаты точки; ang- угол наклона прямой. Пример использования: Line (50,100,20); Результат выполнения представлен на рисунке 11. Рис. 11. Построение элемента с помощью команды Line Команда ksRegularPolygon позволяет создать правильный многоугольник с заданными параметрами. Формат команды следующий: reference ksRegularPolygon (RegularPolygonParam * par, unsigned char centre) где, par-указатель на структуру параметров правильного многоугольника, подлежащих обязательному заполнению: count- количество вершин многоугольника; xc, yc- центр вписанной или описанной окружности; ang- угол радиус-вектора, направленного от центра к первой вершине; radius- радиус вписанной или описанной окружности; describe- признак описанного или вписанного многоугольника (0 вписанный многоугольник, 1 -описанный многоугольник); style- стиль линии; pCorner- динамический массив CORNER_ARR структур параметров скругленных (или усеченных) углов CornerParam (указатель на структуру CornerParam можно не заполнять-параметры будут занесены автоматически); centreпризнак построения обозначения центра: 0- нет осей; 1- значок осей (маленький "крест"); 2- горизонтальная ось; 3- обе оси. Пример использования: RegularPolygonParam par; par.count=9; par.xc=10; par.yc=80; par.ang=0; par.radius=40; par.describe=0; par.style=1; par.pCorner = ::CreateArray (CORNER_ARR, 0); ksRegularPolygon(&par,3); 28 Результат выполнения представлен на рисунке 12. Рис. 12. Построение элемента с помощью команды ksRegularPolygon Команда ksRectangle позволяет построить прямоугольник. Формат команды следующий: reference ksRectangle (RectangleParam * par, unsigned char centre) где, par-указатель на структуру параметров прямоугольника: x,y-координаты базовой точки прямоугольника - одной из его вершин; ang-угол наклона стороны прямоугольника, выходящей из базовой точки; height- высота прямоугольника; width (в документации опечатка: wight-вес) - ширина прямоугольника длина стороны, характеризующейся углом наклона ang, style- стиль линии; pCorner-динамический массив CORNER_ARR структур параметров скругленных (или усеченных) углов CornerParam; centreпризнак построения обозначения центра: 0- нет осей; 1- значок осей (маленький "крест"); 2- горизонтальная ось; 3- обе оси. Пример использования: RectangleParam par; par.x=10; par.y=100; par.ang=5; par.height=30; par.width=60; par.style=1; par.pCorner = ::CreateArray (CORNER_ARR, 0); ksRectangle (&par,2); Результат выполнения представлен на рисунке 13. Рис. 13. Построение элемента с помощью команды ksRectangle Команда ksParEllipseArc позволяет выполнить построение дуги эллипса. Формат команды следующий: reference ksParEllipseArc (EllipseArcParam1 *par) где, 29 par - указатель на структуру параметров дуги: xc, yc- координаты центра эллипса; a,b-длина полуосей эллипса; ang- угол наклона полуоси a к оси OX; parFirst- начальное значение параметра; parSecond- конечное значение параметра; dir- направление построения дуги; style- стиль линии. Пример использования: EllipseArcParam1 par; par.xc=10; par.yc=100; par.a=10; par.b=30; par.ang=90; par.parFirst=10; par.parSecond=50; par.dir=0; par.style=1; ksParEllipseArc (&par); Результат выполнения представлен на рисунке 14. Рис. 14. Построение элемента с помощью команды ksParEllipseArc Команда ksInsertRaster вставить растровый объект. Для того, чтобы команда была успешно выполнена, необходимо разместить графический файл на диске с указанием рабочего пути к нему. Системой поддерживаются следующие форматы файлов: GIF, BMP, JPG, TIF, PNG, TGA и другие. Формат команды следующий: ksInsertRaster (RasterParam *par) где, par - указатель на структуру параметров: xBase,yBase- координаты базовой точки в СК вида; scale- масштаб; ang- угол поворота в СК вида; fileName-полный путь к файлу. Задать путь можно с помощью команды в режиме совместимости ::strcpy, lstrcpy использует только юникодную конфигурацию, которая в данной структуре не поддерживается. Пример использования: 30 RasterParam par; par.place.xBase = 0; par.place.yBase = 200; par.place.ang = 0; par.place.scale = 1; ::strcpy(par.fileName,"c:\\image.tif"); ksInsertRaster (&par); Результат выполнения представлен на рисунке 15. Рис. 15. Построение элемента с помощью команды ksInsertRaster. Формат файла с расширением TIF Команда ksHatch позволяет заштриховать указанную область. Формат команды следующий: reference ksHatch (HatchParam * par) где, style- стиль штриховки; ang- угол штриховки; step- шаг штриховки; width- ширина полосы штриховки (0 - штриховать всю область); x, y- координаты базовой точки; pBoundaries- временная группа - границы штриховки. Системные стили штриховки (параметр style) определены следующим образом: 0-металл; 1- неметалл; 2-дерево; 3- камень естественный; 4- керамика; 5- бетон; 6- стекло; 7- жидкость; 8- естественный грунт; 9- насыпной грунт; 10- камень искусственный; 11- железобетон; 12- напряженный железобетон; 13- дерево в продольном сечении; 14- песок. 31 Пример использования (рассмотрен альтернативный вариант работы с элементом Hatch без описания структуры): // Штриховка квадрата Hatch( 2,45,3,0,0,100); //Контур для штриховки LineSeg (0,100,50,100,1); LineSeg (50,100,50,140,1); LineSeg (50,140,0,140,1); LineSeg (0,140,0,100,1); reference rHatch = EndObj(); Результат выполнения представлен на рисунке 16. Рис. 16. Построение элемента с помощью команды Hatch Команда ksEllipse позволяет построить эллипс с заданными параметрами. Формат команды следующий: reference ksEllipse (EllipseParam *par) где, xc,yc- координаты центра эллипса; a, b- длина полуосей эллипса; ang- угол наклона оси а эллипса к оси X; style- стиль линии. Системные стили линий (style) ksEllipse аналогичны стилям команды LineSeg. Пример использования: EllipseParam par; par.xc = 20; par.yc = 20; par.a = 30; par.b = 10; par.ang = 45; par.style = 1; reference p = ksEllipse(&par); Результат выполнения представлен на рисунке 17. Рис. 17. Построение элемента с помощью команды ksEllipse Команда Circle строит окружность с заданными параметрами. Формат команды следующий: 32 reference Circle (double xc, double yc, double rad, int type) где, xc, yc- координаты центра окружности; rad- радиус окружности; type- стиль линии (см. стили LineSeg). Пример использования: Circle(0,100,50,1); Результат выполнения представлен на рисунке 18. Рис. 18. Построение элемента с помощью команды Circle Команда ksConicArc позволяет построить коническое сечение. Формат команды следующий: reference ksConicArc (ConicArcParam * par) где, A, B, C, D, E, F- коэффициенты канонического уравнения; x1, y1- координаты начальной точки; x2, y2- координаты конечной точки; style- стиль линии (см. стили LineSeg). Пример использования: ConicArcParam par; par.A = 16; par.B = 0; par.C = 9; par.D = 0; par.E = 0; par.F = -144; par.x1 = 2.5; par.y1 =5; par.x2 = -2.5; par.y2 = 5; par.style = 1; ksConicArc(& par); Результат выполнения представлен на рисунке 19. Рис. 19. Построение элемента с помощью команды ksConicArc Команда ArcByPoint производит построение дуги по центру и конечным точкам. Формат команды следующий: 33 ArcByPoint (double xc, double yc, double rad, double x1, double y1, double x2, double y2, short direction, unsigned short style) где, xc, yc- координаты центра дуги; rad- радиус дуги; x1, y1- координаты начальной точки дуги; x2, y2- координаты конечной точки дуги; direction- направление отрисовки дуги: 1 - против часовой стрелки, -1 - по часовой стрелке; type-стиль линии (см. стили LineSeg). Пример использования: const double n=50; ArcByPoint (n,0+n,n,0,n,2*n,n,-1,1 ); Результат выполнения представлен на рисунке 20. Рис. 20. Построение элемента с помощью команды ArcByPoin 2.2. Функции построения составных объектов В системе Компас разработчиками определены функции, позволяющие осуществлять манипуляции с рядом графических примитивов для достижения требуемых задач. К таким задачам относится построение таблиц и контуров графических объектов. Построение контура осуществляется посредством команды Contour. Формат команды следующий: int Contour (unsigned short style) где, style-стиль линии (см. стили LineSeg). Требования для реализации команды: -все определяемые далее до вызова функции EndObj геометрические примитивы чертежа (отрезки, дуги, кривые) будут включены в контур; -контур должен быть непрерывным; 34 -начальная точка очередного объекта обязана совпадать с конечной точкой предыдущего. Полученный контур может быть использован для построения эквидистанты. Функция EndObj возвращает указатель на созданный макрообъект. Пример использования: reference p; Contour(1); /* определение контура */ ArcByPoint (50,50,50,0,50,100,50,1,1 ); LineSeg (100,50, 0, 50, 1); p = EndObj(); Результат выполнения представлен на рисунке 21. Рис. 21. Построение элемента с помощью функции Contour Построение таблицы осуществляется посредством вызова объекта Тable(). Формат и параметры вызова метода Тable() аналогичны как и при построении контуров, за исключением того, что нет необходимости указывать стиль линии. Пример использования представлен частью листинга прикладной библиотеки. Table(); const double n=25; for (int i=0;i<=8;i++) { LineSeg( 50+n*i,50, 50+n*i, 100, 1 ); }; LineSeg (50,50,50+n*8,50,1); LineSeg (50,75,50+n*8,75,1); LineSeg (50,100,50+n*8,100,1); EndObj(); Результат выполнения представлен на рисунке 22. Рис. 22. Построение таблицы с помощью функции Table() 35 2.3. Функции ввода параметров Для организации в прикладной библиотеке ввода данных от пользователя в системе КОМПАС API имеются команды, позволяющие задать значения переменных посредством диалогового окна. В языке С++ определены следующие типы данных: int- описание целочисленного типа данных, doubleописание вещественного (дробного) типа данных, char[]-тип по работе со строками, char-символьный тип и т.д. Вызов диалогов для вышеперечисленных типов осуществляется с помощью следующих функций: ReadInt, ReadLong, ReadString, ReadDouble, а также их аналогов с поддержкой Unicode. Функция ReadInt позволяет ввести целое число с контролем попадания значения в заданный интервал. Формат команды следующий: int ReadInt (char *smess, int def, int min, int max, int *value) где, smess-указатель на строку приглашения; def-значение, которое будет присвоено, если выбор не сделан; min,max- интервал возможных значений; value- результат ввода, посредством которого связывается значение с указанной переменной. Функция ReadLong позволяет ввести длинное целое число с контролем попадания значения в заданный интервал. Формат команды аналогичен ReadInt. Функция ReadDouble позволяет ввести вещественное число с контролем попадания значения в заданный интервал. Формат команды аналогичен ReadInt. Функция ReadString позволяет ввести строку заданной длины. Формат команды следующий: int ReadString(char *smess, char *str, int maxlen) где, smess- строка приглашения; maxlen- максимально допустимая длина строки; str- результат ввода. Для всех юникодных операций форма записи вышеперечисленных функций следующая: ReadIntT, ReadLongT, ReadStringT, ReadDoubleT. Пример использования: 36 TCHAR str[]=_T(""); ReadStringT (_T("Ввод текстового сообщения"), str,20); // Выдача сообщения пользователю MessageT( str );int ValueInteger; ReadIntT(_T("Введите значение &ValueInteger); целого числа"), 12,1,100, //Если Юникод не используется, форма записи выражения следующая: //ReadInt("Введите значение целого числа", 20,1,100, &ValueInteger); double ValueDouble; ReadDoubleT(_T("Введите значение вещественного числа"), 25.,1.,100., &ValueDouble);long ValueLong; ReadLongT(_T("Введите значение длинного целого числа"), 100,1,100000, &ValueLong); double ValueResult=ValueLong/ValueDouble+sin(ValueInteger); TCHAR buf[50]; _stprintf( buf, _T("Результат вычисления: %lf"),ValueResult); MessageT( buf ); Результат выполнения представлен на рисунке 23. Рис. 23. Применение функций ввода параметров для расчетов и инициализации данных При вычислении выражения «ValueResult= ValueLong/ ValueDouble+sin(ValueInteger)» в функцию синуса будет подставлено значение в радианах. Для проведения расчетов в градусах необходимо использовать формулу пересчета: 1 рад=180º/π или воспользоваться математической функцией синуса, которая определена в системе следующим образом: double SinD (double ang) где, ang- угол в градусах. Функция вернет значение синуса аргумента. В систему включены и другие тригонометрические функции: CosDвычисление косинуса, TanD-вычисление тангенса, AtanD-вычисление арктангенса. 37 3. МЕТОДЫ И ИХ СОСТАВЛЯЮЩИЕ ДЛЯ ПРОВЕДЕНИЯ ВСПОМОГАТЕЛЬНЫХ ПОСТРОЕНИЙ Элементы и функции, позволяющие выполнять и решать некоторые вопросы, не связанные напрямую с геометрическими построениями, относятся к вспомогательным построениям. Однако в документации приводится расширенный список команд, который входит в эту группу, но решает совершенно иные задачи. Функции экспорта документов, функции работы со спецификациями и моделями, событиями и интерфейсами системы в данных методических указаниях не будут рассмотрены, так как они не востребованы в составе библиотек с двумерными графическими документами. Для измерений и расчетов в API 2D определены следующие категории: математические функции, функции вычисления перемещений, функции вычисления длин и углов, функции вычисления касаний и сопряжений. 3.1. Математические функции Ряд математических функций был приведен в предыдущем разделе, отвечающих за тригонометрические вычисления. Приведем примеры использования некоторых элементов, выполняющих расчетные действия. Функция ksEqualPoints позволяет определить эквивалентность (совпадение) двух точек. Формат команды следующий: int ksEqualPoints(double x1, double y1, double x2, double y2) где, x1, y1-координаты первой точки; x2, y2координаты второй точки. Функция вернет значение единицы, если координаты точек совпадают и 0- в противном случае. Пример использования: struct { double x,y;} points1,points2,points3; points1.x=10;points1.y=45; points2.x=20;points2.y=80; points3.x=10;points3.y=45; if(ksEqualPoints(points1.x,points1.y,points2.x,points2.y)) MessageT (_T("Координаты точек совпадают")); else MessageT (_T("Координаты точек не совпадают")); if(ksEqualPoints(points1.x,points1.y,points3.x,points3.y)) MessageT (_T("Координаты точек совпадают")); else MessageT (_T("Координаты точек не совпадают")); 38 Функция Symmetry определяет координаты точки, симметричной относительно заданной оси. Формат функции следующий: void Symmetry (double x, double y,double x1, double y1, double x2, double y2, double *xs, double *ys) где, x, y- координаты базовой точки; x1, y1- координаты первой точки на оси симметрии; x2, y2- координаты второй точки на оси симметрии; координаты симметричной точки. xs, ys- координаты симметричной точки. Пример использования: double xs,ys; Symmetry (0, 10, 10, 0, 10, 100, &xs, &ys); TCHAR buf[50]; _stprintf( buf, _T("Координаты новой точки: x->%.2lf; y->%.2lf "),xs,ys); MessageT( buf ); Функция Rotate позволяет повернуть точку относительно центра. Формат команды следующий: void Rotate (double x, double y, double xc, double yc, double ang, double *xr, double *yr) где, x, y- координаты базовой точки; xс, yскоординаты центра поворота; ang- угол поворота; xr, yr- координаты точки после поворота. Пример использования: double xb,yb,xr,yr; int angle=180; xb=10;yb=10; Point (xb,yb,0); Rotate (xb,yb,20,20,angle,&xr,&yr); Point (xr,yr,0); Функция MovePoint производит сдвиг точки по заданному направлению. Команда имеет следующий формат: void MovePoint (double *x, double *y, double ang, double len) где, x, y- координаты точки; ang- угол вектора сдвига в градусах; len- длина вектора сдвига. Координаты x и y точки являются одновременно и входными, и выходными. На входе они представляют собой начальные координаты точки, а 39 в результате работы метода они преобразуются в координаты точки после сдвига. Пример использования: double x, y; x = 60; y = 10; int i; while (i<11) { LineSeg ( 10, 10, x, y, 1); MovePoint (&x, &y, 36, 10); i++; } 3.2. Функции вычисления пересечений Команды данного раздела отвечают за вычисление пересечений геометрических объектов друг с другом. Функция Perpendicular производит вычисление координат точки пересечения отрезка и перпендикуляра к нему, проходящего через заданную точку. Формат команды следующий: void Perpendicular (double x, double y, double x1, double y1, double x2, double y2, double *xp, double *yp) где, x,y- координаты точки; x1, y1- координаты начальной точки отрезка; x2, y2- координаты конечной точки отрезка; xp, yp- координаты точки пересечения отрезка и перпендикуляра к нему, проходящего через заданную точку. Пример использования: double x1,y1,x2,y2,xp,yp; x1=50;y1=0; x2=0;y2=50; Perpendicular (0,0,x1,y1,x2,y2, &xp, &yp); Point (xp,yp,0); Функция IntersectCirLin позволяет получить координаты точек пересечения окружности и прямой. Формат команды следующий: void IntersectCirLin (double xc, double yc, double rad, double x, double y, double ang, int *kp, double *xp, double *yp) где, xc, yc- координаты центра окружности; rad- радиус окружности; x, y- координаты точки на прямой; 40 ang- угол наклона прямой; kp- число пересечений (от 0 до 2); xp, yp- координаты точки пересечения. Пример использования: double x, y; int k; double x1=25,y1=25,r=15; double x2=0,y2=0,ang=45; Circle ( x1, y1, r, 0); Line ( x2, y2, ang); IntersectCirLin (x1, y1, r, x2, y2, ang, &k, &x, &y); char buf[128]; sprintf(buf, "Количество пересечений = %i", k); ::Message(buf); Аналогично работают функции по определению координат пересечений прямой с отрезком, двух прямых, отрезков и окружностей. 3.3. Функции вычисления длин, расстояний, углов Для ряда операций, позволяющих вести построение и определять положение объектов на плоскости, необходимо иметь информацию о расположении этих объектов-координат базовых точек, расстояния между ними и т.д. В систему Компас 3D интегрированы функции, позволяющие вычислять расстояния от точки до объекта, длины объектов, углы между объектами или между объектом и осью X. Функция Angle производит вычисление угла (в градусах) между осью OX и вектором, заданным двумя точками. Формат команды следующий: double Angle (double x1, double y1, double x2, double y2) где, x1, y1- координаты начальной точки вектора; x2, y2- координаты конечной точки вектора. Функция вернет значение угла в градусах или 0, если команда некорректно определена. Пример использования: double ang; LineSeg ( 0, 0, 60, 20, 1); LineSeg ( 0, 0, 60, 0, 1); ang = Angle (0, 0, 60, 40); TCHAR buf[50]; _stprintf( buf, _T("Угол= %3.2f"),ang); MessageT( buf ); 41 Функция DistancePntPnt позволяет получить расстояние между двумя точками. Формат команды следующий: double DistancePntPnt (double x1, double y1, double x2, double y2) где, x1,y1- координаты первой точки; x2,y2-координаты второй точки. Пример использования: double length; Point(10,20,1); Point(201,-20,1); length = DistancePntPnt (10,20, 201,-20); TCHAR buf[50]; _stprintf( buf, _T("Расстояние между двумя точками= %lf"), length); MessageT( buf ); Функция ksViewGetDensity вызывает диалоговое меню, в котором определены значения плотности некоторых материалов. Формат команды следующий: double ksViewGetDensity (void * HWindow) где, HWindow- handle "родительского" окна или NULL. В случае успешного выполнения функция вернет значение плотности выбранного материала. Плотность выбирается из системного файла плотностей graphic.dns. Пример использования: double density = ksViewGetDensity(0); TCHAR buf[50]; _stprintf( buf, _T(" density = %2.3f г/мм3"), density ); MessageT( buf ); Выполнение программного кода в прикладной библиотеке приведет к вызову диалога, представленного на рисунке 24. Рис. 24. Выбор значения плотности материалов из базы данных системного файла «graphic.dns» 42 Функция ksDistancePntLineForPoint позволяет произвести вычисление расстояния между заданной точкой и прямой, проходящей через две точки, отличные от базовой. Формат команды следующий: double ksDistancePntLineForPoint (double x, double y, double x1, double y1, double x2, double y2) где, x, y- координаты базовой точки; x1, y1- координаты первой точки на прямой; x2, y2- координаты второй точки на прямой. Функция вернет значение расстояния в случае успешного выполнения. Пример использования: double xb=100,yb=130; double x1=-20,x2=70; double y1=40,y2=-25; Point(xb,yb,0); LineSeg(x1,y1,x2,y2,0); double length = ksDistancePntLineForPoint(xb,yb,x1,y1,x2,y2); TCHAR buf[50]; _stprintf( buf, _T("Расстояние от точки до прямой=%.2f"), length); MessageT( buf ); 43 4. РАБОТА С БАЗАМИ ДАННЫХ Базы данных достаточно часто используются для хранения и размещения электронной информации подобного типа, поиск которой осуществляется посредством запросов со стороны пользователя. Для организации данных в системе Компас 3D определен набор команд, позволяющий реализовать вышеперечисленные задачи. Под базой данных понимается текстовый документ, имеющий расширение .loa. Текстовый документ, содержащий необходимые параметры, можно создать и отредактировать любой программой, входящей в комплект ОС Windows. Файл с простейшей базой данных под Компас 3D имеет следующий вид: /*Пример базы данных. x - координата х объекта y - координата y объекта r - радиус окружности x y r */ 80, 100, 5, 100, 135, 30, 70, 60, 15, 140, 45, 20, 192, 120, 50, Из примера видно, что файл включает в себя группу цифр, размещенных построчно в несколько рядов. Отдельно взятая строка является взаимосвязанной структурой данных. Так в файле группа из 3 трех цифр позволяет нести информацию о координатах центра окружности с указанием ее радиуса. Базы данных в системе Компас 3D могут иметь более сложную структуру, а одни параметры строки, представленные цифрами, могут находиться в прямой или косвенной зависимости от других. Типичным примером для создания базы данных является номенклатура некоторых крепежных элементов, например винтов, определенных по ГОСТ 149180,11738-84. Для того чтобы начать работу с созданной базой данных необходимо загрузить данные в память или часть информации с базы, если количество параметров превышает размер имеющейся оперативной памяти компьютера, выделенную под операцию чтения. Загрузить базу данных в память возможно посредством указания точного месторасположения данных на диске или на сменном носителе следующим образом: TCHAR fileName[]=_T( "./Load/1154 .loa "); 44 Однако проще организовать для пользователя диалог по загрузке базы данных с произвольного каталога жесткого диска или сменного носителя. Для создания блока заголовка базы данных используется команда CreateDB. Функция позволяет открыть БД. Одновременно может быть открыто несколько БД. Формат команды следующий: reference CreateDB( char *s ) где, s-тип базы данных: TXT_DB - база данных текстового формата. Команда ConnectDB позволяет связать заголовок и базу данных. Формат команды следующий: int ConnectDB (reference bd, char * dataBaseName) где, bd- указатель на блок заголовка, созданный при помощи функции CreateDB, dataBaseName- имя БД (для базы данных, доступной через интерфейс ODBC - имя БД в администраторе ODBC, для базы данных текстового формата - имя файла). Далее необходимо соотнести поля чтения по колонкам с некоторым указателем путем команды Relation- создать новое отношение. Отношение характеризует один запрос и представляет собой описание памяти, необходимой для размещения очередной записи выборки, выполняемого функцией ReadRecord. Является составным объектом, каждое поле которого описывает тип и имя поля (колонки) в таблице базы данных. Имя действительно только в случае работы с текстовым файлом, так как при обмене через ODBC-интерфейс имена уже описаны в блоке заголовка. Количество отношений, определенных для базы данных, не ограничивается. Формат команды следующий: reference Relation (reference bd) где, db- указатель на объект БД. Для обращения к базе данных применяется команда DoStatement. Синтаксис команды следующий: int DoStatement (reference bd, reference rel, char * str) где, bd- указатель на объект БД, rel- действительный указатель на отношение, str- запрос к БД. 45 После обращения к базе данных происходит построчное связывание потока с элементами структуры (struct {}), созданной стандартными средствами языка C. Для нескольких параметров базы данных структура может иметь следующий вид: struct {int par1,par2,par3,…, parn ;}datas; В следующем примере реализована работа по обращению к базе данных. void DrawTxtDB() { TCHAR fileName[255]; // Диалоговое окно при выборе базы данных if ( ksChoiceFileT( _T("*.loa"), _T("Базы данных( *.loa )|*.loa|Все файлы )|*.*|"),fileName, 255,1)) { reference rDataBase = CreateDBT( _T("TXT_DB") ); if ( ConnectDBT( rDataBase, fileName ) ) { reference rRelation = Relation( rDataBase ); RDoubleT( _T("x") ); RDoubleT( _T("y") ); RDoubleT( _T("") ); EndRelation(); //Колонка x - 1, y - 2, оставшаяся колонка - 3 DoStatementT( rDataBase, rRelation, _T("1 2 3") ); TCHAR buf[255]; ( *.* //Структура для считывания информации из базы struct { //Координаты объекта double x, y ; //Радиус окружности double r; }record; // Считывание данных из базы int pointer=1; int counter =0; while (pointer ) { //Считать очередную строку и загрузить в структуру record pointer=ReadRecord( rDataBase, rRelation, &record ); if ( pointer ) { _stprintf( buf, _T("x=%4.1f,y=%4.1f,r=%4.1f"), record.x, record.y, record.r ); MessageT( buf ); Circle( record.x, record.y, record.r, 1); counter++; } } _stprintf( buf, _T("База данных прочитана, всего записей %d"), counter ); MessageT( buf ); } DeleteDB( rDataBase ); } } 46 Результат работы с базой данных элементов представлен на рисунке 25. Рис. 25. Последовательное чтение значений с базы данных и построение окружностей на плоскости согласно значениям, взятым из файла с данными 47 5. ПРИМЕРЫ ПРОЕКТИРОВАНИЯ БИБЛИОТЕК В 2D Рассмотрим варианты и способы применения вышеперечисленных методов для решения практических задач при проектировании библиотек геометрического вывода на плоскости. Под поставленные задачи рассмотрен механизм решения, который состоит из одной или несколько функций. Для управления объектами введено понятие класса, что позволяет разграничить уровень доступа к данным и упростить проектирование прикладной библиотеки. Текст библиотеки содержит комментарии, позволяющие проследить и понять работу некоторых сервисных команд и инструкций, а также изучить особенности построения синтаксических возможностей языка С++. Для ряда расчетов потребуется подключение заголовка математической библиотеки <cmath>, а также стандартной библиотеки <cstdlib>. Некоторые константы определены отдельно в директивах предпроцессора, как например #define PIE 3.1415926535 Проекты подготовлены на базе шаблона из первой главы, что делает их открытими для изменений подобного рода. Примеры были протестированы в системах Kompas 3D v10-13, однако в ряде случаев требуется пересборка проекта прикладной библиотеки, если разработка ведется в разных версиях Microsoft Studio (6, 2003, 2005,2010). 5.1. Построение графиков функций Для построения на плоскости графика заданной функции в изометрии предлагается пример прикладной библиотеки Компас, код которой будет представлен далее. Технически построить функцию в изометрии несложно, для этого достаточно получить новые точки пересчета системы координат. 48 #include "stdafx.h" #include <afxdllx.h> #include "resource.h" #include <сmath> #include <libtool.h> #include <ldefin2d.h> #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define PIE 3.1415926535 class two_d_project { //Функция вывода изображения на экран void DrawSetPoint(double y,double z) { Point (90+0.707*z,65+y+0.707*z,0); }; //Функция для вывода текста void DrawSetText(char *buf) { Text(0,-20,0,7,0,0,buf); }; public: //Построение графиков функций на плоскости в изометрии void graphfunc(); } *two_d; // Специальная структура используемая в течении инициализации DLL static AFX_EXTENSION_MODULE StepDLL = { NULL, NULL }; // Стандартная точка входа // Инициализация и завершение DLL extern "C" int APIENTRY DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved ) {UNREFERENCED_PARAMETER( lpReserved ); if ( dwReason == DLL_PROCESS_ATTACH ) {TRACE0( "DLL Initializing!" ); if ( !AfxInitExtensionModule( StepDLL, hInstance ) ) return 0; new CDynLinkLibrary( StepDLL ); } else if ( dwReason == DLL_PROCESS_DETACH ) { TRACE0( "DLL Terminating!" ); AfxTermExtensionModule( StepDLL ); } return 1; } 49 // Задать идентификатор ресурсов unsigned int WINAPI LIBRARYID() { return IDR_LIBID; } // Получить идентификаторы инструментальных и компактных панелей int WINAPI LibToolBarId( int barType, // Тип запрашиваемой панелей ( 0 - компактная панель, 1 - //простая инструментальная панель ) int index ) // Индекс панели { if ( !barType ) return !index ? COMPACT_BAR1 : -1; else return -1; } // Головная функция библиотеки void WINAPI LIBRARYENTRY( unsigned int comm ) { // Получить активный 2D документ if ( ksGetCurrentDocument( 1 ) ) { switch ( comm ) { case 1 : two_d->graphfunc(); break; } } else Message( "Документ не активизирован или\n не является листом/фрагментом" ); }//Построение графиков функций в аксонометрии void two_d_project::graphfunc() { int change; //Выбор режима отображения графика ReadIntT( _T("Отобразить график:(ввод 1-5)"), 2, 1, 5, &change ) ; //Построение координатных осей LineSeg (90,65,6,120,2); PointArraw(6,120,147,2); LineSeg (90,65,90,165,2); PointArraw(90,165,90,2); LineSeg (90,65,175,150,2); PointArraw(175,150,45,2); LineSeg (44,19,90,65,2); //Расчетные коэффициенты double s=PIE/100; double f,z,y; switch ( change ) {//Построение графика функции sin case 1 : { for (f=-2*PIE;f<3*PIE;f+=s) { z=10*f; 50 y=45*sin (f); two_d->DrawSetPoint(y,z); } char *string="График в аксонометрии функции вида: y=sin(f)"; two_d->DrawSetText (string); break; } //Построение графика функции cos case 2 : { for (f=-2*PIE;f<3*PIE;f+=s) { z=10*f; y=45*cos (f); two_d->DrawSetPoint(y,z); } char *string="График в аксонометрии функции вида: y=cos(f)"; two_d->DrawSetText (string); break; } //Построение графика показательной функции case 3 : { for (f=0;f<70;f+=0.1) { z=f; y=sqrt((f))*5; two_d->DrawSetPoint(y,z); } char *string="График в аксонометрии показательной функции вида: y=SQRT(f)"; two_d->DrawSetText (string); break; } //Построение графика затухающей функции case 4: { for (f=0;f<100;f+=0.05) { z=f; y=70*(exp(-f*0.07))*sin(PIE*f*(10.0/3.0)/30.0); two_d->DrawSetPoint(y,z); } char *string="График затухающей функции вида: y=A(exp(f*B))*sin(PIE*f*(C)/D);"; two_d->DrawSetText (string); break; } //Петля case 5: { double delta=1,base=45; 51 for(f=-3*PIE;f<3*PIE;f+=s) { z=base*f; base=base+delta*f; y=base*cos (f); two_d->DrawSetPoint(y/100,z/100); } char *string="Петля: y=base*cos (f); base=base+delta*f"; two_d->DrawSetText (string); break; } } } Результат работы прикладной библиотеки при выборе значения «4» показан на рисунке 26. График затухающей функции вида: y=A(exp(- f* B))* sin(PIE* f* (C)/ D); Рис. 26. Построение графика функции согласно заданным параметрам 5.2. Построение фигур Для построения на плоскости фигур предлагается пример прикладной библиотеки Компас, код которой приведен ниже. 52 #include "stdafx.h" #include <afxdllx.h> #include "resource.h" #include "math.h" #include <libtool.h> #include <ldefin2d.h> #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define PIE 3.1415926535 class two_d_project { public: //Построение параболоида void paraboloid(); //Построение графических объектов void graphline(); } *two_d; // Специальная структура используемая в течении инициализации DLL static AFX_EXTENSION_MODULE StepDLL = { NULL, NULL }; // Стандартная точка входа // Инициализация и завершение DLL extern "C" int APIENTRY DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved ) { UNREFERENCED_PARAMETER( lpReserved ); if ( dwReason == DLL_PROCESS_ATTACH ) { TRACE0( "DLL Initializing!" ); if ( !AfxInitExtensionModule( StepDLL, hInstance ) ) return 0; new CDynLinkLibrary( StepDLL ); } else if ( dwReason == DLL_PROCESS_DETACH ) { TRACE0( "DLL Terminating!" ); AfxTermExtensionModule( StepDLL ); } return 1; } unsigned int WINAPI LIBRARYID() { return IDR_LIBID; } 53 // Получить идентификаторы инструментальных и компактных панелей int WINAPI LibToolBarId( int barType, // Тип запрашиваемой панелей ( 0 - компактная панель, 1 – // простая инструментальная панель ) int index ) // Индекс панели { if ( !barType ) return !index ? COMPACT_BAR1 : -1; else return -1; } // Головная функция библиотеки void WINAPI LIBRARYENTRY( unsigned int comm ) { if ( ksGetCurrentDocument( 1 ) ) // Получить активный 2D документ { switch ( comm ) { case 1 : two_d->paraboloid(); break; case 2 : two_d->graphline(); break; } } else Message("Документ не активизирован или\nне является листом/фрагментом" ); } // Построение параболоида void two_d_project::paraboloid() { double z,s,zc,x,y; for (z=-5;z<4;z+=0.15) { s=0.707*z; zc=pow(z,2); Bezier( 0, 0 ); for (x=-5;x<5;x+=0.15) {y=0.6*(zc+x*x); double xt=0+6*(x+s); double yt=6*(y+s); Point (xt,yt,0); } // Функция EndObj возвращает указатель на созданный // объект кривой Безье reference rBezier1 = EndObj();} char *string="Параболоид вида: y=0,6*(x*x+z*z)"; Text(-60,-20,0,7,0,0,string); }// Фигуры void two_d_project::graphline() { int i=72,j=0; double px=100,py=100,angle=0; while (i>0) { j++; 54 // Структура параметров прямоугольника RectangleParam parRectangle; memset( &parRectangle, 0, sizeof( parRectangle ) ); //Координаты базовой точки прямоугольника - одной из его вершин parRectangle.x = 0; parRectangle.y = 0; parRectangle.ang = angle; // Высота прямоугольника parRectangle.height = px; // Ширина прямоугольника parRectangle.width = py; // Стиль линии parRectangle.style = 1; // Динамический массив структур параметров скругленных (или // усеченных) углов parRectangle.pCorner = CreateArray( CORNER_ARR, 0 ); // Создать прямоугольник ksRectangle( &parRectangle, 0 ); i--; angle+=5; }//спираль Архимеда //r-Радиус для расчета int r,b; double x,y,a=0; ReadIntT( _T("Введите значение радиуса (ввод 1-20)"), 3, 1, 20, &r); ReadIntT( _T("Введите число итераций (ввод 1-1000)"), 1, 10, 1000, &b); float x0=0; float y0=100; Bezier( 0, 0 ); Point (x0, y0,0); for (int i=1;i<b;i++) { x=x0-(r*a*cos(a)); y=y0+(r*a*sin(a)); Point (x, y,0); a+=0.1; } EndObj(); //Логарифмическая спираль int n; ReadIntT( _T("Введите количество витков(ввод 1-10)"), 4, 1, 10, &n); double r,a=0,arad; while (a<360*n) { arad = a * PIE / 180; r=2*exp(0.1 * arad); Point((r*sin(arad)),(r*cos(arad)),0); a+=0.1; } } 55 Результаты работы прикладной библиотеки представлены на рисунках 27 и 28. Рис. 27. Построение параболоида программным способом Рис. 28. Построение логарифмической спирали Следующий пример позволяет использовать объектно-ориентирванный подход по построению графического объекта-подмножества треугольников. Для удобства в одном файле объявлен пользовательский класс с описанием метода указанного класса, а также размещены все сервисные функции прикладной библиотеки Компас. 56 // Библиотека на Visual C++ #include "stdafx.h" #include <afxdllx.h> #include "my_first_library.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //Описание объекта-в данном случае треугольников class triangle { //Координаты базового треугольника float xA,yA,xB,yB,xC,yC; //Координаты рассчитанного треугольника float xxA,yyA,xxB,yyB,xxC,yyC; //Коэффициенты смещения новой точки (точек) float p,q; //Маштабирование объекта int dis; public: void building(); triangle() { dis=10; building(); } ~triangle() {} }; //Метод класса по построению треугольников void triangle::building() { p=0.95; q=1-p; xA=0.0;xB=8.0;xC=4.0; yA=0.0;yB=0.0;yC=8.0; //Построение 50 однотипных объектов for(int i=0;i<50;i++) { //Построение отрезков LineSeg (xA/dis,yA/dis,xB/dis,yB/dis,1); LineSeg (xB/dis,yB/dis,xC/dis,yC/dis,1); LineSeg (xC/dis,yC/dis,xA/dis,yA/dis,1); 57 //Расчет новых координатных точек xxA=p*xA+q*xB;yyA=p*yA+q*yB; xxB=p*xB+q*xC;yyB=p*yB+q*yC; xxC=p*xC+q*xA;yyC=p*yC+q*yA; xA=xxA;xB=xxB;xC=xxC; yA=yyA;yB=yyB;yC=yyC; } } //-----------------------------------------------------------// Специальная структура используемая в течении инициализации DLL // ----------------------------------------------------------static AFX_EXTENSION_MODULE My_first_libraryDLL = { NULL, NULL }; HINSTANCE g_hInstance = NULL; IApplicationPtr newKompasAPI( NULL ); void OnProcessDetach(); // Отключение библиотеки // Стандартная точка входа // Инициализация и завершение DLL // --extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { g_hInstance = hInstance; if (dwReason == DLL_PROCESS_ATTACH) { TRACE0("MY_FIRST_LIBRARY.AWX Initializing!\n"); AfxInitExtensionModule(My_first_libraryDLL, hInstance); new CDynLinkLibrary(My_first_libraryDLL); } else if (dwReason == DLL_PROCESS_DETACH) { TRACE0("MY_FIRST_LIBRARY.AWX Terminating!\n"); OnProcessDetach(); AfxTermExtensionModule(My_first_libraryDLL); } return 1; // ok } //----------------------------------------------------------------// Получить доступ к новому API void GetNewKompasAPI() { if ( !( IApplication * )newKompasAPI ) { CString filename; if( ::GetModuleFileName(NULL, filename.GetBuffer(255), 255) ) { filename.ReleaseBuffer( 255 ); CString libname; 58 libname = LoadStr( IDR_API7 ); // kAPI7.dll filename.Replace( filename.Right(filename.GetLength() (filename.ReverseFind('\\') + 1)), libname ); HINSTANCE hAppAuto = LoadLibrary( filename ); // идентификатор kAPI7.dll if( hAppAuto ) { // Указатель на функцию возвращающую интерфейс KompasApplication typedef LPDISPATCH ( WINAPI * FCreateKompasApplication )(); FCreateKompasApplication pCreateKompasApplication = (FCreateKompasApplication)GetProcAddress( hAppAuto, "CreateKompasApplication" ); if ( pCreateKompasApplication ) newKompasAPI = IDispatchPtr ( pCreateKompasApplication(), false /*AddRef*/); // Получаем интерфейс Application FreeLibrary( hAppAuto ); } } } } // Задать идентификатор ресурсов // --unsigned int WINAPI LIBRARYID() { return IDR_LIBID; } // Описания используемых функций void figure(); // Головная функция библиотеки void WINAPI LIBRARYENTRY( unsigned int comm ) { //Построение функции построения объектов класса figure(); } // Проектирование объекта void figure() { //Создание указателя на класс triangle *pointer=new triangle(); //Вызов метода класса pointer->building(); //Удаление указателя delete pointer; } // Завершение приложения void OnProcessDetach() { newKompasAPI = NULL; } // Загрузить строку из ресурса // --CString LoadStr( int strID ) { TCHAR temp[_MAX_PATH]; LoadString( My_first_libraryDLL.hModule, strID, temp, _MAX_PATH ); return temp; }_MODULE My_first_libraryDLL = { NULL, NULL }; 59 На рисунке 29 представлены результаты работы прикладной библиотеки в Компас 3D. Рис. 29. Построение треугольников 5.3. Построение эскизов Для построения эскизов с указанием размерных линий, допусков, отображением знаков шероховатости, отклонений и т. д. необходимо подробно ознакомиться с документацией и примерами, так как проектирование элементов чертежей и эскизов программным путем является достаточно трудоемким процессом. Листинг прикладной библиотеки, выполняющей построение эскиза, приведен ниже. 60 #include "stdafx.h" #include <afxdllx.h> #include "resource.h" #include "math.h" #include <libtool.h> #include <ldefin2d.h> #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define PIE 3.1415926535 class two_d_project {//Прототип функции, позволяющей строить разметные линии void LinearSize(double px1,double py1, double px2, double py2,int style, int type,int set,double posx,double posy); //Прототип функции, позволяющей задать шероховатость поверхностей void DrawRough(double an,double xpos,double ypos,TCHAR ch[]); public: //Построение эскиза void outline(); }*two_d; // Специальная структура используемая в течении инициализации DLL static AFX_EXTENSION_MODULE StepDLL = { NULL, NULL }; // Стандартная точка входа // Инициализация и завершение DLL extern "C" int APIENTRY DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved ) {UNREFERENCED_PARAMETER( lpReserved ); if ( dwReason == DLL_PROCESS_ATTACH ) { TRACE0( "DLL Initializing!" ); if ( !AfxInitExtensionModule( StepDLL, hInstance ) ) return 0; new CDynLinkLibrary( StepDLL ); } else if ( dwReason == DLL_PROCESS_DETACH ) { TRACE0( "DLL Terminating!" ); AfxTermExtensionModule( StepDLL ); } return 1; } // Задать идентификатор ресурсов unsigned int WINAPI LIBRARYID() { return IDR_LIBID; } // Получить идентификаторы инструментальных и компактных панелей int WINAPI LibToolBarId( int barType, 61 // Тип запрашиваемой панелей (0 - компактная панель, 1 - простая // инструментальная панель ) int index ) // Индекс панели { if ( !barType ) return !index ? COMPACT_BAR1 : -1; else return -1; } // Головная функция библиотеки void WINAPI LIBRARYENTRY( unsigned int comm ) { if ( ksGetCurrentDocument( 1 ) ) // Получить активный 2D документ { switch ( comm ) { case 1 : two_d->outline(); break; } } else Message( "Документ не активизирован или\nне является листом/фрагментом" ); } //Построение эскиза шпильки void two_d_project::outline() { Mtr( 0, 0, 0, 1 ); // Матрица преобразования координат ( 30 по оси OX, 20 по оси OY, маштаб 1:2 ) //Построение контура втулки LineSeg (0.0,1.6,1.6,0.0,1); LineSeg (1.6,0,35,0.0,1); LineSeg (35.0,0,35.0,7,1); LineSeg (1.6,7.0,35,7.0,1); LineSeg (1.6,7.0,0.0,5.4,1); LineSeg (0.0,1.6,0.0,5.4,1); // Штриховка квадрата Hatch( 0, // Стиль штриховки ( 0 - металл, 1 - неметалл, 2 - дерево, 3 – // камень естественный, 4 - керамика, 5 - бетон, 6 - стекло, 7 – // жидкость, 8 - естественный грунт, 9 - насыпной грунт, 10 – // камень искусственный, 11 - железобетон, 12 - напряженный // железобетон, 13 - дерево в продольном сечении, 14 - песок ) 45, // Угол штриховки 2, // Шаг штриховки 0, // Ширина полосы штриховки ( 0 - штриховать всю область ) 0, 0 ); // Базовая точка //Контур для штриховки LineSeg (0.0,1.6,1.6,0.0,1); LineSeg (1.6,0,35,0.0,1); LineSeg (35.0,0,35.0,7,1); LineSeg (1.6,7.0,35,7.0,1); LineSeg (1.6,7.0,0.0,5.4,1); LineSeg (0.0,1.6,0.0,5.4,1); 62 reference rHatch = EndObj(); DeleteMtr(); //Вызов Функций по нанесению линейных размеров two_d->LinearSize(0,1.6,35,1.6,0,1,0,0,-30); two_d->LinearSize(33.4,0,33.4,7,1,2,1,20,0); two_d->LinearSize(0,1.6,1.6,0,0,2,0,0,-10); //Вызов Функций по указанию заданной шероховатости поверхности two_d->DrawRough(90,17.5,7,_T("3.2")); two_d->DrawRough(180,0,-27,_T("3.2")); two_d->DrawRough(0,35,-20,_T("3.2")); } //Функция по нанесению линейных размеров void two_d_project::LinearSize(double px1,double py1, double px2, double py2,int style, int type,int set,double posx,double posy) { // Структура параметров линейного размера LDimParam parLDim; memset( &parLDim, 0, sizeof( parLDim ) ); // Параметры изображения размера // Положение текста ( 0 - автоматическое размещение текста, // > 0 - на указанное расстояние в направлении от первой точки //ко второй, // < 0 - на указанное расстояние в направлении от второй точки к //первой ) parLDim.dPar.textPos = 0; // Параметр отрисовки текста ( 0 - в центре, 1 - textPos //относительно 1 точки, // 2 - textPos относительно 2 точки, 3 - общая размерная линия ) parLDim.dPar.textBase = 0; // Признак отрисовки первой выносной линии ( 0 - включена, 1 – // выключена ) parLDim.dPar.pl1 = 0; // Признак отрисовки второй выносной линии ( 0 - включена, 1 // выключена ) parLDim.dPar.pl2 = 0; // Тип стрелки у первой выносной линии ( 0 - стрелки нет, 1 – // внутри, 2 - снаружи, 3 - засечка, 4 - точка ) parLDim.dPar.pt1 = type; // Тип стрелки у второй выносной линии ( 0 - стрелки нет, 1 – // внутри, 2 - снаружи, 3 - засечка, 4 - точка ) parLDim.dPar.pt2 = type; // Наличие выносной полки ( 0 - нет выносной полки, -1 - полка // направлена влево, // 1 - полка направлена вправо, 2 - полка направлена вверх, 3 – // полка направлена вниз ) parLDim.dPar.shelfDir = 0; // Угол наклона ножки выносной полки parLDim.dPar.ang = 0; // Длина ножки выносной полки parLDim.dPar.length = 0; // Параметры размерной надписи // Cтиль текста размера, ( 0 - стиль по умолчанию ) parLDim.tPar.style = 0; 63 // Номер условного значка перед номиналом ( 0 - нет значка, 1 – // диаметр, 2 - квадрат, // 3 - радиус, > 3 - номер значка из шрифта Symbol type A ) parLDim.tPar.sign = style; // Признаки размерной надписи ( набор битовых полей, 0 - ручное // задание ) // Должны быть строки PREFIX, номинал ставится auto ( ставить не // нужно ), TOLERANCE, отклонения // ставятся auto ( ставить не нужно ), UNIT, SUFFIX ( 4 строки ) parLDim.tPar.bitFlag = _AUTONOMINAL ; //parLDim.tPar.bitFlag = _AUTONOMINAL|_UNIT; parLDim.tPar.pText = CreateArray( CHAR_STR_ARR, 0 ); // Динамический массив строк // Привязка линейного размера // Признак ориентации размерной линии ( 0 - горизонтально, 1 – // вертикально, // 2 - параллельно отрезку, соединяющему точки привязки, 3 – по // dx, dy, // 4 - параллельно отрезку с выносными линиями по dx, dy. parLDim.sPar.ps = set; // Координаты первой точки привязки parLDim.sPar.x1 = px1; parLDim.sPar.y1 = py1; // Координаты второй точки привязки parLDim.sPar.x2 = px2; parLDim.sPar.y2 = py2; // Вектор, определяющий положение размерной линии parLDim.sPar.dy = posy; parLDim.sPar.dx = posx; // Признак, указывающий, от какой точки откладывать dx, dy // ( 1 - от первой точки, 2 - от второй точки ) parLDim.sPar.basePoint = 1; // Создание линейного размера reference rLinDimension = LinDimension( &parLDim ); GetObjParam( rLinDimension, // Указатель на граф. объект &parLDim, // Указатель на структуру параметров sizeof( parLDim ), // Размер структуры параметров ALLPARAM ); // Тип считывания параметров }//Функция по указанию заданной шероховатости поверхности void two_d_project::DrawRough(double an,double xpos,double ypos,TCHAR ch[]) {// Структура параметров обозначения шероховатости с полкой RoughParam parRougham; memset( &parRougham, 0, sizeof( parRougham ) ); // Параметры выносной полки // Направление полки параллельно оси X ( 0 - нет выносной полки, // -1 - полка направлена влево, 1 - полка направлена вправо, // 2 - полка направлена вверх, 3 - полка направлена вниз ) parRougham.shPar.psh = 0; // Угол наклона размерной линии parRougham.shPar.ang = 130; // Длина ножки parRougham.shPar.length = 20; 64 // Параметры знака шероховатости // Тип шероховатости ( 0 - вид обработки не устанавливается, // 1 - обработка удалением слоя материала, // 2 - обработка без удаления слоя материала ) parRougham.rPar.type = 0; // 1 - шероховатость по контуру parRougham.rPar.around = 0; // Координаты точки привязкиопараметры первого отрезка parRougham.rPar.x = xpos; parRougham.rPar.y = ypos; // Угол наклона оси значка шероховатости с осью X parRougham.rPar.ang = an; // Количество строк в тексте над знаком ( параметры шер-ти по // ГОСТ 2789-73 ) parRougham.rPar.cText0 = 0; // Количество строк в тексте над полкой ( вид обработки и // дополнительные указания ) parRougham.rPar.cText1 = 1; // Количество строк в тексте под полкой ( базовая длина по ГОСТ // 2789-73 ) parRougham.rPar.cText2 = 0; // Количество строк в тексте под полкой ( условное обозначение // направления неровностей ) // ( не более одной строки ) parRougham.rPar.cText3 = 0; // Режим, когда тексты задаются массивом модельных строк текста // Стиль текста ( 0 - то стиль умолчательный, // INDICATIN_TEXT_LINE_ARR - массив TEXT_LINE_ARR ) parRougham.rPar.style = INDICATIN_TEXT_LINE_ARR; // Структура параметров строки текста TextLineParam parTextLine; // Номер стиля строки текста parTextLine.style = 0; // Массив неопределенной длины компонент строки текста parTextLine.pTextItem = CreateArray( TEXT_ITEM_ARR, 0 ); // Структура параметров шрифта компоненты строки текста TextItemFontT parItemFont; memset( &parItemFont, 0, sizeof( parItemFont ) ); // Структура параметров компоненты строки текста TextItemParamT parTextItem; // SPECIAL_SYMBOL, FONT_SYMBOL, FRACTION_TYPE, SUM_TYPE или 0 parTextItem.tip = 0; // Параметры шрифта компоненты строки текста parTextItem.font = parItemFont; // Номер спецсимвола, символа из произвольного фонта или тип // отрисовки дроби или выражения типа суммы или 0 parTextItem.iSNumb = 0; // Массив неопределенной длины строк текста шероховатости // Различают 4 разных текста для шероховатости ( строки лежат в // следующей последовательности ) // 1. текст над знаком ( параметры шер-ти по ГОСТ 2789-73 ) // 2. текст над полкой ( вид обр-ки и доп, указания ) // 3. текст под полкой ( базовая длина по ГОСТ 2789-73 ) 65 // 4. текст под полкой ( усл.обозн.направления неровностей ) // Если cText0 = 0 или cText1 = 0 или cText2 = 0 или cText3 = 0, // то соответствующий текст в обозначении шероховатости // отсутствует parRougham.rPar.pText = CreateArray( TEXT_LINE_ARR, 0 ); // Режим, когда тексты задаются массивом строк символов // Стиль текста ( 0 - то стиль умолчательный, INDICATIN_TEXT_LINE_ARR - массив TEXT_LINE_ARR ) parRougham.rPar.style = 0; // Массив неопределенной длины строк текста шероховатости // Различают 4 разных текста для шероховатости ( строки лежат в // следующей последовательности ) // 1. текст над знаком ( параметры шер-ти по ГОСТ 2789-73 ) // 2. текст над полкой ( вид обр-ки и доп, указания ) // 3. текст под полкой ( базовая длина по ГОСТ 2789-73 ) // 4. текст под полкой ( усл.обозн.направления неровностей ) // Если cText0 = 0 или cText1 = 0 или cText2 = 0 или cText3 = 0, // то соответствующий текст в обозначении шероховатости // отсутствует parRougham.rPar.pText = CreateArray( CHAR_STR_ARR_T, 0 ); // Заполнение массива строк текста шероховатости AddArrayItem( parRougham.rPar.pText, -1, ch, 4 ); // Создание шероховатости reference rRough = Rough( &parRougham ); // Режим, когда тексты задаются массивом строк символов // Удалить динамический массив строк текста DeleteArray( parRougham.rPar.pText ); } Результат работы прикладной библиотеки показан на рисунке 30. 3.2 7 35 3.2 3.2 1,6 Рис. 30. Построение эскиза шпильки 66 6. БАЗОВОЕ ТВЕРДОТЕЛЬНОЕ МОДЕЛИРОВАНИЕ ОБЪЕКТОВ В КОМПАС 3D В системе Компас 3D, наряду с программным построением на плоскости, возможно моделирование твердотельных деталей и узлов посредством команд и функций АPI. Посредством моделирования или программным способом можно подготовить к работе два типа документов 3D: детали и сборки. Сборки включают в себя модели деталей и узлы. Для того, что начать работу с документом 3D, необходимо внести в проект файл kAPI3D5.lib. Указанный файл размещен в папке lib каталога SDK. Проект можно создать с помощью мастера проектов (об этом подробно написано в разделе по созданию 2D документов) или изменить имеющиеся проекты примеров из папки Examples SDK VisualC++. Кроме того, требуется импортировать пути для подключаемых библиотек, указав их месторасположение на диске. Все изменения необходимо произвести в файле StdAfx.h. #ifndef __STDAFX_H #define __STDAFX_H #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #define VC_EXTRALEAN //Exclude rarely-used stuff from headers #include <afxwin.h> // MFC core and standard components #include <afxext.h> // MFC extensions #ifndef _AFX_NO_OLE_SUPPORT #include <afxole.h> // MFC OLE classes #include <afxodlgs.h> // MFC OLE dialog classes #include <afxdisp.h> // MFC Automation classes #endif // _AFX_NO_OLE_SUPPORT #ifndef _AFX_NO_DB_SUPPORT #include <afxdb.h> // MFC ODBC database classes #endif // _AFX_NO_DB_SUPPORT #pragma warning( disable : 4192 ) //Указать пути расположения библиотек! #import "d:\SDK\lib\ksConstants3D.tlb" no_namespace named_guids #import "d:\SDK\lib\ksConstants.tlb" no_namespace named_guids #import "d:\SDK\lib\kAPI2D5COM.tlb" no_namespace named_guids #import "d:\SDK\lib\kAPI3D5COM.tlb" no_namespace named_guids #import "d:\SDK\lib\kAPI7.tlb" no_namespace named_guids #pragma warning( once : 4192 ) #ifndef __LHEAD3D_H #include <LHead3d.h> #endif #ifndef __LIBTOOL_H #include <libtool.h> #endif //{{AFX_INSERT_LOCATION}} #endif // !defined(__STDAFX_H) 67 Далее приводится пример кода, позволяющий создать новый документ в 3D-деталь с указанием одноименного имени. // Головная функция библиотеки void WINAPI LIBRARYENTRY( UINT comm ) { IDocument3DPtr Doc3d( ksGet3dDocument(), false ); Doc3d->Create( false, true ); Doc3d->SetAuthor( _T( "Иванов Андрей" ) ); Doc3d-> SetComment(_T("Проектирование прикладных библиотек в API 3D")); Doc3d->SetFileName(_T("C:\\Деталь.m3d" )); Doc3d->UpdateDocumentParam(); Doc3d->Save(); Doc3d->Close(); } В первой строке вышеприведенного кода создается указатель на интерфейс IDocument3DPtr трехмерного документа, который в последствии необходимо использовать для обращения к методам и свойствам указанного интерфейса. Далее по методу Create в прикладной библиотеке производится создание документа. Первый параметр указывает на признак режима редактирования документа (TRUE - невидимый режим, FALSE - видимый режим), второй параметр отвечает за тип документа (TRUE - деталь, FALSE сборка). Следующие несколько строк отвечают за свойства документа (имя автора - SetAuthor, комментарий к проекту- SetComment, имя файла для записи- SetFileName). За обновление документа, запись модели на носитель информации и закрытие документа отвечают последние три метода в тексте функции (UpdateDocumentParam, Save, Close). 6.1. Построение твердотельных деталей посредством операций вращения и выдавливания Принципы построения твердотельных моделей для ряда CAD/CAM систем имеют общие закономерности получения форм деталей. Изначально необходимо выбрать плоскость и выполнить построение эскиза, применяя набор инструментальных средств интегрированной среды системы посредством геометрических примитивов (линии, дуги окружностей, сплайновые кривые и т.д). Эскиз выполняется с учетом требуемых размеров и компонентов, позволяющих однозначно определить его на выбранной плоскости. Дальнейшие действия над эскизом осуществляются путем операций, зарезервированных в системе CAD/CAM, которые задают условия 68 формирования конечной твердотельной модели. Например, для того, чтобы получить объемный цилиндр в пространстве, необходимо в основании объекта начертить окружность и, посредством операции выдавливания с указанием высоты подъема, сформировать твердотельную модель. Для операции вращения кроме эскиза на плоскости основным условием построения является наличие осевой линии, вокруг которой контур эскиза сформирует требуемый твердотельный элемент. Далее приводится механизм построения твердотельных моделей для вышеуказанных операций путем программной реализации в системе Компас 3D. Для этой цели будет модифицирован код программы из предыдущего раздела путем добавления двух функций, строящих тела методом выдавливания и вращения. // Описания используемых функций void CreateExtrusion( IPartPtr& part ); void OperationRotated( IPartPtr& part ); // Головная функция библиотеки void WINAPI LIBRARYENTRY( UINT comm ) { IDocument3DPtr Doc3d( ksGet3dDocument(), false ); Doc3d->Create( false, true ); Doc3d->SetAuthor( _T( "Иванов Андрей" ) ); Doc3d->SetComment(_T("Проектирование прикладных библиотек с использованием API 3D")); Doc3d->SetFileName(_T("C:\\Деталь.m3d" )); IPartPtr part( Doc3d->GetPart( pNew_Part ), false ); if ( part ) { switch ( comm ) { case 1 : CreateExtrusion (part); break;// операция выдавливания case 2 : OperationRotated (part ); break; // операции вращения } } Doc3d->UpdateDocumentParam(); Doc3d->Save(); } // Оперция выдавливания, работа с экизом void CreateExtrusion( IPartPtr& part ) { // Создадим новый эскиз IEntityPtr entitySketch( part->NewEntity(o3d_sketch), false ); if ( entitySketch ) { //Получить указатель на интерфейс параметров объектов и //элементов ISketchDefinitionPtr sketchDefinition( IUnknownPtr( entitySketch->GetDefinition(), false ) ); if ( sketchDefinition ) { // Получим интерфейс базовой плоскости XOY IEntityPtr basePlane( part->GetDefaultEntity (o3d_planeXOY), false); // Установка параметров эскиза // Установим плоскость XOY базовой для эскиза sketchDefinition->SetPlane( basePlane ); // Угол поворота эскиза sketchDefinition->SetAngle( 45 ); // Создадим эскиз entitySketch->Create(); //При построении эскиза пользуемся элементами 2D API //Координаты ключевых точек и значение радиуса //(для окружностей) struct position { double x; 69 am[0].x=26.0564;am[0].y=37.0658; am[1].x=80.5036;am[1].y=-17.3814; am[2].x=91.8173;am[2].y=-6.0677;am[2].rad=16; am[3].x=103.1310;am[3].y=5.2460; am[4].x=81.9178;am[4].y=26.4592; am[5].x=88.9889;am[5].y=33.5302;am[5].rad=10; am[6].x=81.9178;am[6].y=40.6013; am[7].x=120.1016;am[7].y=78.7851; am[8].x=93.9387;am[8].y=104.9480; am[9].x=56.1084;am[9].y=40.9549;am[9].rad=10; am[10].x=73.0790;am[10].y=57.9254;am[10].rad=5; am[11].x=90.0496;am[11].y=74.8960;am[11].rad=10; //Войти в режим редактирования эскиза if ( sketchDefinition->BeginEdit() ) { reference p; //Определение контура Contour(1); LineSeg(am[0].x,am[0].y,am[1].x,am[1].y,1); ArcByPoint (am[2].x,am[2].y,am[2].rad,am[1].x,am[1].y,am[3].x,am[3].y,1,1); LineSeg(am[3].x,am[3].y,am[4].x,am[4].y,1); ArcByPoint (am[5].x,am[5].y,am[5].rad,am[4].x,am[4].y,am[6].x,am[6].y,-1,1); LineSeg(am[6].x,am[6].y,am[7].x,am[7].y,1); LineSeg(am[7].x,am[7].y,am[8].x,am[8].y,1); LineSeg(am[8].x,am[8].y,am[0].x,am[0].y,1); p = EndObj(); Circle(am[9].x,am[9].y,am[9].rad,1); Circle(am[10].x,am[10].y,am[10].rad,1); Circle(am[11].x,am[11].y,am[11].rad,1); // Выйти из режима редактирования эскиза sketchDefinition->EndEdit(); } //Очищаем динамически выделенную память delete [] am; // Оперция выдавливани IEntityPtr entityExtrusion( part->NewEntity( o3d_baseExtrusion ), false); if ( entityExtrusion ) { // Интерфейс базовой операции выдавливания IBaseExtrusionDefinitionPtr extrusionDefinition( IUnknownPtr( entityExtrusion->GetDefinition(), false ) ); if ( extrusionDefinition ) { // Установка параметров операции выдавливания // Направление выдавливания ( dtNormal - прямое // направление, для тонкой стенки - наружу, // dtReverse-обратное направление, для тонкой стенки - внутрь // dtBoth - в обе стороны, dtMiddlePlane от средней плоскости ) extrusionDefinition->SetDirectionType( dtNormal ); // Изменить параметры выдавливания в одном направлении 70 extrusionDefinition->SetSideParam( true, // Направление выдавливания ( TRUE - прямое направление, // FALSE - обратное направление ) etBlind, // Тип выдавливания ( etBlind - строго на глубину, // etThroughAll - через всю деталь, etUpToVertexTo - на //расстояние до вершины, //etUpToVertexFrom-на расстояние за вершину,etUpToSurfaceTo - на // расстояние до поверхности, etUpToSurfaceFrom - на расстояние //за поверхность, // etUpToNearSurface - до ближайшей поверхности ) 10, // Глубина выдавливания 0, // Угол уклона false ); // Направление уклона ( TRUE - уклон наружу, FALSE //уклон внутрь ) extrusionDefinition->SetSketch( entitySketch ); // Эскиз операции выдавливания // Создать операцию выдавливания entityExtrusion->Create(); MessageT( _T("Операция выдавливания") ); } } } } } // Операции вращения void OperationRotated( IPartPtr & part ) { // Создадим новый эскиз IEntityPtr entitySketch( part->NewEntity(o3d_sketch), false ); if ( entitySketch ) { // Получить указатель на интерфейс параметров объектов // Интерфейс свойств эскиза ISketchDefinitionPtr sketchDefinition( IUnknownPtr( entitySketch->GetDefinition(), false ) ); if ( sketchDefinition ) { // Получим интерфейс базовой плоскости XOY IEntityPtr basePlane( part->GetDefaultEntity( o3d_planeXOY ), false ); // Установка параметров эскиза sketchDefinition->SetPlane( basePlane ); // Установим плоскость XOY базовой для эскиза // Создадим эскиз entitySketch->Create(); // Войти в режим редактирования эскиза if ( sketchDefinition->BeginEdit() ) { // Введем новый эскиз reference p; //Определение контура Contour(1); LineSeg( 0, 0, 40, 0, 1); LineSeg( 40, 0, 48, 6, 1); LineSeg( 48, 6, 58, 6, 1); 71 LineSeg( 58, 6, 58, 28, 1); LineSeg( 58, 28, 75, 28, 1); LineSeg( 75, 28, 85, 18, 1); LineSeg( 85, 18, 85, -10, 1); LineSeg( 85, -10, 70, -10, 1); LineSeg( 70, -10, 70, -22, 1); LineSeg( 70, -22, 0, -22, 1); LineSeg( 0, -22, 0, 0, 1); p = EndObj(); //Осевая линия LineSeg( -5, -37, 90, -37, 3); // Выйти из режима редактирования эскиза sketchDefinition->EndEdit(); } // Операции вращения IEntityPtr entityRotate( part->NewEntity( o3d_baseRotated ), false); if ( entityRotate ) { // Получить указатель на интерфейс параметров объектов // Интерфейс базовой операции вращения IBaseRotatedDefinitionPtr baseRotatedDefinition( IUnknownPtr( entityRotate->GetDefinition(), false) ); if ( baseRotatedDefinition ) { baseRotatedDefinition->SetToroidShapeType( true ); // Признак тороида ( TRUE - тороид, FALSE - сфероид ) baseRotatedDefinition->SetDirectionType( dtBoth ); // Направление вращения ( dtNormal - прямое направление, для //тонкой стенки - наружу // dtReverse - обратное направление, для тонкой стенки - внутрь, //dtBoth - в обе стороны, // dtMiddlePlane - от средней плоскости) // Изменить параметры выдавливания в одном направлении baseRotatedDefinition->SetSideParam( true, // Направление вращения ( TRUE - прямое, FALSE - обратное ) 0 ); // Угол вращения // Изменить параметры выдавливания в одном направлении baseRotatedDefinition->SetSideParam( false, // Направление вращения ( TRUE - прямое, FALSE - обратное ) 275 ); // Угол вращения baseRotatedDefinition->SetSketch( entitySketch ); // Эскиз операции выдавливания // Создать операцию entityRotate->Create(); MessageT( _T("Базовая операция вращения") ); } } } } } Эскизы для получения твердотельных моделей методами выдавливания и вращения показаны на рисунках 31 и 32. 24 48 72 96 72 37 20 2 окр 18 ,5 10 R10 93 R16 Рис. 31. Программная реализация эскиза получения модели посредством операции выдавливания 130 30 54 74 86 10•45 40 48 58 70 85 Рис. 32. Программная реализация эскиза получения модели посредством операции вращения Спроектированные объекты в результате выполнения прикладной библиотеки показаны на рисунках 33 и 34. Рис. 33. Твердотельная модель, полученная операцией “выдавливания” 73 Рис. 34. Твердотельная модель, полученная операцией “вращения” Функции по созданию моделей (вращением и выдавливанием) в тексте прикладной библиотеки содержат подробные комментарии, однако необходимо следовать некоторому алгоритму действий при создании объектов в объеме. Для построения тел методом выдавливания последовательность действий будет следующая: - Создать новый объект-эскиз. Для этого следует подготовить элемент построения эскиза посредством интерфейса IEntityPtr: IEntityPtr entitySketch( part->NewEntity(o3d_sketch), false ); - Получить интерфейс некоторой опорной плоскости и установить параметры эскиза: IEntityPtr basePlane( part->GetDefaultEntity( o3d_planeXOY ), false ); sketchDefinition->SetPlane( basePlane ); - Создать эскиз и зайти в режим его редактирования: entitySketch->Create(); if ( sketchDefinition->BeginEdit() ) { //Здесь формируется объект, состоящий из 2D графических //примитивов. Если объект имеет сложно-выраженную структуру, то //построение ведется с указанием контура объекта //Для операции вращения необходимо в эскизе наличие осевой //линии! sketchDefinition->EndEdit(); } - Создать операцию для получения модели методом вращения и указать параметры, определяющие режимы для проведения данной процедуры (направление вращения, угол, сведения о том, является ли будущий объект тонкостенным, ссылка на эскиз для проведения заданной операции). 74 IEntityPtr entityRotate( part->NewEntity( o3d_baseRotated ), false); if ( entityRotate ) { IBaseRotatedDefinitionPtr baseRotatedDefinition( IUnknownPtr( entityRotate->GetDefinition(), false) ); if ( baseRotatedDefinition ) { baseRotatedDefinition->SetToroidShapeType( true ); baseRotatedDefinition->SetDirectionType( dtBoth ); baseRotatedDefinition->SetThinParam( true,dtBoth,1,1); baseRotatedDefinition->SetSideParam( true,0); baseRotatedDefinition->SetSideParam( false, 275); baseRotatedDefinition->SetSketch( entitySketch ); entityRotate->Create(); } Значительное количество элементов построения имеют указатель на интерфейс IEntityPtr. Для доступа к списку элементов служит функция EntityCollection. Перечень всех типов объектов документа-модели EntityCollection приведен ниже: Элементы системы координат o3d_unknown 0 неизвестный (включает все объекты) o3d_planeXOY 1 плоскость XOY o3d_planeXOZ 2 плоскость XOZ o3d_planeYOZ 3 плоскость YOZ o3d_pointCS 4 точка начала системы координат Элементы детали эскиз поверхность ребро вершина o3d_sketch o3d_face o3d_edge o3d_vertex 5 6 7 8 o3d_axis2Planes o3d_axis2Points o3d_axisConeFace o3d_axisEdge o3d_axisOperation o3d_planeOffset o3d_planeAngle o3d_plane3Points o3d_planeNormal Конструктивные элементы 9 ось по двум плоскостям 10 ось по двум точкам 11 ось конической грани 12 ось, проходящая через ребро 13 ось операции 14 смещённая плоскость 15 плоскость под углом 16 плоскость по 3-м точкам 17 нормальная плоскость 75 o3d_planeTangent 18 касательная плоскость o3d_planeEdgePoint 19 плоскость через ребро и вершину o3d_planeParallel 20 плоскость через вершину параллельно другой плоскости o3d_planePerpendicular 21 плоскость через вершину перпендикулярно ребру o3d_planeLineToEdge 22 плоскость через ребро параллельно/перпендикулярно другому ребру o3d_planeLineToPlane 23 плоскость через ребро параллельно /перпендикулярно грани o3d_baseExtrusion o3d_bossExtrusion o3d_cutExtrusion o3d_baseRotated o3d_bossRotated o3d_cutRotated o3d_baseLoft o3d_bossLoft o3d_cutLoft o3d_chamfer o3d_fillet o3d_meshCopy o3d_circularCopy o3d_curveCopy o3d_circPartArray сборки o3d_meshPartArray o3d_curvePartArray o3d_derivPartArray o3d_incline o3d_shellOperation o3d_ribOperation o3d_baseEvolution 26 27 28 29 32 34 35 36 37 38 42 44 Операции 24 базовая операция выдавливания 25 приклеивание выдавливанием вырезать выдавливанием базовая операция вращения приклеивание вращением вырезать вращением 30 базовая операция по сечениям 31 приклеивание по сечениям вырезать по сечениям 33 операция "фаска" операция "скругление" операция копирования по сетке операция копирования по концентрической сетке операция копирования по кривой операция массив по концентрической сетке для 39 операция массив по сетке для сборки 40 операция массив по кривой для сборки 41 операция массив по образцу для сборки операция "уклон" 43 операция "оболочка" операция "ребро жесткости" 45 кинематическая операция 76 o3d_bossEvolution o3d_cutEvolution 47 o3d_mirrorOperation o3d_mirrorAllOperation 49 o3d_cutByPlane 50 o3d_cutBySketch 51 o3d_holeOperation 46 приклеить кинематически вырезать кинематически 48 операция "зеркальный массив" операция "зеркально отразить все" операция "сечение поверхностью" операция "сечение эскизом" 52 отверстие o3d_polyline o3d_conicSpiral o3d_spline o3d_cylindricSpiral o3d_importedSurface o3d_thread o3d_EvolutionSurface o3d_ExtrusionSurface o3d_RotatedSurface o3d_LoftSurface o3d_MacroObject o3d_UnionComponents o3d_MoldCavity Кривые 53 ломаная коническая спираль сплайн 56 цилиндрическая спираль 57 импортированная условное изображение резьбы кинематическая поверхность поверхность выдавливания 61 поверхность вращения поверхность по сечениям макрообъект 3D операция объединения компонентов операция вычитания компонентов 54 55 58 59 60 62 63 64 65 Объединенные типы объектов для создания EntityCollection o3d_constrElement 109 конструктивные элементы-плоскости и оси (конструктивные от o3d_axis2Planes до o3d_plane3Points) o3d_operationElement 110 операции (от o3d_baseExtrusion до o3d_cylindricSpiral) o3d_curveElement 111 кривые (пространственные и ребра) Внимательно изучив код указанных выше функций разработанной прикладной библиотеки КОМПАС 3D, аналогичным образом создаются функции построения моделей по сечениям и подготавливаются операции: оболочка, уклон, сечение плоскостью, сечение эскизом. 77 Кроме того, в системе реализован функционал по построению фасок и скруглений, выполнение параметрических моделей, подготовки сборочных узлов с историей построения, назначение объектам атрибутов (цвет, материал и т.д.) 78 ЗАКЛЮЧЕНИЕ В пособии изложен материал, соответствующий основной образовательной программе кафедры, представлены методики подготовки к геометрическому проектированию и выполнению расчетов на языке С++ в интегрированной среде разработки программного обеспечения. Определена последовательность работы над разработкой прикладных библиотек, использования мастеров и шаблонов, позволяющих оптимизировать процессы проектирования станочного оборудования с целью усовершенствования их конструкции. Даны рекомендации и определены направления информационного поиска прогрессивных технических решений. Наиболее сложные методические рекомендации иллюстрированы примерами и текстами с программным кодом прикладных библиотек. Во всех разделах приводятся схемы и модели, примеры подробно прокомментированы. Пособие обеспечивает усвоение учебной информации, имеющей высокий уровень практической значимости, позволят использовать оптимальные технологии обучения и виды взаимодействия преподавателя и студентов, способствующие их целенаправленной подготовке к будущей практической деятельности. 79 БИБЛИОГРАФИЧЕСКИЙ СПИСОК Аверин, В.Н. Компьютерная инженерная графика / В.Н. Аверин. - М.: Academia, 2018. - 174 c. 2. Аммерааль, Леен STL для программистов на C++; М.: ДМК — Москва, 2014. — 239 c. 3. Большаков, В.П. Инженерная и компьютерная графика: Учебное пособие / В.П. Большаков, В.Т. Тозик, А.В. Чагина. - СПб.: БХВ-Петербург, 2013. - 288 c. 4. Герасимов, Анатолий Компас-3D V10 (+ CD-ROM) / Анатолий Герасимов. - М.: БХВ-Петербург, 2015. - 976 c. 5. Дегтярев, В.М. Инженерная и компьютерная графика: Учебник / В.М. Дегтярев. - М.: Академия, 2017. - 160 c. 6. Кидрук, Максим Компас-3D V10 на 100% / Максим Кидрук. - М.: Питер, 2016. - 560 c. 7. Компас-3D v11. Эффективный самоучитель / А.М. Доронин и др. - М.: Наука и техника, 2015. - 688 c. 8. Коплиен Дж. Программирование на С++ /Дж. Коплиен. – – СПб.: Питер, 2015. – 480 с. 9. Мейерс С. Эффективное использование С++. 35 новых рекомендаций по улучшению ваших программ и проектов. — М.: ДМК Пресс, 2014. — 294с. 10. Самсонов, В. В. Автоматизация конструкторских работ в среде Компас3D / В.В. Самсонов, Г.А. Красильникова. - М.: Academia, 2016. - 224 c. 11. Талалай, Павел Компас-3D V11 на примерах (+ DVD-ROM) / Павел Талалай. - М.: БХВ-Петербург, 2016. - 616 c. 12. Стивен Прата. Язык программирования C++ (C++11). Лекции и упражнения, 6-е издание — М.: Вильямс, 2012. — 1248 с. 13. Шилдт Г. С++ Базовый курс. 3-е изд. / Г.Шилдт.– М.: Вильямс, 2012. – 624 с. 14. London J. Modeling Derivatives in C++ / London J. Wiley, 2015 -841p. 1. 80 Учебное издание Юров Алексей Николаевич Паринов Максим Викторович Ачкасов Александр Владимирович Зольников Константин Владимирович Меерсон Вера Эдуардовна ИНСТРУМЕНТАЛЬНЫЕ СРЕДСТВА ИНФОРМАЦИОННЫХ СИСТЕМ Учебное пособие Редактор А.С. Люлина Подписано в печать 01.02.2021. Формат 60×90 /16. Усл. печ. л. 9,7. Уч.-изд. л. . Тираж экз. Заказ ФГБОУ ВО «Воронежский государственный лесотехнический университет имени Г.Ф. Морозова» РИО УМУ ФГБОУ ВО «ВГЛТУ». 394087, г. Воронеж, ул. Тимирязева, 8 УОП ФГБОУ ВО «ВГЛТУ». 394087, г. Воронеж, ул. Докучаева, 10