简体   繁体   中英

C# Revit API Create linear dimension

I am trying to create a dimension between the left and right ends of an element in a view section as shown in the image.

Linear dimension

I am using the following code to get the references of the faces by iterating the solids.

public static Reference ReferenciaPlanoIzquierdoElementoEnVista(View vista, Element elem)
{
    // Crea la referencia a devolver
    Reference referencia = null;

    // Crea la variable distancia
    double distancia = double.MinValue;

    // Obtiene el vector unitario que apunta hacia la izquierda de la vista
    XYZ vistaIzquierda = -vista.RightDirection.Normalize();

    // Crea las preferencias para analizar la geometría
    Options opcion = new Options();

    // Activa el cálculo de referencias a objetos
    opcion.ComputeReferences = true;

    // Crea una representación geométrica del elemento
    GeometryElement geoElem = elem.get_Geometry(opcion);

    // Recorre todos las geometrías primitivas
    foreach (GeometryObject geoObje in geoElem)
    {
        // Castea la primitiva 
        GeometryInstance geoInst = geoObje as GeometryInstance;

        // Verifica que esa geometría no sea nula
        if (geoInst != null && geoInst.IsElementGeometry)
        {
            // Asigna la geometría primitiva a la representación geométrica
            geoElem = geoInst.GetInstanceGeometry();
                
            break;
        }
    }

    // Recorre todos los solidos de la geometría
    foreach (Solid solido in geoElem.OfType<Solid>().Where<Solid>(sol => sol != null))
    {
        // Recorre todas las caras del solido
        foreach (Face cara in solido.Faces)
        {
            // Verifica que la cara no sea nula
            if (cara != null)
            {
                // Obtiene las coordenadas 3D de la cara en un punto dado
                XYZ puntoMedio = ObtenerPuntoMedioCara(cara);
                    
                // Obtiene el vector unitario normal de la cara en un punto dado
                XYZ normal = ObtenerVectorNormalCara(cara).Normalize();

                // Verifica que la normal sea paralela a la vista derecha
                if (normal.CrossProduct(vistaIzquierda).IsZeroLength() && normal.IsAlmostEqualTo(vistaIzquierda))
                {
                    // Distancia del punto medio de la cara al baricentro del elemento en el sentido del vector derecha de la vista
                    double distanciaACara = Math.Abs(DistanciaBaricentroElementoACara(vista, elem, cara));

                    // Verifica que la distancia sea mayor
                    if (distanciaACara > distancia)
                    {
                        // Asigna la nueva distancia
                        distancia = distanciaACara;

                        // Asigna la referencia de la cara
                        referencia = cara.Reference;
                    }
                }
            }
        }
    }

    return referencia;
}

And this code to create a dimension.

public static Dimension CrearCotaHorizontalAbajoParaElemento(System.Windows.Forms.ComboBox combo, List<DimensionType> estilosCotas,
                                                                Document doc, View vista, Element elem)
{
    // Obtiene el DimensionType de la etiqueta seleccionada
    DimensionType dimType = estilosCotas.FirstOrDefault(eti => eti.Name == combo.SelectedItem.ToString());

    // Crea un arreglo con las referencias
    ReferenceArray ArregloRef = new ReferenceArray();

    // Obtiene el vector unitario que apunta hacia la derecha de la vista
    XYZ vistaDerecha = vista.RightDirection.Normalize();

    // Crea una caja de sección del elemento
    BoundingBoxXYZ bb = elem.get_BoundingBox(vista);

    // Agrega las referencias del plano
    ArregloRef.Append(ReferenciaPlanoIzquierdoElementoEnVista(vista, elem));
    ArregloRef.Append(ReferenciaPlanoDerechoElementoEnVista(vista, elem));
        
    // Crea las coordenadas de la linea
    XYZ x1 = new XYZ(bb.Min.X, bb.Min.Y, bb.Min.Z);
    XYZ x2 = x1.Add(vistaDerecha);

    // Crea la linea temporal
    Line linea = Line.CreateBound(x1, x2);

    // Crea la cota temporal
    Dimension cota = doc.Create.NewDimension(vista, linea, ArregloRef, dimType);

    // Crea una caja de sección del elemento
    BoundingBoxXYZ bbCota = cota.get_BoundingBox(vista);

    // Obtiene la altura del texto
    double zCota = Math.Abs(bbCota.Min.Z - cota.LeaderEndPosition.Z);

    // Mueve la cota hacia abajo
    ElementTransformUtils.MoveElement(doc, cota.Id, new XYZ(0, 0, -zCota));

    return cota;
}

I draw on the posts of Jeremy Tammik, who talks about two ways to get referrals. I chose the first way which is iterating.

https://thebuildingcoder.typepad.com/blog/2011/02/dimension-walls-by-iterating-faces.html https://thebuildingcoder.typepad.com/blog/2011/02/dimension-walls-using-findreferencesbydirection.html

But then he throws me a poster saying the references are not correct and the dimension should be removed.

One or more dimension references are or have become invalid

In your code, you are retrieving the symbol geometry. You probably need to use the instance geometry instead, as discussed in The Building Coder article on References to Symbol versus Instance Geometry .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM