Переход в локальную систему координат

Автор antigrav, 09.05.25, 17:35:01

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

antigrav

Здравствуйте!
Есть такая задача. В документе компаса имеются точки (интерфейс точек IPoint3D). Координаты точек заданы в базовой системе координат документа. В документе также есть локальная система координат, не совпадающая с базовой. Требуется сохранить точки в файл, предварительно переведя их из базовой в локальную систему координат. Собственно, вопрос в том, как выполнить это преобразование (переход к локальной системе) командами компаса? У интерфейса IPart7 есть метод TransferObject, который, как будто, для этого и предназначен. Приходилось ли кому-нибудь его использовать? Или есть другие варианты?

Lemieux

Цитата: antigrav от 09.05.25, 17:35:01Здравствуйте!
Есть такая задача. В документе компаса имеются точки (интерфейс точек IPoint3D). Координаты точек заданы в базовой системе координат документа. В документе также есть локальная система координат, не совпадающая с базовой. Требуется сохранить точки в файл, предварительно переведя их из базовой в локальную систему координат. Собственно, вопрос в том, как выполнить это преобразование (переход к локальной системе) командами компаса? У интерфейса IPart7 есть метод TransferObject, который, как будто, для этого и предназначен. Приходилось ли кому-нибудь его использовать? Или есть другие варианты?
Для таких целей я написал структуры Point3d, Vector3d, Matrix3d. Что интересно, в API C3D есть такие структуру, но разработчики API КОМПАС решили, что пользователи должны страдать.

antigrav

Цитата: Lemieux от 09.05.25, 17:38:40Для таких целей я написал структуры Point3d, Vector3d, Matrix3d. Что интересно, в API C3D есть такие структуру, но разработчики API КОМПАС решили, что пользователи должны страдать.
То есть Вы считаете, что метод TransferObject не подходит?

Lemieux

Цитата: antigrav от 09.05.25, 17:45:36То есть Вы считаете, что метод TransferObject не подходит?
Так Вы поэкспериментируйте. Сделайте ЛСК активной и посмотрите, что выдаст метод. Я просто брал матрицу трансформации от ЛСК и умножал на точку.

antigrav

Цитата: Lemieux от 09.05.25, 17:48:51Так Вы поэкспериментируйте. Сделайте ЛСК активной и посмотрите, что выдаст метод. Я просто брал матрицу трансформации от ЛСК и умножал на точку.

В том то и дело, что не могу понять, как правильно его применить.

Lemieux

Цитата: antigrav от 09.05.25, 17:49:50В том то и дело, что не могу понять, как правильно его применить.
Он работает как вот этот функционал сущностей КОМПАС.
1.png2.png

antigrav

Цитата: Lemieux от 09.05.25, 18:22:58Он работает как вот этот функционал сущностей КОМПАС.
1.png2.png

Хорошо, спасибо!

UU

Проблема активировать нужную ЛСК?

antigrav

Цитата: UU от 10.05.25, 08:39:29Проблема активировать нужную ЛСК?

Вообще, я хотел найти API-команды компаса, которые позволяют выполнять аффинные преобразования для 3D объектов в документе. Понятно, что эти команды можно реализовать самостоятельно, через собственные векторы и матрицы. Но зачем, если такое встроено в API? Возможно, в терминологии компаса, это и называется "активировать нужную ЛСК". Я пока только изучаю Компас и его API. Что-то получается, но многое - нет. Примеров использования не хватает.

Student2025

Вроде так активировать

Безымянный.png

Заходите сюда - "C:\Program Files\ASCON\KOMPAS-3D v21\SDK\SDK.chm"
или в другую версию Компаса и в поиске вбиваете ключевые слова.

Lemieux

Цитата: antigrav от 10.05.25, 10:01:12Но зачем, если такое встроено в API?
Там шляпа встроена. Пусть разработчики АСКОН сами работают с массивами и страдают!

Student2025

UU писал что у него база кода на все случаи - получается же их сами разработчики скидывают ?
Там черт ногу сломит что делать с этим массивом и как вообще дальше развивать код..

antigrav

В итоге я отказался от использования классов API для перехода в локальную систему координат. То есть пошел по пути Lemieux. А именно, по локальной системе координат, установленной в документе Компаса, построил матрицу 4x4, взял к ней обратную,  умножил на нее все векторы точек и сохранил результат в файле. Вроде бы получил то, что нужно.

Student2025

Цитата: antigrav от 10.05.25, 19:27:25В итоге я отказался от использования классов API для перехода в локальную систему координат. То есть пошел по пути Lemieux. А именно, по локальной системе координат, установленной в документе Компаса, построил матрицу 4x4, взял к ней обратную,  умножил на нее все векторы точек и сохранил результат в файле. Вроде бы получил то, что нужно.

Не кому не чего не понятно - напишите по подробней что да как если конечно решили этот вопрос.

Lemieux

