Как задать направление для offset?

Автор Тема: Как задать направление для offset?  (Прочитано 4143 раз)

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

Оффлайн AtomohodАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Здравствуйте!

Столкнулся с ситуацией когда нужно сделать offset линии. Пользуюсь кодом
Код - C# [Выбрать]
  1. DBObjectCollection acDbObjColl = acPoly.GetOffsetCurves(0.25);
  2.  
  3.             // Step through the new objects created
  4.             foreach (Entity acEnt in acDbObjColl)
  5.             {
  6.                 // Add each offset object
  7.                 acBlkTblRec.AppendEntity(acEnt);
  8.                 acTrans.AddNewlyCreatedDBObject(acEnt, true);
  9.             }
  10.  

команда работает, но только в одном направлении - по оси Х, а мне нужно еще и в отрицательную сторону Х. Значение offset с минусом задать нельзя. Как можно указать направление для команды?

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Re: Как задать направление для offset?
« Ответ #1 : 16-08-2018, 22:44:16 »
Почему же отрицательный нельзя? Как раз постоянно задаю отрицательный.  Для окружностей почему-то офсет внутрь нужен отрицательный, а для полилинии положительный

Отмечено как Решение Atomohod 19-08-2018, 20:59:37

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Как задать направление для offset?
« Ответ #2 : 16-08-2018, 22:48:18 »
Цитировать
If the offsetDist value is negative, it is usually interpreted as being an offset to make a smaller curve (that is, for an arc it would offset to a radius that is offsetDist less than the starting curve's radius). If the negative value has no meaning in terms of making the curve smaller, a negative offsetDist may be interpreted as an offset in the direction of smaller X,Y,Z WCS coordinates. This is not enforced, so custom entities can interpret the sign of the offsetDist value however they want.

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Re: Как задать направление для offset?
« Ответ #3 : 16-08-2018, 23:18:59 »
Что-то ребята явно перемудрили. Взяли бы нормаль к точке StartPoint, было б однозначно для любых кривых.

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Как задать направление для offset?
« Ответ #4 : 16-08-2018, 23:24:43 »
Что-то ребята явно перемудрили. Взяли бы нормаль к точке StartPoint, было б однозначно для любых кривых.
Если вы думаете, что в автокаде перемудрили, то вот аннотация к подобному методу в ревите  :D ;)
Цитировать
The offset curve is obtained by moving the points of the given curve by a certain distance (not necessarily the input distance) to the right relative to the reference vector. If the distance is negative, then the offset will be actually on the left side. The precise role played by the reference vector depends on the curve type in an inconsistent way, as specified in detail below. We plan to update this function to have a more consistent and understandable behavior.
For Line, HermiteSpline, NurbSpline and Cylindrical Helix, the right direction is along the cross product of the tangent at that point and the reference vector. In other words, the "right" side of the curve at a given point on the curve is defined with the reference vector being thought of as the upward direction and curve tangent being thought of as the forward direction, as if you are walking along the curve with your body aligned to the reference vector.

For Arc and Ellipse, the right direction is defined relative to the axis of the arc or ellipse in conjunction with the reference vector. If the dot product of the reference vector with the axis is positive, then the right direction is along the cross product of the curve tangent the axis. If the dot product is negetive, then it is in the other way. If the dot product is zero, then it is an input error.

