Хаотичное смещение blockref после округления точки вставки

Автор Тема: Хаотичное смещение blockref после округления точки вставки  (Прочитано 7580 раз)

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

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Здравствуйте! написал небольшой код для округления координат объектов. Для линий и полилиний все работает нормально, а после обработки блоков все они  съезжаются в одну точку. Это не начало координат какая-то произвольная координата. В чем может быть причина?
Код - C# [Выбрать]
  1.  public static void RoundOffPoints()
  2.         {
  3.             Document doc = Application.DocumentManager.MdiActiveDocument;
  4.             Database db = doc.Database;
  5.             Editor ed = doc.Editor;
  6.             double accuracy = SelectionUtilities.GetNumParameter("Set desired accuracy");
  7.             using (Transaction tr = db.TransactionManager.StartTransaction())
  8.             {
  9.                 Point2dCollection point2DCollection = null;
  10.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite);
  11.                 foreach (ObjectId btrId in bt)
  12.                 {
  13.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForWrite);
  14.                     if (btr.IsFromExternalReference)
  15.                     {
  16.                         continue;
  17.                     }
  18.  
  19.                     foreach (ObjectId id in btr)
  20.                     {
  21.                         Entity ent = (Entity)tr.GetObject(id, OpenMode.ForWrite, false, true);
  22.                         if (ent is Polyline)
  23.                         {
  24.                             Polyline pline = (Polyline)ent;
  25.                             point2DCollection = CoordinatesNormalizer.VerticesToCollection(pline);
  26.  
  27.                             Point2dCollection normVertices = CoordinatesNormalizer.NormalizePoint(accuracy, point2DCollection);
  28.                             for (int i = 0; i < normVertices.Count; i++)
  29.                             {
  30.                                 pline.SetPointAt(i, normVertices[i]);
  31.                             }
  32.                         }
  33.  
  34.                         if (ent is Line)
  35.                         {
  36.                             Line line = (Line)ent;
  37.                             point2DCollection = CoordinatesNormalizer.VerticesToCollection(line);
  38.                             Point2dCollection normVertices = CoordinatesNormalizer.NormalizePoint(accuracy, point2DCollection);
  39.                             line.StartPoint = new Point3d(normVertices[0].X, normVertices[0].Y, 0);
  40.                             line.EndPoint = new Point3d(normVertices[1].X, normVertices[1].Y, 0);
  41.  
  42.                         }
  43.                         if (ent is BlockReference)
  44.                         {
  45.                             BlockReference bref = (BlockReference)ent;
  46.  
  47.  
  48.                             point2DCollection.Add(new Point2d(bref.Position.X, bref.Position.Y));
  49.                             Point2dCollection normVertices = CoordinatesNormalizer.NormalizePoint(accuracy, point2DCollection);
  50.                             bref.Position = new Point3d(normVertices[0].X, normVertices[0].Y, 0);
  51.  
  52.                         }
  53.                     }
  54.                 }
  55.  
  56.                 tr.Commit();
  57.             }
  58.  
  59.             ed.Regen();
  60.         }
  61. internal class CoordinatesNormalizer
  62.     {
  63.         public static double RoundOff(double input, double accuracy)
  64.         {
  65.             double result = Math.Round(input / accuracy) * accuracy;
  66.             return result;
  67.         }
  68.  
  69.         public static Point2dCollection NormalizePoint(double accuracy, Point2dCollection vertices)
  70.         {
  71.             Point2dCollection normVertices = new Point2dCollection();
  72.             foreach (Point2d vertice in vertices)
  73.             {
  74.                 Point2d normVertice = new Point2d(RoundOff(vertice.X, accuracy), RoundOff(vertice.Y, accuracy));
  75.                 normVertices.Add(normVertice);
  76.             }
  77.  
  78.             return normVertices;
  79.         }
  80.  
  81.         public static Point2dCollection VerticesToCollection(Polyline polyline)
  82.         {
  83.             Point2dCollection vertices = new Point2dCollection();
  84.             for (int i = 0; i < polyline.NumberOfVertices; i++)
  85.             {
  86.                 vertices.Add(polyline.GetPoint2dAt(i));
  87.             }
  88.  
  89.             return vertices;
  90.         }
  91.         public static Point2dCollection VerticesToCollection(Line line)
  92.         {
  93.             Point2dCollection vertices = new Point2dCollection();
  94.             vertices.Add(new Point2d(line.StartPoint.X, line.StartPoint.Y));
  95.             vertices.Add(new Point2d(line.EndPoint.X, line.EndPoint.Y));
  96.             return vertices;
  97.         }
  98.  
  99.         public static class MathExtensions
  100.         {
  101.             public static int RoundUpTo(int number, int nearest)
  102.             {
  103.                 if ((nearest < 10) || (nearest % 10 != 0))
  104.                 {
  105.                     throw new ArgumentOutOfRangeException(nameof(nearest), $"{nameof(nearest)} must be a positive multiple of 10, but you specified {nearest}.");
  106.                 }
  107.  
  108.                 int modulo = number % nearest;
  109.                 if (modulo == 0)
  110.                 {
  111.                     return number;
  112.                 }
  113.  
  114.                 if (modulo > 0)
  115.                 {
  116.                     return number + (nearest - modulo);
  117.                 }
  118.  
  119.                 return number - modulo;
  120.             }
  121.         }
  122.     }

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 475
  • Карма: 63
Удивительно, что у тебя Acad не вылетел
Point2dCollection point2DCollection = null;
point2DCollection.Add(new Point2d(bref.Position.X, bref.Position.Y));

мне кажется проще написать свою функцию округления для каждого типа
Normalize(BlockReference obj)
Normalize(Polyline obj)
Normalize(Line obj)

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Для линий и полилиний все работает нормально, а после обработки блоков все они  съезжаются в одну точку. Это не начало координат какая-то произвольная координата. В чем может быть причина?
AutoCAD выполнил то, что ты хотел)

...хотя бы так добавь.
point2DCollection = new Point2dCollection();
point2DCollection.Add(new Point2d(bref.Position.X, bref.Position.Y));
....
bref.Position = new Point3d(normVertices[0].X, normVertices[0].Y, 0);

при этом любой блок лучше не двигать с помощью  bref.Position, т.к. если блок с атрибутами, то атрибуты не сдвинуться вместе с блоком

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
ри этом любой блок лучше не двигать с помощью  bref.Position, т.к. если блок с атрибутами, то атрибуты не сдвинуться вместе с блоком
А как его правильно двигать? У блок-рефа есть только это свойство для указания положения.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
У блок-рефа есть только это свойство для указания положения.
У всех примитивов есть метод TransformBy.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Atomohod 19-07-2019, 23:08:57

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
А как его правильно двигать? У блок-рефа есть только это свойство для указания положения.
Matrix3d displacement = Matrix3d.Displacement(moveVector);
blockRef.TransformBy(displacement);

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
У всех примитивов есть метод TransformBy.
Если я правильно понял, то это метод для перемещения объекта, а мне нужно не смещая его всего лишь округлить координаты - например 179,78955566 должно стать 180.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Atomohod,
Тебе уже Привалов Дмитрий всё разжевал. Вычисли правильный moveVector из точки в которой была точка вставки блока в "округленную точку" и используй его код.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение