[bug] SetFaceOffset Face doesn't belong to the Part

[bug] SetFaceOffset Face doesn't belong to the Part

maxime.touchard7RAK6
Contributor Contributor
1,296 Views
10 Replies
Message 1 of 11

[bug] SetFaceOffset Face doesn't belong to the Part

maxime.touchard7RAK6
Contributor
Contributor

Hi everyone,

I was trying to edit the shape of a Part using the method SetFaceOffset. I get the sample from https://thebuildingcoder.typepad.com/blog/2012/09/parts-assemblies-partutils-and-divideparts.html
However I'm always having an error saying "face doesn't belong to the part". Which I think is impossible. My code so far :

 

UIDocument uidoc = uiapp.ActiveUIDocument;
Autodesk.Revit.ApplicationServices.Application app = uiapp.Application;
Document doc = uidoc.Document;

Reference refS = uidoc.Selection.PickObject(ObjectType.Element);
Part p = doc.GetElement(refS.ElementId) as Part;
Options opt = new Options();
opt.View = doc.ActiveView;
GeometryElement geomElem = p.get_Geometry(opt);
foreach (GeometryObject geomObject in geomElem)
{
    if (geomObject is Solid)
    {
        Solid solid = geomObject as Solid;
        FaceArray faceArray = solid.Faces;
        foreach (Face face in faceArray)
        {
            if (p.CanOffsetFace(face))
            {
                p.SetFaceOffset(face, 0.078740157480311268);
            }
        }
    }
}

 

Have you got any ideas why I get this error ? Is it a bug of the Revit API ?
Thanks !

0 Likes
Accepted solutions (1)
1,297 Views
10 Replies
Replies (10)
Message 2 of 11

jeremy_tammik
Alumni
Alumni

In the sample you refer to, the element is a multi-layer compound structure wall, and all the faces being offset seem to be parallel to each other and to the wall location line. Maybe some of these restrictions are relevant in your case too, and maybe violated in some way. Can you achieve the desired effect manually through the end user interface? Then it should be possible programmatically as well. If it works in the UI and fails in the API, please submit a minimal reproducible case that I can pass on to the development team:

 

https://thebuildingcoder.typepad.com/blog/about-the-author.html#1b

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 11

maxime.touchard7RAK6
Contributor
Contributor

Hi Jeremy,

Thank you for your quick reply.

As you can see in the attacted image, the part seems to to respect all the conditions. I tried the same sample on a Generic wall and I get the same issue... I'm starting to doubt 😞
To reproduce the problem :
I'm using Revit 2021.1.3
Steps :
    -Create new project
    -Create one wall (Generic 200mm)
    -Go to "Create tab"
    -Click "Create Parts"
    -Execute the previous sample on the recently created Part

Thank you for your help

0 Likes
Message 4 of 11

jeremy_tammik
Alumni
Alumni

Does the same operation work as you expect when you drive it manually through the end user interface?

 

Please check that first.

 

Secondly, please submit a complete minimal reproducible case for this, including your complete macro or add-in solution and a minimal model to test it in, just in case there is something special in the somewhere that we might otherwise miss.

 

https://thebuildingcoder.typepad.com/blog/about-the-author.html#1b

 

Thank you!

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 5 of 11

maxime.touchard7RAK6
Contributor
Contributor

Hi Jeremy,
Yes it works in the UI.
Here is a minimum test file. The wall in the file in one big part which can be edited by the UI using the shape handles. But while trying to edit the part with SetFaceOffset() it always fail.

My code:

#region Namespaces
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;

#endregion

namespace SameTypeJunctionLayers
{
    [Transaction(TransactionMode.Manual)]
    public class Command : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument uidoc = uiapp.ActiveUIDocument;
            Autodesk.Revit.ApplicationServices.Application app = uiapp.Application;
            Document doc = uidoc.Document;

            Reference refS = uidoc.Selection.PickObject(ObjectType.Element);
            Part p = doc.GetElement(refS.ElementId) as Part;
            Options opt = new Options();
            opt.View = doc.ActiveView;
            opt.ComputeReferences = true;
            GeometryElement geomElem = p.get_Geometry(opt);

            using (Transaction tr = new Transaction(doc, "edit part"))
            {
                tr.Start();
                foreach (GeometryObject geomObject in geomElem)
                {
                    if (geomObject is Solid)
                    {
                        Solid solid = geomObject as Solid;
                        FaceArray faceArray = solid.Faces;
                        foreach (Face face in faceArray)
                        {
                            if (p.CanOffsetFace(face))
                            {
                                try
                                {
                                    p.SetFaceOffset(face, 0.1);
                                    MessageBox.Show("offseted");
                                }
                                catch
                                {
                                    MessageBox.Show("notOffsetd");
                                }
                            }
                            else
                            {
                                MessageBox.Show("cantbeOffseted");
                            }
                        }
                    }
                }
                tr.Commit();
            }
            return Result.Succeeded;
        }
    }
}
0 Likes
Message 6 of 11

jeremy_tammik
Alumni
Alumni

Dear Maxime,

 

Thank you for your report, clear description and sample material.

 

Sorry to hear about this.

 

I logged the issue REVIT-178837 [SetFaceOffset Face doesn't belong to the Part] 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.

 

You are welcome to request an update on the status of this issue or to provide additional information on it at any time quoting this change request number.

 

This issue is important to me. What can I do to help?

 

This issue needs to be assessed by our engineering team and prioritised against all other outstanding change requests. Any information that you can provide to influence this assessment will help. Please provide the following where possible:

 

  • Impact on your application and/or your development.
  • The number of users affected.
  • The potential revenue impact to you.
  • The potential revenue impact to Autodesk.
  • Realistic timescale over which a fix would help you.
  • In the case of a request for a new feature or a feature enhancement, please also provide detailed Use cases for the workflows that this change would address.

 

This information is extremely important. Our engineering team have limited resources, and so must focus their efforts on the highest impact items. We do understand that this will cause you delays and affect your development planning, and we appreciate your cooperation and patience.

 

I hope this helps.

 

Best regards,

 

Jeremy

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 7 of 11

jeremy_tammik
Alumni
Alumni

Dear Maxime,

 

The development team analysed the issue REVIT-178837 [SetFaceOffset Face doesn't belong to the Part] and reply:

 

I implemented the attached Revit macro JWMTestRevitMacro.txt also listed below that's almost identical to the one provided by the add-in developer.

 

It works as expected in my internal development build.

 

Does it fix the problem for Maxime as well?

 

What is the actual error message?

 

"face doesn't belong to the part" is not a real error message, as far as I can tell.

 

I found the exception "face does not belong to the part." in Revit's Part code.

 

However, as said, I did not encounter any errors or exceptions running my attached macro code.

 

Please test it your end as well and let us know how it goes.

 

Thank you!

 

Best regards,

 

Jeremy

 

/*
 * Created by SharpDevelop.
 * User: mitchej
 * Date: 6/25/2021
 * Time: 11:06 AM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;
using System.Windows;

namespace JWMTest
{
  [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
  [Autodesk.Revit.DB.Macros.AddInId("408FA176-F788-4C86-B988-6AD65804DD9E")]
  public partial class ThisDocument
  {
    private void Module_Startup(object sender, EventArgs e)
    {
    }

    private void Module_Shutdown(object sender, EventArgs e)
    {
    }

    #region Revit Macros generated code
    private void InternalStartup()
    {
      this.Startup += new System.EventHandler(Module_Startup);
      this.Shutdown += new System.EventHandler(Module_Shutdown);
    }
    #endregion
    
    public Result JWMTestMacro()
    {
      Document doc = this.Document;
      Reference refS = this.Selection.PickObject(ObjectType.Element);
      Part p = doc.GetElement(refS.ElementId) as Part;
      Options opt = new Options();
      opt.View = doc.ActiveView;
      opt.ComputeReferences = true;
      GeometryElement geomElem = p.get_Geometry(opt);

      using (Transaction tr = new Transaction(doc, "edit part"))
      {
        tr.Start();
        foreach (GeometryObject geomObject in geomElem)
        {
            if (geomObject is Solid)
            {
              Solid solid = geomObject as Solid;
              FaceArray faceArray = solid.Faces;
              foreach (Face face in faceArray)
              {
                  if (p.CanOffsetFace(face))
                  {
                    try
                    {
                        p.SetFaceOffset(face, 0.1);
                        //MessageBox.Show("offseted");
                    }
                    catch
                    {
                        //MessageBox.Show("notOffsetd");
                    }
                  }
                  else
                  {
                    //MessageBox.Show("cantbeOffseted");
                  }
              }
            }
        }
        tr.Commit();
      }      
      return Result.Succeeded;
    }
  }
}

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 8 of 11

jeremy_tammik
Alumni
Alumni

Is the issue resolved for you now?

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 9 of 11

RPTHOMAS108
Mentor
Mentor

Macro function needs to a have void return type to be listed in the macro manager to run.

 

Anyway I find it works when I made that change and pick a face in the 3D view.

 

I see cast to part is being done so know part is being selected.

 

The RevitAPI.chm notes the wording under ArgumentException:

"face does not belong to the part. -or- The face to be offset should be planar and satisfy constraints of its parent element"

 

Also is the function Part.CanOffsetFace working as expected? i.e. if you get the error after checking this then something is wrong there perhaps.

0 Likes
Message 10 of 11

maxime.touchard7RAK6
Contributor
Contributor
Accepted solution

Hi everyone,
Thanks a lot !
I do have a good news and a bad news.
Unfortunatly your sample doesn't resolve my problem. I don't know why.. Could it comes from my version of the software (2021.1.3) ? Something else ?
The good news now : I found a workaround. So for anyone having the problem here is the sample that is worked for me :

 

 

public static Result test(Document doc, UIDocument uidoc)
{
    Reference refS = uidoc.Selection.PickObject(ObjectType.Element);
    Part p = doc.GetElement(refS.ElementId) as Part;
    Options opt = new Options();
    opt.View = doc.ActiveView;
    opt.ComputeReferences = true;
    GeometryElement geomElem = p.get_Geometry(opt);
    using (Transaction tr = new Transaction(doc, "edit part"))
    {
        tr.Start();
        foreach (GeometryObject geomObject in geomElem)
        {
            if (geomObject is Solid)
            {
                Solid solid = geomObject as Solid;
                FaceArray faceArray = solid.Faces;
                foreach (Face face in faceArray)
                {
                    PlanarFace refFace = p.GetGeometryObjectFromReference(face.Reference) as PlanarFace;
                    if (refFace == null)
                    {
                        continue;
                    }
                    if (p.CanOffsetFace(refFace))
                    {
                        try
                        {
                            p.SetFaceOffset(refFace, 0.1);
                            // MessageBox.Show("offseted");
                        }
                        catch(Exception exp)
                        {
                            MessageBox.Show("notOffsetd " + exp.Message);
                        }
                    }
                    else
                    {
                        //MessageBox.Show("cantbeOffseted");
                    }
                }
            }
        }
        tr.Commit();
    }
    return Result.Succeeded;
}

 

As you can see I have to get the face with GetGeometryObjectFromReference() so the function SetFaceOffset() recognize the that the Face belongs to the Part.

Message 11 of 11

jeremy_tammik
Alumni
Alumni

Congratulations on solving and thank you very much for letting us know how!

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes