Зеркальное отображение деталей в разрезе с помощью Revit API

У меня есть некоторые линии детализации внутри вида сечения, которые я хотел бы отразить через среднюю точку CropBox для сечения. Я использую ElementTransformUtils.MirrorElements, чтобы попытаться выполнить это. Однако мне пока не удалось найти правильную плоскость, на которой можно отразить линии деталей. Я пробовал Plane.CreateByNormalAndOrigin(section.ViewDirection, section.Origin) и detailLine.SketchPlane.GetPlane(), но ни один из них не отражал линии деталей.

Зеркальное отображение линий детализации

Каков правильный способ добиться этого?


person skeletank    schedule 27.02.2017    source источник


Ответы (2)


Да, самолёты, о которых вы говорите, не будут отражаться так, как вы ожидаете.

Я полагаю, вам нужна плоскость, перпендикулярная линии детализации.

Это будет отражать горизонтальную линию детализации, которую вы показываете справа налево или наоборот.

Вы можете определить нормаль плоскости зеркала и начало от самой линии детализации:

  XYZ p = detail line start point
  XYZ q = detail line end point
  XYZ normal = q - p
  Plane plane = Plane.CreateByNormalAndOrigin(p, normal)

Более менее...

person Jeremy Tammik    schedule 28.02.2017

Мне удалось отобразить детали посередине ViewSection.CropBox, но это было довольно сложно. Я обнаружил, что ViewSection.Origin — это точка в системе координат проекта. ViewSection.CropBox, с другой стороны, не дает вам его Min и Max в системе координат проекта, а вместо этого дает вам местоположение CropBox относительно ViewSection.Origin. Используя ViewSection.Origin и ViewSection.CropBox, вы можете рассчитать мин. и макс. ViewSection.CropBox в системе координат проекта. Наконец, вам нужно использовать эти минимальные и максимальные значения, чтобы найти среднюю точку ViewSection.CropBox, а затем зеркально отразить эту точку.

Вот несколько вспомогательных классов, которые я использую, чтобы найти Min и Max с помощью одной функции.

public enum PointComponent
{
  Invalid,
  X,
  Y,
  Z
}

public enum MinOrMax
{
  Invalid,
  Min,
  Max
}

Вот функция для поиска компонента X, Y или Z минимального или максимального значения CropBox:

private double GetSectionCropBoxOrigin(ViewSection section,
  PointComponent pointComponent, MinOrMax minOrMax)
{
  double cropBoxOrigin;

  double sectionOrigin, viewDirection, upDirection, rightDirection;

  switch (pointComponent)
  {
    case PointComponent.X:
      sectionOrigin = section.Origin.X;
      viewDirection = section.ViewDirection.X;
      upDirection = section.UpDirection.X;
      rightDirection = section.RightDirection.X;
      break;
    case PointComponent.Y:
      sectionOrigin = section.Origin.Y;
      viewDirection = section.ViewDirection.Y;
      upDirection = section.UpDirection.Y;
      rightDirection = section.RightDirection.Y;
      break;
    case PointComponent.Z:
      sectionOrigin = section.Origin.Z;
      viewDirection = section.ViewDirection.Z;
      upDirection = section.UpDirection.Z;
      rightDirection = section.RightDirection.Z;
      break;
    default:
      throw new InvalidOperationException();
  }

  double cropX, cropY;

  switch (minOrMax)
  {
    case MinOrMax.Min:
      cropX = section.CropBox.Min.X;
      cropY = section.CropBox.Min.Y;
      break;
    case MinOrMax.Max:
      cropX = section.CropBox.Max.X;
      cropY = section.CropBox.Max.Y;
      break;
    default:
      throw new InvalidOperationException();
  }

  if (Math.Abs(viewDirection) == 1)
    cropBoxOrigin = sectionOrigin;
  else if (Math.Abs(upDirection) == 1)
    cropBoxOrigin = sectionOrigin + (cropY * upDirection);
  else if (Math.Abs(rightDirection) == 1)
    cropBoxOrigin = sectionOrigin + (cropX * rightDirection);
  else
    throw new InvalidOperationException();

  return cropBoxOrigin;
}

Обратите внимание, что для PointComponent.Z мы не используем среднюю точку между значениями Min и Max, а вместо этого используем начало координат. Это связано с тем, что наша детализация существует только в 2D, хотя мы указываем глубину CropBox, а детализация находится на той же глубине, что и ViewSection.Origin.

Вот код, который я использую для получения средней точки:

private XYZ Get3dMidpoint(XYZ start, XYZ end)
{
    double x = (start.X + end.X) / 2.0;
    double y = (start.Y + end.Y) / 2.0;
    double z = (start.Z + end.Z) / 2.0;

    return new XYZ(x, y, z);
}

И, наконец, вот код, чтобы собрать все вместе и получить зеркальную плоскость:

XYZ cropBoxMinInGlobalCoordinates = new XYZ(
    GetSectionCropBoxOrigin(section, PointComponent.X, MinOrMax.Min),
    GetSectionCropBoxOrigin(section, PointComponent.Y, MinOrMax.Min),
    GetSectionCropBoxOrigin(section, PointComponent.Z, MinOrMax.Min)
);
XYZ cropBoxMaxInGlobalCoordinates = new XYZ(
    GetSectionCropBoxOrigin(section, PointComponent.X, MinOrMax.Max),
    GetSectionCropBoxOrigin(section, PointComponent.Y, MinOrMax.Max),
    GetSectionCropBoxOrigin(section, PointComponent.Z, MinOrMax.Max)
);
XYZ cropBoxOriginInGlobalCoordinates = 
  Get3dMidpoint(cropBoxMinInGlobalCoordinates, cropBoxMaxInGlobalCoordinates);

Plane mirrorPlane = 
  Plane.CreateByNormalAndOrigin(section.RightDirection, cropBoxOriginInGlobalCoordinates);
person skeletank    schedule 01.03.2017