Цитата: antigrav от 10.05.25, 19:27:25В итоге я отказался от использования классов API для перехода в локальную систему координат. То есть пошел по пути Lemieux. А именно, по локальной системе координат, установленной в документе Компаса, построил матрицу 4x4, взял к ней обратную,  умножил на нее все векторы точек и сохранил результат в файле. Вроде бы получил то, что нужно.
Если провести тесты, то потом ещё выяснится, что работать со своими структурами гораздо быстрее чем с методами API.

Lemieux

Цитата: Student2025 от 10.05.25, 20:22:13Не кому не чего не понятно - напишите по подробней что да как если конечно решили этот вопрос.
Всё тут понятно.

antigrav

Цитата: Student2025 от 10.05.25, 20:22:13Не кому не чего не понятно - напишите по подробней что да как если конечно решили этот вопрос.

Хорошо. Немного соберусь с мыслями, и напишу. Может кому-то пригодится. К сожалению, очень много времени уходит на поиск элементарных вещей.

Vi2

Цитата: Lemieux от 09.05.25, 17:38:40Для таких целей я написал структуры Point3d, Vector3d, Matrix3d. Что интересно, в API C3D есть такие структуру, но разработчики API КОМПАС решили, что пользователи должны страдать.
Есть такой файл SDK\Include\LMathUtil3D.h, который позволяет получать объекты с3д по интерфейсам.

// Экспортный номер - 20   kAPI3D5.dll
//-----------------------------------------------------------------------------
// Получить указатель на математический объект из объекта API.
// ---
MbRefItem * LIB_FUNC ksGetMathFromAPI( LPUNKNOWN pObj, long iObj );
+ Благодарностей: 1

antigrav

  Исходный документ модели показан на рис. 1. В нем есть «поверхность вращения». На поверхности построена кривая – «сплайн на поверхности». Сплайн на поверхности задается точками в криволинейных координатах U и V. Но мне не удалось через API обратиться к этим точкам. Через API вижу только их количество, а мне нужны их декартовы координаты. Поэтому сделал следующим образом. Построил «группу точек по кривой» по данному сплайну на поверхности. Затем занес эти точки в «сплайн по точкам». Теперь у меня появились точки уже в декартовых координатах. Далее добавил в документ локальную систему координат (ЛСК:1) и разместил ее так, чтобы она отличалась от базовой системы координат документа. Все это я проделал в визуальном режиме.
  Итак, я имею сплайн, построенный на наборе точек в декартовых координатах. Если посмотреть на значения координат точек (таблица на рис. 2), то можно увидеть, что они отложены в базовой системе координат документа, что естественно. Но мне нужно получить те же самые точки в локальной системе координат ЛСК:1 (выделена зеленым цветом на рис. 3) и записать их в текстовый файл. В этом суть задачи, которая должна быть решена программно. Далее фрагменты кода.
  TfKompasAPI – класс формы.

// инициализация документа Компас
procedure TfKompasAPI.GetNewKompasAPI;
begin
  newKompasAPI := nil;
  newKompasAPI := GetActiveOleObject('Kompas.Application.7') as IApplication;
  if Assigned(newKompasAPI) then
  begin
    newKompasAPI.visible := True;
    Report.Lines.Clear;
    Report.Lines.Add('Компас загружен');
  end else
  begin
    ShowMessage('Компас не загружен!');
    Exit;
  end;

  doc := nil;
  doc := newKompasAPI.ActiveDocument;
  if not Assigned(doc) then
  begin
    ShowMessage('Документ не получен!');
    Exit;
  end else
  begin
    Report.Lines.Add('Документ получен');
  end;
  doc3d := doc as IKompasDocument3D;
end;

// Обработчик кнопки сохранения точек в файле
procedure TfKompasAPI.SaveSplinePointsToFile(FName: string);
var
  p: ISpline3D;
begin
  p := FindSplinePoints('Сплайн:1');
  if not Assigned(p) then Exit;
  SaveSplinePointsToFile(p, FName);
end;

// Поиск сплайна по имени
function TfKompasAPI.FindSplinePoints(searched_name: string): ISpline3D;
var
  top: IPart7;
  aux_cont: IAuxiliaryGeomContainer;
  Splines3D: ISplines3D;
  spline3D: ISpline3D;
  count: Integer;
  I: Integer;
begin
  if not Assigned(doc3D) then Exit(nil);
  Result := nil;
  top := doc3D.TopPart;
  aux_cont := top as IAuxiliaryGeomContainer;
  Splines3D := aux_cont.Splines3D;
  count := Splines3D.Count;
  for I := 0 to Pred(count) do
  begin
    spline3D := Splines3D.Spline3D;
    if spline3D.Name = searched_name then
      Exit(spline3D);
  end;
end;

// Запись точек в файл
procedure TfKompasAPI.SaveSplinePointsToFile(spline: ISpline3D; FName: string);
var
  f: TextFile;
  I: Integer;
  x,y,z,tmp: Double;
  lcs: ILocalCoordinateSystem;
