Cloning a Solid, AngelHack, 3D Web Fest and Dubai

The Revit 2016 offers a whole host of exciting new functionality that I am dying to try out, e.g.:

And much, much more…

Too little time!

At least I can mention one useful aspect of the new geometry API that came in handy for an issue that came up yesterday.

I am in Dubai right now, preparing for the AngelHack Hackathon.

Here are the topics for today:

3D Web Festival in San Francisco

Hey, there is this really cool event coming up in San Francisco on May 13th,
the 3D Web Festival,
sponsored by Autodesk, Goo Technologies and Leap Motion:

If you know any folks in the Bay Area who might be interested in seeing and experiencing what’s possible today with 3D on the web, please let them know.

AngelHack and I♥3D in Dubai

As said, I am in Dubai right now, for the first time in my life.

Here are my
first impressions wandering
around
Jumeirah Beach Residence, aka JBR.

Jumeirah Beach Residence, Dubai

Tonight we hold the
AngelHack Dubai Pre-Hackathon Meetup and Workshop
to get all interested
AngelHack Dubai Hackathon participants
up to speed on the View and Data API in preparation for two hot and frantic days of hacking over the weekend – which is Friday and Saturday here, of course.

AngelHack and I♥3D in Athens

We also just held the inaugural
I love 3D – Athens meetup,
on April 24th, at
The Cube,
Greece’s biggest coworking space.

Cyrille Fauvel and Peter Schlipf presented the View and Data API, Fusion360, AutoCAD I/O and Recap360 to a group 30 enthusiastic local developers:

I♥3D Athens inaugural meetup

They loved it.

I will be going there too soon, for the
Angelhack in Athens, on June 5-7.

Again, we have scheduled an
AngelHack workshop meetup
session on Friday evening to get us all well prepared and up to speed for the subsequent hackathon.

I am looking forward to meeting you there!

Autodesk University proposals

The
Autodesk University Call for Proposals has opened.

I am already busy preparing mine   :-)

Cloning a solid

Now, finally, back to the Revit API, with a question on cloning solids, very well addressed by one of the Revit 2016 API enhancements:

Question: To clone solids, we have been using the following workaround in the past:


  static public Solid Clone( this Solid solid )
  {
    if( solid == null )
    {
      return null;
    }
    return BooleanOperationsUtils
      .ExecuteBooleanOperation( solid, solid,
        BooleanOperationsType.Union );
  }

This function allows us to clone solids to later use them to create or modify DirectShape elements.
It works very well in the majority of the cases; however, the ExecuteBooleanOperation function throws an exception on some specific DirectShape elements, saying:

  • Exception: “Failed to perform the Boolean operation for the two solids. Error: Autodesk.Revit.Exceptions.InvalidOperationException: Failed to perform the Boolean operation for the two solids”

I would be very grateful if you can give me some directions how to fix this issue.

Answer: Have you noticed the following new functionality provided by the
Revit 2016 API
Geometry API additions?

Solid – copy

The new method:

  • SolidUtils.Clone()

creates a new Solid that is a copy of the input Solid.

That looks as if it should solve your problem for you more elegantly and efficiently.

Response:
Thanks for the quick answer.

The SolidUtils.Clone method does indeed solve the issue for Revit 2016. It works perfectly. Thanks!

However, what can I do to fix it in Revit 2015?

Answer: I am very glad to hear that the issue is solved in Revit 2016 by the SolidUtils.Clone enhancement.

For Revit 2015 and previous versions, a better workaround, rather than unioning the original solid with itself, might be to union the shape with a small cube (1″ x 1″ would work for most shapes) located in the interior of the shape.

Response: Thank you!

I can confirm that the workaround solves the issue I was having with the Revit 2015 API.


Comments

