Не могу сделать скругления пересекающих обєктов???

Автор Nesh, 03.02.06, 12:41:32

« предыдущая - следующая »

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

Nesh

Напишите пример как сделать скргуления пересекающих обєктов (ksLineSeg) . В хелпах ненашел. Заранее спасибо!!! :beer:

IronMaxxx

Вот у меня готовая функция. Использую уже около двух лет - очень сокращает время при создании скруглений между двумя отрезками. Функция возвращает указатель на макрообъект - так его можно еще копировать, масштабировать и пр.

function CON_(doc: ksDocument2D;  ks: KompasObject; r1, r2: reference; rad: double; index: integer;
                direction: smallint; parms: smallint): reference;
// входные параметры
// doc - ну это понятно :)
// r1, r2 - указатели на сопрягаемые отрезки (они необязательно должны сходиться в одной точке - функция сама их "обрежет" и округлит, как положено)
// rad - радиус скругления
// index, direction, parms - параметры, использующиеся в методах ksCouplingLineLine, ksArcByPoint и интерфейсе ksCON...
var math: ksMathematic2D;
    Con: ksCON;
    parms1, parms2: ksLineSegParam;
    ang1, ang2: double;
begin
  Result := 0;
  if index > 4 then exit;
  if (direction <> 1) and (direction <> -1) then exit;
  if (parms <> 1) and (parms <> 2) then exit;
  Con := ksCON(ks.GetParamStruct(ko_CON));
  math := ksMathematic2D(ks.GetMathematic2D);
  if (Con = nil) or (math = nil) then exit;

// считываем параметры отрезков
  parms1 := ksLineSegParam(ks.GetParamStruct(ko_LineSegParam));
  parms2 := ksLineSegParam(ks.GetParamStruct(ko_LineSegParam));

  doc.ksGetObjParam(r1, parms1, ALLPARAM);
  doc.ksGetObjParam(r2, parms2, ALLPARAM);

//определяем угол наклона отрезков к оси Х
  ang1 := RadToDeg(arctan( (parms1.y1 - parms1.y2)/(parms1.x1 - parms1.x2) ));
  ang2 := RadToDeg(arctan( (parms2.y1 - parms2.y2)/(parms2.x1 - parms2.x2) ));

//определяем параметры скругления
  math.ksCouplingLineLine(parms1.x1, parms1.y1, ang1, parms2.x1, parms2.y1, ang2, rad, Con);

//строим скругление
  doc.ksMacro(0);
    doc.ksArcByPoint(Con.GetXc(index), Con.GetYc(index), rad, Con.GetX1(index), Con.GetY1(index),
      Con.GetX2(index), Con.GetY2(index), direction, 1);
    if parms = 1 then
      begin
        doc.ksLineSeg(parms1.x1, parms1.y1, Con.GetX1(index), Con.GetY1(index), 1);
        doc.ksLineSeg(parms2.x1, parms2.y1, Con.GetX2(index), Con.GetY2(index), 1);
      end
        else
          begin
            doc.ksLineSeg(parms1.x2, parms1.y2, Con.GetX1(index), Con.GetY1(index), 1);
            doc.ksLineSeg(parms2.x2, parms2.y2, Con.GetX2(index), Con.GetY2(index), 1);
          end;

//результат - указатель на макрообъект
  Result := doc.ksEndObj;

  doc.ksDeleteObj(r1);
  doc.ksDeleteObj(r2);
end;

С тебя пиво, тавагищ... :o:

Nesh

Спасибо ОЧЕНЬ БОЛЛЬШОЕ. ПИВКО С МЕНЯ  :fr:. Очень помогло...
много код правда но разобрался...

Gek

А в API не реализовано обычное скругление (Fillet) сходящихся в одной точке отрезков? У меня задача попроще.
В хелпе нашел только Fillet для 3D. Самому делать процедуру как-то нехоца :~

A-Lex

А что такое параметр  parms используемый в интерфейсе ksCON?

Prog2

A-Lex, вероятно, Вы имели ввиду переменные parms1, parms2.
parms1, parms2: ksLineSegParam;

По сути это структуры параметров, описывающие соответственно первый и второй отрезки, которые нужно скруглить (координаты начала и конца отрезков, стиль линии).

A-Lex

Что-то у меня пока не получается - divizion by zero. Почему-то получаются очень малые величины значений (в -304 степени!). Ладно, пока разбираюсь...

Prog2

Обратите внимание на следующие строки:

