Issue with Automatic Grid Dimensions Alignment using Revit API

Issue with Automatic Grid Dimensions Alignment using Revit API

guillermogutierrezgcp
Participant Participant
305 Views
1 Reply
Message 1 of 2

Issue with Automatic Grid Dimensions Alignment using Revit API

guillermogutierrezgcp
Participant
Participant

Hello everyone,

I'm developing a Revit add-in using the API to automatically generate dimensions between visible grids in a floor plan view. While the dimensions are being created, their positions are incorrect: they appear misaligned or shifted relative to the grids they are supposed to measure.

guillermogutierrezgcp_0-1734973953625.png

 

Problem Description:

  1. Dimensions between consecutive grids:

    • The dimensions are generated between consecutive grids.
    • However, the baseline of the dimensions seems offset or not properly aligned perpendicular to the grids.
  2. Overall dimension from the first to the last grid:

    • The dimension spanning the first and last grid is created, but it also appears misaligned or shifted.
  3. Involved elements:

    • The tool exclusively works with Grid elements, and I ensure that only visible grids in the active view are collected using a FilteredElementCollector.Self-correcting behavior:
  4. Self-correcting behavior:

    • When I manually perform certain actions in Revit (e.g., changing the view scale or interacting with the dimensions), they correct their position automatically and align as expected. This suggests that the issue might be related to document regeneration or how the API processes coordinates during execution.

Initial Diagnosis:

  • I use the endpoints of the grid curves (Curve) to calculate the baseline for the dimensions.
  • An offset is applied to position the dimensions slightly away from the grids for clarity, but the calculation does not seem to work as expected.
  • I've tried using both the minimum and average coordinates for alignment, but the results remain inconsistent.
  • Interestingly, when I manually change the view scale or interact with the dimensions after they are generated, their positions correct themselves automatically. This makes me think the issue could be related to document regeneration or the interpretation of coordinates within the active view.

 

using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.Attributes;

namespace Acotar
{
[Transaction(TransactionMode.Manual)]
public class AcotarEjes : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uiDoc = commandData.Application.ActiveUIDocument;
Document doc = uiDoc.Document;
View view = doc.ActiveView;

try
{
// Validar que la vista activa sea una vista de plano
if (view.ViewType != ViewType.FloorPlan)
{
MostrarError("Las cotas automáticas solo se pueden crear en vistas de plano.");
return Result.Cancelled;
}

using (Transaction trans = new Transaction(doc, "Crear Cotas Automáticas"))
{
trans.Start();

// Obtener ejes visibles en la vista
List<Grid> grids = ObtenerEjesVisibles(doc, view);

if (grids.Count < 2)
{
MostrarError("No se encontraron suficientes ejes en la vista para acotar.");
return Result.Cancelled;
}

// Clasificar ejes horizontales y verticales
var horizontalGrids = grids.Where(g => IsHorizontal(g.Curve))
.OrderBy(g => g.Curve.GetEndPoint(0).X)
.ToList();

var verticalGrids = grids.Where(g => !IsHorizontal(g.Curve))
.OrderBy(g => g.Curve.GetEndPoint(0).Y)
.ToList();

// Crear cotas horizontales y verticales
if (horizontalGrids.Count >= 2)
{
CrearCotasEntreConsecutivos(doc, view, horizontalGrids, true);
CrearCotaGeneral(doc, view, horizontalGrids, true);
}

if (verticalGrids.Count >= 2)
{
CrearCotasEntreConsecutivos(doc, view, verticalGrids, false);
CrearCotaGeneral(doc, view, verticalGrids, false);
}

trans.Commit();
}

MostrarInformacion("¡Cotas creadas exitosamente!");
return Result.Succeeded;
}
catch (Exception ex)
{
message = ex.Message;
return Result.Failed;
}
}

private List<Grid> ObtenerEjesVisibles(Document doc, View view)
{
return new FilteredElementCollector(doc, view.Id)
.OfClass(typeof(Grid))
.Cast<Grid>()
.ToList();
}

