offset

offset

Anonymous
Not applicable
2,130 Views
8 Replies
Message 1 of 9

offset

Anonymous
Not applicable

Hi,

 

While placing sprinkles/Ceiling Lights on ceilings I am trying to offset them by a negative value so that they get placed below the ceiling but somehow the sprinkers/Ceiling Lights are getting placed on top of it. Kindly help:

 

The code to place ceiling sprinkers/Ceiling Lights is as follows:

 

public static FamilyInstance InsertCeilingElements(Document doc, XYZ location, String FamilyName, Element host,double offset)
{

FamilySymbol symbol = null;
foreach (FamilySymbol symbq in fsym)
{
String dd1 = symbq.Name;
String ff = symbq.Category.Name;
Family fm = symbq.Family;

 

Boolean fnd = false;


String[] Famarr = FamilyName.Split(new string[] { "=>" }, StringSplitOptions.None);
if (dd1 == Famarr[1] && ff == Famarr[0])
{
symbol = symbq;

fnd = true;

break;
}
if (fnd == true)
{
break;
}
}
FamilyInstance Finst= null;
using (Transaction t = new Transaction(doc, "Place Instance"))
{
t.Start();
Ceiling ceil = (Ceiling)host;
Options opt1 = Command.app.Create.NewGeometryOptions();
opt1.ComputeReferences = true;
ceil.get_Geometry(opt1);
GeometryElement geo = ceil.get_Geometry(opt1);

PlanarFace ceilingBottom = null;

foreach (GeometryObject obj in geo.Objects)
{
Solid solid = obj as Solid;

if (null != solid)
{
foreach (Face face in solid.Faces)
{

PlanarFace pf = face as PlanarFace;

if (null != pf)
{
XYZ normal = pf.Normal;


ceilingBottom = pf;
XYZ x = new XYZ(0, 0, 0);


Finst= doc.Create.NewFamilyInstance(face, location, x, symbol);
Finst.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM).Set(-150);
t.Commit();
break;


}
}
}
}


}

 

return Finst;
}

0 Likes
Accepted solutions (1)
2,131 Views
8 Replies
Replies (8)
Message 2 of 9

Anonymous
Not applicable

 

PlanarFace pf = face as PlanarFace;


XYZ normal = pf.Normal;

 

In practice I've found that the vectors obtained using both Planarface.Normal and the Transform returned by PlanarFace.ComputeDerivitives() are unreliable and tend to be the opposite of what they should be (but not always...).

 

Instead you should use the PlanarFace.ComputeNormal() method, I usually just pass in UV.Zero and to date I've had no issues.

 

Edit:

 

 Also, after looking at your code again, you are just taking the first face that you find and then throwing the family instance on it without checking whether it is indeed the bottom face of the ceiling, you could check the face normal for this.

 

A better way to get the bottom face of a host element is to use HostObjectUtils.GetBottomFaces() and then directly use the references returned for placement using the appropriate overload of NewFamilyInstance.

 

And one more tip. Move that t.Commit() statement out of the foreach loop, calling Commit() multiple times will throw an exception, the only thing saving you at the moment is the break; directly below it. I hope you don't take this as hash criticism, just trying to be helpful.

0 Likes
Message 3 of 9

Anonymous
Not applicable

Hi Scott,

 

Using HostObjectUtils.GetBottomFaces()  returns error:

 

 

IList<Reference> references = HostObjectUtils.GetBottomFaces(ceil);
Face lface=null;
foreach (Reference myRef in references)
{


lface = ceil.GetGeometryObjectFromReference(myRef) as Face;


}
try
{
finstance = doc.Create.NewFamilyInstance(lface, location, x, symbol);
}
catch (Exception er)
{

MessageBox.Show(er.ToString());
}

 

 

 

Autodesk.Revit.Exceptions.ArgumentException: The Reference of the input face is null.  If the face was obtained from Element.Geometry, make sure to turn on the option 'ComputeReferences'.

 

The revit file which I am running this tool has a single ceiling element.

 

Also I need to know Can I offset all family instances or there are limitations to it:

 

finstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM).Set(offsetvalue);

 

Thanks & regards

 

 

0 Likes
Message 4 of 9

Anonymous
Not applicable

Hmm, that seems strange, I'd check whether the output from GetGeometryObjectFromReference() succesfully being cast to Face.

 

Try using the reference directly instead by using:

 

NewFamilyInstance(Reference reference, XYZ location, XYZ referenceDirection, FamilySymbol symbol)

 

In regard to the offset parameter question, I'm not sure off the top of my head, hopefully someone else can jump in on that one.

0 Likes
Message 5 of 9

Anonymous
Not applicable

Scott that was very sweet and gentle. Such a quick reply.

 

Using NewFamilyInstance(Reference reference, XYZ location, XYZ referenceDirection, FamilySymbol symbol) also returned error:

 

reference direction is parallel to face normal at insertion point.

 

I am able ro place elements on ceiling with the code I posted initially but they get placed above ceiling so I need to offset the placed elements by a negative value so that they come under the ceiling but some elements are able to offset but some not. That was the reason I asked that can offset be applied to all family instances.

 

 

ceilplacement.png

 

Thanks & Regards

0 Likes
Message 6 of 9

Anonymous
Not applicable
Accepted solution

What vector are you passing in as the reference direction? Looks like you passed in the face normal or XYZ.BasisZ. Try PlanarFace.get_Vector(0) or something else parallel to the ceiling plane.

 

I've just tried using NewFamilyInstance(Reference reference, XYZ location, XYZ referenceDirection, FamilySymbol symbol) and it does indeed work for a sprinkler family. Not all families are created in the same way though, see what info you get from FamilySymbol.Family.FamilyPlacementType, the sprinkler I used was "WorkPlaneBased" and a light family I tried was "OneLevelBasedHosted" which required a Level and the actual host element instead of a face.

 

As you said the original method you used was kind of working, but I think you were just using the top face for placement. If you were to compute the normal of each face and ensure that the one you are using is pointing downward you'll be back in business I'm sure.

 

Message 7 of 9

Anonymous
Not applicable

Dear Scott,

 

PlanarFace.get_Vector(0) worked like a charm. Thanks a ton.

 

I also wanted your valuable advice on revit programming from career perspective. I have been using revit api from last two years. 

 

 

Thanks & Regards

0 Likes
Message 8 of 9

Anonymous
Not applicable

Dear Scott,

 

A little help please.

 

say I have x,y points 234,56. when I place an element in linked cad which is linked using origin to origin the element gets placed perfectly. but in linked cad using center that element gets placed somewhere else.

Is there a way where I can convert these xy points so that they become suitable for center to center linked cad also.

 

Thanks & regards

 

0 Likes
Message 9 of 9

Anonymous
Not applicable

Sorry, I've not had any dealings with imported CAD elements so I can't be of much help.

0 Likes