11 responses to “Cloning a Solid, AngelHack, 3D Web Fest and Dubai”

  1. Alexander Ignatovich Avatar
    Alexander Ignatovich

    Hi, Jeremy!
    I’ve found useful trick to Clone element geometry in Revit 2015. This is Iron Python script:
    for wall in selection:
    t = Transaction(doc, “temp”)
    t.Start()
    for insId in wall.FindInserts(True, True, True, True):
    doc.Delete(insId)
    doc.Regenerate()
    for s in wall.get_Geometry(Options()).GetTransformed(Transform.CreateTranslation(XYZ.Zero)):
    if s.GetType().Name == “Solid”:
    print s.IsElementGeometry, s.Volume # <= very strange, s.IsElementGeometry is “true”
    solid = s
    t.RollBack()
    print solid.Volume
    if you omit .GetTransformed(Transform.CreateTranslation(XYZ.Zero)) it will fail on the last line

  2. Dear Alexander,
    Wow, thank you for the very interesting hint!
    Reminds me of the tricks to refresh graphics mentioned here:
    http://thebuildingcoder.typepad.com/blog/2011/07/refresh-element-graphics-display.html
    Unfortunately, all leading spaces are removed from the blog post text, so all indentation is gone, making it hard to see where the Python blocks end. Can you add points instead of spaces, or mark the end of each block somehow, or post it in pastebin or something, please?
    Thank you!
    Cheers, Jeremy.

  3. Alexander Ignatovich Avatar
    Alexander Ignatovich

    Let’s try (to test it just replace “…” to Tab symbol:
    for wall in selection:
    …t = Transaction(doc, “temp”)
    …t.Start()
    …for insId in wall.FindInserts(True, True, True, True):
    ……doc.Delete(insId)
    …doc.Regenerate()
    …for s in wall.get_Geometry(Options()).GetTransformed(Transform.CreateTranslation(XYZ.Zero)):
    ……if s.GetType().Name == “Solid”:
    ………print s.IsElementGeometry, s.Volume # <= very strange, s.IsElementGeometry is “true”
    ………solid = s
    …t.RollBack()
    …print solid.Volume
    I’m also interesting is it a bug, that s.IsElementGeometry is True after
    calling GetTransformed method? It looks like detached from element geometry because it is available after transaction.RollBack?

  4. Dear Alexander,
    Thank you, that clarifies.
    Very interesting alternative!
    The developer is currently using another approach:
    I used the following steps to clone a solid in Revit 2015.
    1. I obtained the largest face from the original solid.
    2. Triangulate the largest face (public Mesh Triangulate())
    3. I obtained a triangle whose edges are bigger than 0.0026 feet because Revit API allows to create solids only with edges bigger than this value.
    4. Using the triangle, I created a pyramid solid using the opposite vector Normal of largest face.
    5. Finally, I union the original solid with pyramid solid.
    For now, it is working in the all cases that I tested. However, I could get some issues using this workaround with more complex solids. If you have a better workaround, please let me know.
    Maybe suitable material for a follow-up post on cloning solids in Revit 2015…
    Or have we all moved on to Revit 2016 already?
    Cheers, Jeremy.

  5. Alexander Ignatovich Avatar
    Alexander Ignatovich

    Dear Jeremy! I’ve tried this approach, but I have some problems with creating 3-sideded pyramid, so I replaced it with a small extrusion. It works in most cases, but I’ve found a specific case, that fails. Can you ask the developer about creating pyramid details? I am interesting in testing this approach, may be if I replace extrusion with piramid it will work.
    And yes, we still need to support Revit 2015…

  6. The Web Fest was fantastic-full capacity, standing room only! Wish you had been here!

  7. Dear Lisa,
    Wow, fantastic!
    I wish I could have joined.
    Where can we read more about it?
    Who won?
    Cheers, Jeremy

  8. Dear Alexander,
    I don’t see why you should have any difficulty creating the pyramid.
    Can’t you just do the following?

    Triangulate a face.
    Pick an arbitrary mesh triangle.
    It has three vertex points.
    Determine its normal vector.
    Use the normal vector to calculate a fourth point on the inside of the solid.
    Create a tetrahedron between the four points.

    I hope this helps.
    Cheers, Jeremy.

  9. Alexander Ignatovich Avatar
    Alexander Ignatovich

    Hi again, Jeremy!
    After the battle with GeometryCreationUtilities.CreateSweptGeometry method, I’ve realized my own implementation of this algorithm:
    http://pastebin.com/vTkNjUuF
    and tried to test it in the project, downloaded from https://grabcad.com/library/manor-house-1 (you can freely download this file after registration). Unfortunately, there are a lot of cases, when it fails, first of all, there are a lot of cases, when you get “Failed to perform the Boolean operation for the two solids” exception. The other case is failing on GeometryCreationUtilities.CreateSweptGeometry. I suppose it fails because there are less meaning digits in real number in Python, but I don’t know exactly.

  10. Dear Alexander,
    I do not think Python has less meaningful digits in real numbers than C# or Revit.
    Here is Marcelo’s implementation, in case you want to compare them (http://pastebin.com/rUi7gERi):

    static private Solid GetJoinSolid(Solid solid)
    {
    Solid joinSolid = solid;
    //Get the large face of the solid
    Face largetsFace = solid.GetLargestFace();
    if (largetsFace == null) { return joinSolid; }
    // Get mesh
    Mesh mesh = largetsFace.Triangulate();
    if (mesh.NumTriangles == 0) { return joinSolid; }
    List validTrianglePts = new List();
    for (int i = 0; i < mesh.NumTriangles; i++)
    {
    MeshTriangle triangle = mesh.get_Triangle(i);
    XYZ vertex1 = triangle.get_Vertex(0);
    XYZ vertex2 = triangle.get_Vertex(1);
    XYZ vertex3 = triangle.get_Vertex(2);
    if (Math.Abs(vertex1.DistanceTo(vertex2)) < 0.0026) { continue; }
    if (Math.Abs(vertex2.DistanceTo(vertex3)) < 0.0026) { continue; }
    if (Math.Abs(vertex3.DistanceTo(vertex1)) < 0.0026) { continue; }
    validTrianglePts.Add(vertex1);
    validTrianglePts.Add(vertex2);
    validTrianglePts.Add(vertex3);
    break;
    }
    if (validTrianglePts.Count == 0) { return joinSolid; }
    joinSolid = SolidUtils.SolidCreator.NewPyramid(
    validTrianglePts, -largetsFace.GetFaceNormal(), 0.1);
    return joinSolid;
    }
    //Return faces to create the pyramid solid
    static public List GetFacesForPyramid(
    ElementId materialId,
    List faceptsBottom,
    XYZ vecDir,
    double height)
    {
    if (faceptsBottom == null) { return null; }
    if (faceptsBottom.Count < 2) { return null; }
    if (height == 0) { return null; }
    List tFaces = new List();
    tFaces.Add(new TessellatedFace(faceptsBottom, materialId));
    XYZ ptAverage = faceptsBottom[0];
    for (int i = 1; i < faceptsBottom.Count; i++)
    ptAverage = ptAverage + faceptsBottom[i];
    ptAverage = ptAverage / faceptsBottom.Count;
    XYZ topPt = ptAverage + vecDir * height;
    XYZ pt1 = faceptsBottom[0];
    for (int i = 1; i < faceptsBottom.Count; i++)
    {
    XYZ pt2 = faceptsBottom[i];
    List trianglePts = new List();
    trianglePts.Add(pt1);
    trianglePts.Add(pt2);
    trianglePts.Add(topPt);
    tFaces.Add(new TessellatedFace(trianglePts, materialId));
    pt1 = pt2;
    }
    List triangleEndPts = new List();
    triangleEndPts.Add(faceptsBottom.Last());
    triangleEndPts.Add(faceptsBottom.First());
    triangleEndPts.Add(topPt);
    tFaces.Add(new TessellatedFace(triangleEndPts, materialId));
    return tFaces;
    }
    

    However, this fails as well sometimes, he says.
    Cheers, Jeremy.

  11. Dear Alexander,
    The fact that IsElementGeometry returns true is indeed strange, so I logged the issue REVIT-67549 [IsElementGeometry returns true on non-element geometry] with our development team for this on your behalf as it requires further exploration and possibly a modification to our software. Please make a note of this number for future reference.
    Cheers, Jeremy.

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading