Good day,
yesterday I had the issue to create a closed slabedge made of a series of arches or a combination of arches and straight lines. There are 3 ways to create an arc, but actually only one works for me as the double precission in revit kills you. The input comes from a database and the user can create an arc by:
As I will only use method 1 as method 2 doesn't exist in the api, I wrote a function to convert method 2 in method 1.
public static XYZ GetMidPoint(XYZ sPoint, XYZ ePoint, XYZ cPoint)
{
XYZ sDir = sPoint - cPoint;
XYZ eDir = ePoint - cPoint;
double sR = Math.Sqrt(sDir.X * sDir.X + sDir.Y * sDir.Y + sDir.Z * sDir.Z); // Start radius
double eR = Math.Sqrt(eDir.X * eDir.X + eDir.Y * eDir.Y + eDir.Z * eDir.Z); // End radius
double mR = (sR + eR) / 2; // Radius of the midpoint
XYZ mDir = (eDir + sDir) / 2; // Director for the midpoint
// Norm of the midpoint director (used to normalize the director)
double norm_mDir = Math.Sqrt( mDir.X * mDir.X + mDir.Y * mDir.Y + mDir.Z * mDir.Z );
/*
if (eR == 0 || sR/eR < 0.9999 || sR/eR > 1.0001)
{
//MessageBox.Show("Three points do not make an arc.");
}
*/
XYZ mPoint = new XYZ(cPoint.X + mDir.X * mR / norm_mDir, cPoint.Y + mDir.Y * mR / norm_mDir, cPoint.Z + mDir.Z * mR / norm_mDir);
return mPoint;
}
For degugging I had a messagebox pop up just to see revits internal impressive precission ;-).
The code creating the floor plate that uses this function see below.
public static Floor PlaceSlab(Document uidoc, List<XYZ> CoordList, Level baseLevel, double thickness, double offset, List<ArcEntry> ThirdPoints)
{
FloorType aFloorType = null;
FloorType newFloorType = null;
bool FloorTypeExists = false;
string NewFloorTypeName = "Slab_" + (thickness * 1000).ToString();
FilteredElementCollector collector = new FilteredElementCollector(uidoc);
collector.OfClass(typeof(FloorType));
foreach (FloorType floortype in collector)
{
if (floortype.Name == NewFloorTypeName)
{
aFloorType = floortype;
FloorTypeExists = true;
break;
}
}
if (FloorTypeExists == false)
{
foreach (FloorType floortype in collector)
{
if (floortype.Name == "150 Concrete" || floortype.Name == "Generic 150mm")
{
aFloorType = floortype;
break;
}
}
newFloorType = aFloorType.Duplicate(NewFloorTypeName) as FloorType;
if (newFloorType != null)
{
CompoundStructure cs = newFloorType.GetCompoundStructure();
double layerWidth = UnitUtils.Convert(thickness, DisplayUnitType.DUT_METERS, DisplayUnitType.DUT_DECIMAL_FEET);
int layerIndex = cs.GetFirstCoreLayerIndex();
IList<CompoundStructureLayer> cslayers = cs.GetLayers();
foreach (CompoundStructureLayer csl in cslayers)
{
cs.SetLayerWidth(layerIndex, layerWidth);
layerIndex++;
}
newFloorType.SetCompoundStructure(cs);
}
}
else
{
newFloorType = aFloorType;
}
CurveArray SlabEdge = new CurveArray();
XYZ NormZ = new XYZ(0,0,1);
XYZ NormX = new XYZ(1,0,0);
for (int i = 0; i < CoordList.Count; i++)
{
if (ThirdPoints.Count > 0)
{
if (i == (CoordList.Count - 1))
{
// 0 - Line
// 1 - MidPoint Arc
// 2 - 3 Point Arc
switch (ThirdPoints[i].ArcType)
{
case 0:
Line aLine = Line.CreateBound(CoordList[i], CoordList[0]);
SlabEdge.Append(aLine);
break;
case 1:
try
{
XYZ mPoint = GlobalFunctions.GetMidPoint(CoordList[i], CoordList[0], ThirdPoints[i].CLine);
Arc aArc1 = Arc.Create(CoordList[i], CoordList[0], mPoint);
SlabEdge.Append(aArc1);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
break;
case 2:
Arc aArc2 = Arc.Create(CoordList[i],CoordList[0],ThirdPoints[i].CLine);
SlabEdge.Append(aArc2);
break;
}
}
else
{
// 0 - Line
// 1 - MidPoint Arc
// 2 - 3 Point Arc
switch (ThirdPoints[i].ArcType)
{
case 0:
Line aLine = Line.CreateBound(CoordList[i], CoordList[i+1]);
SlabEdge.Append(aLine);
break;
case 1:
try
{
XYZ mPoint = GlobalFunctions.GetMidPoint(CoordList[i], CoordList[i + 1], ThirdPoints[i].CLine);
Arc aArc1 = Arc.Create(CoordList[i], CoordList[i + 1], mPoint);
SlabEdge.Append(aArc1);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
break;
case 2:
Arc aArc2 = Arc.Create(CoordList[i], CoordList[i + 1], ThirdPoints[i].CLine);
SlabEdge.Append(aArc2);
break;
}
}
}
else
{
if (i == (CoordList.Count - 1))
{
Line aLine = Line.CreateBound(CoordList[i], CoordList[0]);
SlabEdge.Append(aLine);
}
else
{
Line aLine = Line.CreateBound(CoordList[i], CoordList[i + 1]);
SlabEdge.Append(aLine);
}
}
}
// Create a slab using the location line and slab type
try
{
Floor newFloor = uidoc.Create.NewFloor(SlabEdge, newFloorType, baseLevel, true);
double offSet = UnitUtils.Convert(offset, DisplayUnitType.DUT_METERS, DisplayUnitType.DUT_DECIMAL_FEET);
newFloor.get_Parameter(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM).Set(offSet);
return newFloor;
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
return null;
}
}
Maybe this code will help someone as it took me some hours to get it to work and here a screenshot with the final slabs.
regards
Christian
Solved! Go to Solution.
Solved by mikako_harada. Go to Solution.
Hi Christian,
Excellent! Thank you for sharing and thinking about the community!
(Update: Looks like we cannot accept the original post as a solution. Allow me to check mark here so that others knows that original post includes solution.)
Can't find what you're looking for? Ask the community or share your knowledge.