//определяем угол наклона отрезков к оси Х
  ang1 := RadToDeg(arctan( (parms1.y1 - parms1.y2)/(parms1.x1 - parms1.x2) ));
  ang2 := RadToDeg(arctan( (parms2.y1 - parms2.y2)/(parms2.x1 - parms2.x2) ));

Здесь нет проверки деления на ноль (что очень вероятно при некоторых условиях: (parms1.x1 - parms1.x2) - вполне может оказаться нулём ).
Стоит слегка усовершенствовать код, и должно заработать.

A-Lex

Вся проблемма этого кода в том, что строится скругление только для отрезков не параллельных осям координат (хотя на мой взгляд, таких на чертежах большинство!)
Вот отредактированный код:
function CON_(doc: ksDocument2D;  Kompas: KompasObject; p1, p2: reference; rad: double; index: integer;
                direction: smallint; parms: smallint): reference;
// входные параметры
// doc - ну это понятно
// p1, p2 - указатели на сопрягаемые отрезки (они необязательно должны сходиться в одной точке - функция сама их "обрежет" и округлит, как положено)
// rad - радиус скругления
// index, direction, parms - параметры, использующиеся в методах ksCouplingLineLine, ksArcByPoint и интерфейсе ksCON...
var math: ksMathematic2D;
    Con: ksCON;
    parms1, parms2: ksLineSegParam;
    ang1, ang2: double;

begin
  Result := 0;
  if index > 4 then exit;
  if (direction <> 1) and (direction <> -1) then exit;
  if (parms <> 1) and (parms <> 2) then exit;
  Con := ksCON(Kompas.GetParamStruct(ko_CON));
  math := ksMathematic2D(Kompas.GetMathematic2D);
  if (Con = nil) or (math = nil) then exit;

// считываем параметры отрезков
  parms1 := ksLineSegParam(Kompas.GetParamStruct(ko_LineSegParam));
  parms2 := ksLineSegParam(Kompas.GetParamStruct(ko_LineSegParam));

  doc.ksGetObjParam(p1, parms1, ALLPARAM);
  doc.ksGetObjParam(p2, parms2, ALLPARAM);

//определяем угол наклона отрезков к оси Х
  if (parms1.x1 - parms1.x2)=0 then ang1 :=90 else //если вертикаль
  ang1 := RadToDeg(arctan( (parms1.y1 - parms1.y2)/(parms1.x1 - parms1.x2) ));
  if (parms1.y1 - parms1.y2)=0 then ang1 :=0;     //если горизонталь
  if (parms2.x1 - parms2.x2)=0 then ang2 :=90 else //если вертикаль
  ang2 := RadToDeg(arctan( (parms2.y1 - parms2.y2)/(parms2.x1 - parms2.x2) ));
  if (parms2.y1 - parms2.y2)=0 then ang2 :=0;     //если горизонталь
 
//определяем параметры скругления
  math.ksCouplingLineLine(parms1.x1, parms1.y1, ang1, parms2.x1, parms2.y1, ang2, rad, Con);

//строим скругление
  doc.ksMacro(0);
    doc.ksArcByPoint(Con.GetXc(index), Con.GetYc(index), rad, Con.GetX1(index), Con.GetY1(index),
      Con.GetX2(index), Con.GetY2(index), direction, 1);
    if parms = 1 then
      begin
        doc.ksLineSeg(parms1.x1, parms1.y1, Con.GetX1(index), Con.GetY1(index), 1);
        doc.ksLineSeg(parms2.x1, parms2.y1, Con.GetX2(index), Con.GetY2(index), 1);
      end
        else
          begin
            doc.ksLineSeg(parms1.x2, parms1.y2, Con.GetX1(index), Con.GetY1(index), 1);
            doc.ksLineSeg(parms2.x2, parms2.y2, Con.GetX2(index), Con.GetY2(index), 1);
          end;

//результат - указатель на макрообъект
  Result1 := doc.ksEndObj;

  doc.ksDeleteObj(p1);
  doc.ksDeleteObj(p2);
end;

P.S. Всё строится, только для 3d операций не пойдет - строится макрообъект!
Вот как нибудь его програмно разрушить...

Prog2

Вот такую модификацию кода я и имел ввиду. :)

Про макрообъект.
Если макро не нужен, то зачем его создавать: закомментируйте строки doc.ksMacro(0); и Result1 := doc.ksEndObj; и макрообъект не будет создан. Ну и функцию CON_(...) в процедуру переделать нужно будет (по-моему, в делфях так), чтобы ничего не возвращала.

А если создать макро очень хочется, но на каком-то этапе его необходимо разрушать, то можно в нужный момент вызвать ksDestroyObjects(refMacro) - макрообъект будет разрушен (refMacro - указатель на объект).