private void CrearCotasEntreConsecutivos(Document doc, View view, List<Grid> grids, bool isHorizontal)
{
double offset = 1.0; // Desplazamiento en metros

// Crear cotas entre ejes consecutivos
for (int i = 0; i < grids.Count - 1; i++)
{
Line baseline = CrearLineaBaseParaEjes(grids[i], grids[i + 1], isHorizontal, offset);
CrearCota(doc, view, new List<Grid> { grids[i], grids[i + 1] }, baseline);
}
}

private void CrearCotaGeneral(Document doc, View view, List<Grid> grids, bool isHorizontal)
{
double offset = 2.0; // Desplazamiento adicional para la cota general

// Crear línea base entre el primer y último eje
Line baseline = CrearLineaBaseParaEjes(grids.First(), grids.Last(), isHorizontal, offset);

// Crear cota general
CrearCota(doc, view, new List<Grid> { grids.First(), grids.Last() }, baseline);
}

private void CrearCota(Document doc, View view, List<Grid> grids, Line baseline)
{
ReferenceArray references = new ReferenceArray();
foreach (var grid in grids)
{
references.Append(new Reference(grid));
}

DimensionType dimType = ObtenerDimensionTypeValido(doc);
if (dimType == null)
throw new InvalidOperationException("No se encontró un tipo de cota lineal válido en el proyecto.");

Dimension dimension = doc.Create.NewDimension(view, baseline, references);
dimension.DimensionType = dimType;

doc.Regenerate();
}

private Line CrearLineaBaseParaEjes(Grid grid1, Grid grid2, bool isHorizontal, double offset)
{
Curve curve1 = grid1.Curve;
Curve curve2 = grid2.Curve;

if (curve1 == null || curve2 == null)
throw new InvalidOperationException("No se pudo obtener la curva de uno o ambos ejes.");

if (isHorizontal)
{
// Coordenadas mínimas y máximas en X
double minX = Math.Min(curve1.GetEndPoint(0).X, curve2.GetEndPoint(0).X);
double maxX = Math.Max(curve1.GetEndPoint(1).X, curve2.GetEndPoint(1).X);

// Obtener Y promedio para garantizar alineación
double averageY = (curve1.GetEndPoint(0).Y + curve2.GetEndPoint(0).Y) / 2;

// Desplazamiento hacia abajo
double yPosition = averageY - offset;

return Line.CreateBound(new XYZ(minX, yPosition, 0), new XYZ(maxX, yPosition, 0));
}
else
{
// Coordenadas mínimas y máximas en Y
double minY = Math.Min(curve1.GetEndPoint(0).Y, curve2.GetEndPoint(0).Y);
double maxY = Math.Max(curve1.GetEndPoint(1).Y, curve2.GetEndPoint(1).Y);

// Obtener X promedio para garantizar alineación
double averageX = (curve1.GetEndPoint(0).X + curve2.GetEndPoint(0).X) / 2;

// Desplazamiento hacia la izquierda
double xPosition = averageX - offset;

return Line.CreateBound(new XYZ(xPosition, minY, 0), new XYZ(xPosition, maxY, 0));
}
}


private DimensionType ObtenerDimensionTypeValido(Document doc)
{
return new FilteredElementCollector(doc)
.OfClass(typeof(DimensionType))
.Cast<DimensionType>()
.FirstOrDefault(dt => dt.StyleType == DimensionStyleType.Linear);
}

private bool IsHorizontal(Curve curve)
{
return Math.Abs(curve.GetEndPoint(1).X - curve.GetEndPoint(0).X) >
Math.Abs(curve.GetEndPoint(1).Y - curve.GetEndPoint(0).Y);
}

private void MostrarError(string mensaje)
{
TaskDialog.Show("Error", mensaje);
}

private void MostrarInformacion(string mensaje)
{
TaskDialog.Show("AutoDimension", mensaje);
}
}
}

 

 

 

 

 

 

0 Likes
306 Views
1 Reply
Reply (1)
Message 2 of 2

Sleepingfish_Kuo
Advocate
Advocate

Try write them in two (or more) transactions?

I guess something is applied only when the transaction commits.

0 Likes