More details of the behavior depending on the type of curve: Line: For a Line, a vecPerp is computed as the cross product of the line direction and the reference vector. The offset is obtained by moving the line by the given distance along the direction of the vecPerp. Note: vecPerp can be zero vector if the reference vector is parallel to the line direction. In that case, the offset is simply a copy of the given line. No error is reported. Arc: For an Arc, the offset is done in the plane of the arc. The resulting offset is another arc in the same plane as the given arc and with the same center. The radius is increased or decreased by the offset distance depending on the offset is to the right or left. The reference vector is used to determine if the offset is to be done to the right or left of the arc, based on the dot product of the reference vector with the axis (normal vector) of the arc. If the dot product is positive then the offset is to the right relative to the axis of the arc; if not, it is to the left. If the dot product is zero, that is, reference vector is perpendicular to the axis, the function will return NULL and report an error. Ellipse: An Ellipse is also a planar curve like the Arc. The offset is done in the plane of the ellipse. Note that the offset of an ellipse is not an ellipse in general. It will be approximated by a Hermite spline curve. The offset curve is obtained by offsetting the points of the ellipse, by the given offset distance, to the right or left relative to the axis (normal vector) of the ellipse. The reference vector is used to determine if the offset is to be done to the right or left of the ellipse, based on the dot product of the reference vector with the axis of the ellipse. If the dot product is positive then the offset is to the right relative to the axis of the ellipse; if not, it is to the left. If the dot product is zero, that is, reference vector is perpendicular to the axis, the function will return NULL and report an error. HermiteSpline, NurbSpline and Cylindrical Helix: A Hermite or Nurbs spline curve can be planar or non-planar; a cylindrical helix is non-planar. For these three types of curves, the offset is computed in a general way as follows: Let P be a point on the given curve and let T be the unit tangent vector at P, assuming that the derivative of the curve at P is not zero. The offset vector at P is the cross product of T and the reference vector. Then the offset point Q corresponding to P is computed as: Q = P + (offset distance) * (offset vector at P). The offset depends on the magnitude as well as the direction of the reference vector. If the magnitude of the reference vector is not one, then the actual distance moved will not be the given offset distance. NOTE: If the curve is a planar Hermite or Nurbs spline curve, the offset curve may not lie on the same plane – unlike the case of arc and ellipse.

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Re: Как задать направление для offset?
« Ответ #5 : 07-04-2019, 13:20:40 »
Продолжу старую тему т.к. обнаружились новые подробности. Указанное в документации поведение - чистый обман. Отрицательный offset редко когда уменьшает контур. Что я понял на текущий момент для замкнутых фигур для положительного offset :
- Круг - наружу
- Эллипс - внутрь
- Полилиния - по умолчанию внутрь, но есть команда Reverse Direction и после нее наружу.
- Сплайн - по умолчанию внутрь, но есть команда Reverse Direction и после нее наружу.
К сожалению столкнулся с полилиниями, которые сразу после создания вывернуты не туда. Свойство Direction отсутствует, что делает результат офсета абсолютно непредсказуемым. Есть ли у кого-нибудь мысли, как офсетить всегда внутрь? Ничего не приходит в голову кроме как мерить длину кривой. Для сплайна, я думаю, это не очень быстрый метод...


Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как задать направление для offset?
« Ответ #6 : 07-04-2019, 13:36:49 »
Ничего не приходит в голову кроме как мерить длину кривой.
Или площадь.
Для сплайна, я думаю, это не очень быстрый метод...
Проверь. Думаю, что достаточно быстрый.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Re: Как задать направление для offset?
« Ответ #7 : 07-04-2019, 13:43:19 »
Похоже был не прав - для полилиний и сплайнов направление офсета зависит от направления обхода:
- по часовой - внутрь
- против часовой - наружу
Можно это использовать для построения - взять три любые точки на кривой, и (если повезет) то они покажут направление обхода. Но со сложными фигурами может и не повезти... Буду мерить длину.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как задать направление для offset?
« Ответ #8 : 07-04-2019, 13:49:24 »
Но со сложными фигурами может и не повезти...
Повезет только в простейших случаях. А в общем случае алгоритм определения направления кривой будет не быстрее определения длины.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Re: Как задать направление для offset?
« Ответ #9 : 07-04-2019, 13:53:25 »
Вообще конечно шедевр программирования - правильно задать параметры функции можно только после вычисления результата :)

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Re: Как задать направление для offset?
« Ответ #10 : 07-04-2019, 15:11:32 »
Короче получается так:
Код - C# [Выбрать]
  1.     /// <summary>
  2.     /// Офсет замкнуторго контура. Положительный offset - наружу, отрицательный - внутрь
  3.     /// </summary>
  4.     internal static DBObjectCollection OffsetClosed(this Curve cur, double offset)
  5.     {
  6.       if (cur == null || cur.IsErased || !cur.IsPlanar || !cur.Closed || offset == 0)
  7.         return null;
  8.       try
  9.       {
  10.         // для окружностей и элипса офсет внутрь нужен отрицательный
  11.         if (cur is Circle || cur is Ellipse) return cur.GetOffsetCurves(offset);
  12.         // У сплайна и полинии - зависит от направления обхода - по часовой - положительный внутрь
  13.         DBObjectCollection offColl = cur.GetOffsetCurves(offset);
  14.         if (offColl == null) // не получилось в эту сторону - но может мы и не туда офсетили?
  15.         {
  16.           offColl = cur.GetOffsetCurves(-offset);
  17.           if (offColl == null) return null;
  18.           bool reduce = cur.Length() > offColl.Length(); // контур уменьшился
  19.           if (offset < 0 && reduce || offset > 0 && !reduce) return offColl;
  20.           else return null;
  21.         }
  22.  
  23.         bool reduce1 = cur.Length() > offColl.Length(); // контур уменьшился
  24.         if (offset < 0 && reduce1 || offset > 0 && !reduce1) return offColl;
  25.         else return cur.GetOffsetCurves(-offset);
  26.       }
  27.       catch { return null; }
  28.     }
  29.  
  30.     internal static double Length(this DBObjectCollection coll)
  31.     {
  32.       if (coll == null) return 0;
  33.       double ret = 0;
  34.       foreach(DBObject obj in coll)
  35.         if (obj is Curve cur) ret += cur.Length();
  36.       return ret;
  37.     }
  38.  
  39.     internal static double Length(this Curve curve)
  40.     {
  41.       return curve.GetDistanceAtParameter(curve.EndParam) - curve.GetDistanceAtParameter(curve.StartParam);
  42.     }
  43.  
  44.  
Сильно не бейте, накидал за 5 минут. На простых тестах работает. Тормозов не заметил.