begin
  if not assigned(spline) then Exit;
  AssignFile(f, fname);
  Rewrite(f);
  try
    for I := 0 to Pred(spline.VertexCount) do
    begin
      spline.VertexParams.GetParamVertex({out}x, {out}y, {out}z, {out}tmp);

      lcs := FindLCS('ЛСК:1');
      TransferToLCS(lcs, {out}x, {out}y, {out}z);
      var spoint: string := '';
      spoint := spoint + FloatToStrF(x, ffFixed, 10, 3);
      spoint := spoint + '  ' + FloatToStrF(y, ffFixed, 10, 3);
      spoint := spoint + '  ' + FloatToStrF(z, ffFixed, 10, 3);
      spoint := StringReplace(spoint, ',', '.', []);
      WriteLn(f, spoint);
    end;
  finally
    CloseFile(f);
  end;
end;

// Поиск ЛСК по имени
function TfKompasAPI.FindLCS(searched_name: string): ILocalCoordinateSystem;
var
  top: IPart7;
  count: Integer;
  I: Integer;
  aux_cont: IAuxiliaryGeomContainer;
  lcs: ILocalCoordinateSystem;
begin
  if not Assigned(doc3D) then Exit(nil);
  Result := nil;
  top := doc3D.TopPart;
  aux_cont := top as IAuxiliaryGeomContainer;
  count := aux_cont.LocalCoordinateSystems.Count;
  for I := 0 to Pred(count) do
  begin
    lcs := aux_cont.LocalCoordinateSystems.LocalCoordinateSystem;
    if lcs.Name = searched_name then
    begin
      Result := lcs;
      Exit;
    end;
  end;
end;

// Перенос координат в локальную систему из базовой (абсолютной)
procedure TfKompasAPI.TransferToLCS(lcs: ILocalCoordinateSystem;
  var x, y, z: double);
var
  r_in: Vector4;
  r_out: Vector4;
  m: Matrix4;
begin
  r_in.X := x;
  r_in.Y := y;
  r_in.Z := z;
  r_in.W := 1;

  m := GetMatrixForLCS(lcs);
  m := m.InvertibleMatrix; // обратная матрица

  r_out := m * r_in;

  x := r_out.X;
  y := r_out.Y;
  z := r_out.Z;
end;

// Формирование матрицы для локальной системы координат
function TfKompasAPI.GetMatrixForLCS(lcs: ILocalCoordinateSystem): Matrix4;
var
  rx,ry,rz,ro: Vector4;
  a,b,c: double;
begin
  ro.X := lcs.X;
  ro.Y := lcs.Y;
  ro.Z := lcs.Z;
  ro.W := 1;

  lcs.GetVector(o3d_axisOX, {out}a, {out}b, {out}c);
  with rx do
  begin
    X := a;
    Y := b;
    Z := c;
    W := 0;
  end;
  rx := rx.Normalize;

  lcs.GetVector(o3d_axisOY, {out}a, {out}b, {out}c);
  with ry do
  begin
    X := a;
    Y := b;
    Z := c;
    W := 0;
  end;
  ry := ry.Normalize;

  lcs.GetVector(o3d_axisOZ, {out}a, {out}b, {out}c);
  with rz do
  begin
    X := a;
    Y := b;
    Z := c;
    W := 0;
  end;
  rz := rz.Normalize;

  Result.Col[0] := rx;
  Result.Col[1] := ry;
  Result.Col[2] := rz;
  Result.Col[3] := ro;
end;

Здесь Vector4 – класс вектора 1x4 в однородных координатах, Matrix4 – класс матрицы 4x4, имеющий метод для обращения матрицы.



+ Благодарностей: 1

Vi2

#19
Цитата: antigrav от 10.05.25, 23:21:25В нем есть «поверхность вращения». На поверхности построена кривая – «сплайн на поверхности». Сплайн на поверхности задается точками в криволинейных координатах U и V. Но мне не удалось через API обратиться к этим точкам. Через API вижу только их количество, а мне нужны их декартовы координаты

Интерфейс IAuxiliaryGeomContainer
Интерфейс контейнера объектов вспомогательной геометрии.

SplinesOnSurfaces - Интерфейс коллекции сплайнов на поверхностях

PS
HRESULT TransferObjects( VARIANT objects, ILocalCoordinateSystem * Lcs, VARIANT_BOOL holdPosition, BOOL * Result );
objects - в координатах СК IPart7 (детали?),  Lcs - нужная LCS,

Если параметр holdPosition == TRUE, то положение объекта в документе не изменяется.
Если параметр holdPosition == FALSE, то положение объекта будет задано относительно новой системы координат.

Если поэкспериментировать с holdPosition, то вроде должно сработать.

PPS
Интерфейс ILocalCSObject
Интерфейс подчиненного объекта ЛСК.
Интерфейс является дополнительным для следующих объектов:
– IPoint3D - Точка 3D,
– ISpline3D - Сплайн
Интерфейс позволяет получать и изменять параметры объектов в удобной для этого си�стеме координат. По умолчанию используется СК компонента

Может, этот интерфейс поможет проще программировать? Перенесли в ЛСК и сохранили в файл WriteToFile.