BoundingBox Corner Coordinates

BoundingBox Corner Coordinates

floretti
Advocate Advocate
3,536 Views
13 Replies
Message 1 of 14

BoundingBox Corner Coordinates

floretti
Advocate
Advocate

Hi all, I've got a challenge I haven't quite worked out how to tackle yet and some help would go a long way before I invest days into it.

 

I need to collect my FamilyInstances' BoundingBox, "move" their boundaries inwards by specific amounts (arrows 1 to 4 below) and collect the resulting corners (A, B, C and D below). Any suggestions on how to achieve that or places I can find small snippets of code which could potentially help? Much appreciated.

 

I'm very familiar with collecting the BoundingBox of elements but I realise I may need to get into some more advanced maths topics such as normals and vectors, which I'm not as familiar especially in the coding world.

 

FabioLorettiOliveira_0-1626747113740.png

 

Accepted solutions (1)
3,537 Views
13 Replies
Replies (13)
Message 2 of 14

floretti
Advocate
Advocate

Just reporting on progress, the good news is that I managed to find a way to get the new coordinates of points based on the distance and angle.

 

FabioLorettiOliveira_1-1626777994017.png

 

The bad news is that I just realised that the BoundingBox for something that's been rotated is like the red lines below, which shows that my original plan won't work. Back to the drawing board...

 

FabioLorettiOliveira_0-1626777817943.png

 

0 Likes
Message 3 of 14

floretti
Advocate
Advocate

Ok, just reporting on progress, I managed to make the BoundingBox work by collecting the Symbol BoundingBox's 4 corners and applying the instance's point transform to each. The result is an accurate angled box, which I can then apply the formula shown above to each corner based on the instance's location angle and the desired distances (1, 2, 3 and 4). I'll keep going tomorrow and post the result here.

Message 4 of 14

floretti
Advocate
Advocate
Accepted solution

Ok, I resolved my own problem but I'll post the code here in case anyone comes across this in the future.

 

foreach (FamilyInstance instance in famInstances)
{
	if (instance.ViewSpecific != true)
	{
		Location instLocation = instance.Location;
		LocationPoint instLocPt = instLocation as LocationPoint;
		Double instRotationRad = instLocPt.Rotation;
		double instRotationDeg = UnitUtils.ConvertFromInternalUnits(instRotationRad, DisplayUnitType.DUT_DECIMAL_DEGREES);

		// Collect 4x corners of symbol Bbox
		BoundingBoxXYZ symBox = instance.Symbol.get_BoundingBox(doc.ActiveView);
		XYZ symBoxBL = symBox.Min;  // BL=bottom left
		XYZ symBoxTR = symBox.Max;  // TR=top right
		XYZ symBoxTL = new XYZ(symBoxBL.X, symBoxTR.Y, 0);
		XYZ symBoxBR = new XYZ(symBoxTR.X, symBoxBL.Y, 0);
		
		// Apply transform to each corner to find actual instance Bbox coordinates
		var transf = instance.GetTransform();
		XYZ coordBL = transf.OfPoint(symBoxBL);
		XYZ coordTR = transf.OfPoint(symBoxTR);
		XYZ coordTL = transf.OfPoint(symBoxTL);
		XYZ coordBR = transf.OfPoint(symBoxBR);

		// L=left, B=bottom, R=right, T=top
		double distL = 30;
		double distB = 15;
		double distR = 20;
		double distT = 10;

		//Formulas
		//double newX = oldX + dist * Math.Cos(angle * Math.PI / 180);
		//double newY = oldY + dist * Math.Sin(angle * Math.PI / 180);

		#region BOTTOM LEFT CORNER
		double startBLx = coordBL.X +
					   UnitUtils.ConvertToInternalUnits(distL, DisplayUnitType.DUT_MILLIMETERS) *
					   Math.Cos((instRotationDeg) * Math.PI / 180);
		double startBLy = coordBL.Y +
					   UnitUtils.ConvertToInternalUnits(distL, DisplayUnitType.DUT_MILLIMETERS) *
					   Math.Sin((instRotationDeg) * Math.PI / 180);
		double finalBLx = startBLx +
				   UnitUtils.ConvertToInternalUnits(distB, DisplayUnitType.DUT_MILLIMETERS) *
				   Math.Cos((instRotationDeg + 90) * Math.PI / 180);
		double finalBLy = startBLy +
					   UnitUtils.ConvertToInternalUnits(distB, DisplayUnitType.DUT_MILLIMETERS) *
					   Math.Sin((instRotationDeg + 90) * Math.PI / 180);

		Log.Information("BotL: ({0},{1})", finalBLx, finalBLy);
		#endregion

		#region BOTTOM RIGHT CORNER
		double startBRx = coordBR.X +
					   UnitUtils.ConvertToInternalUnits(distR, DisplayUnitType.DUT_MILLIMETERS) *
					   Math.Cos((instRotationDeg + 180) * Math.PI / 180);
		double startBRy = coordBR.Y +
					   UnitUtils.ConvertToInternalUnits(distR, DisplayUnitType.DUT_MILLIMETERS) *
					   Math.Sin((instRotationDeg + 180) * Math.PI / 180);
		double finalBRx = startBRx +
				   UnitUtils.ConvertToInternalUnits(distB, DisplayUnitType.DUT_MILLIMETERS) *
				   Math.Cos((instRotationDeg + 90) * Math.PI / 180);
		double finalBRy = startBRy +
					   UnitUtils.ConvertToInternalUnits(distB, DisplayUnitType.DUT_MILLIMETERS) *
					   Math.Sin((instRotationDeg + 90) * Math.PI / 180);

		Log.Information("BotR: ({0},{1})", finalBRx, finalBRy);
		#endregion

		#region TOP RIGHT CORNER
		double startTRx = coordTR.X +
					   UnitUtils.ConvertToInternalUnits(distR, DisplayUnitType.DUT_MILLIMETERS) *
					   Math.Cos((instRotationDeg + 180) * Math.PI / 180);
		double startTRy = coordTR.Y +
					   UnitUtils.ConvertToInternalUnits(distR, DisplayUnitType.DUT_MILLIMETERS) *
					   Math.Sin((instRotationDeg + 180) * Math.PI / 180);
		double finalTRx = startTRx +
				   UnitUtils.ConvertToInternalUnits(distT, DisplayUnitType.DUT_MILLIMETERS) *
				   Math.Cos((instRotationDeg + 270) * Math.PI / 180);
		double finalTRy = startTRy +
					   UnitUtils.ConvertToInternalUnits(distT, DisplayUnitType.DUT_MILLIMETERS) *
					   Math.Sin((instRotationDeg + 270) * Math.PI / 180);

		Log.Information("TopR: ({0},{1})", finalTRx, finalTRy);
		#endregion

		#region TOP LEFT CORNER
		double startTLx = coordTL.X +
					   UnitUtils.ConvertToInternalUnits(distT, DisplayUnitType.DUT_MILLIMETERS) *
					   Math.Cos((instRotationDeg + 270) * Math.PI / 180);
		double startTLy = coordTL.Y +
					   UnitUtils.ConvertToInternalUnits(distT, DisplayUnitType.DUT_MILLIMETERS) *
					   Math.Sin((instRotationDeg + 270) * Math.PI / 180);
		double finalTLx = startTLx +
				   UnitUtils.ConvertToInternalUnits(distL, DisplayUnitType.DUT_MILLIMETERS) *
				   Math.Cos((instRotationDeg) * Math.PI / 180);
		double finalTLy = startTLy +
					   UnitUtils.ConvertToInternalUnits(distL, DisplayUnitType.DUT_MILLIMETERS) *
					   Math.Sin((instRotationDeg) * Math.PI / 180);

		Log.Information("TopL: ({0},{1})", finalTLx, finalTLy);
		#endregion

	}
}
Message 5 of 14

joseph.he
Contributor
Contributor

I know its been a while since you posted this, but just wanted to say massive thanks for going through and posting the code and solution. Thank you!

0 Likes
Message 6 of 14

floretti
Advocate
Advocate
I get a lot of help from people in this forum. It would only be fair to give some back. 🙂
Message 7 of 14

mizrachi_amir2
Advocate
Advocate

Thanks, @floretti, for sharing this!
I am assuming that your solution is based on instances that are Point based (their Location is LocationPoint) and not a Curve based.
As far as I understand from a short research on that - instances that have LocationCurve do not need to have this kind pf transformation in their bounding box, as their bounding box is at the exact rotation as well.
Am I correct?

0 Likes
Message 8 of 14

jeremy_tammik
Alumni
Alumni

The bounding box of an element is always aligned with thr cardinal axes, and never rotated away from those. This means that for a thin, long, angles object, e.g., a 10 cm diameter pipe from 0,0,0 to  10m,10m,10m, the bounding box wil be more or less from 0,0,0 to  10m,10m,10m. So, it will have a volume of 10x10x10 = 1000 cubic metres instead of the optimised non-axis-aligned box that would have only 0.1 x 0.1 x length_of_pipe, which would be about  0.173 cubic metres.

   

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

mizrachi_amir2
Advocate
Advocate
Then I am confused with the red dashed lines illustrated above.
Why in this case the BB is rotated from the element itself?
0 Likes
Message 10 of 14

floretti
Advocate
Advocate

@mizrachi_amir2 I believe the element BB never rotates and it stays aligned to the XYZ axis, even if the element is rotated, hence the red dashed lines. What I had to do to get the rotated BB is, get the Symbol's BB and apply the transform, which has the rotation information.

0 Likes
Message 11 of 14

jeremy_tammik
Alumni
Alumni

The bounding box is NOT rotated. It is aligned with the cardinal axes. The element has a rotation.

  

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

Chuong.Ho
Advocate
Advocate

- In case you don't need care so much about angle and just want to see list point conors follow  the cardinal axes

Revit_rW8L9NEtN8.gif

```

public static List<XYZ> Corners(BoundingBoxXYZ boundingBox)
{
    if (boundingBox == null)
    {
        throw new ArgumentNullException("BoundingBox is null");
    }
    
    XYZ minPoint = boundingBox.Min;
    XYZ maxPoint = boundingBox.Max;
    
    List<XYZ> corners = new List<XYZ>();
    corners.Add(minPoint);
    corners.Add(new XYZ(minPoint.X, minPoint.Y, maxPoint.Z));
    corners.Add(new XYZ(minPoint.X, maxPoint.Y, minPoint.Z));
    corners.Add(new XYZ(minPoint.X, maxPoint.Y, maxPoint.Z));
    corners.Add(new XYZ(maxPoint.X, minPoint.Y, minPoint.Z));
    corners.Add(new XYZ(maxPoint.X, minPoint.Y, maxPoint.Z));
    corners.Add(new XYZ(maxPoint.X, maxPoint.Y, minPoint.Z));
    corners.Add(maxPoint);
    
    return corners;
}

```

 

Chuong Ho

EESignature

0 Likes
Message 13 of 14

mizrachi_amir2
Advocate
Advocate

Hi @Chuong.Ho, I do care about the rotation and angles. Meaning if my Element is rotated I need all 6 planes of its (rotated) bounding box.

I just don't get the idea presented here using the GetTransform() - I inspeted a horizontal element and inspected that same element rotated 45 degrees and the returned back value of the Transform attribute was exactly the same in both cases. 

0 Likes
Message 14 of 14

floretti
Advocate
Advocate

@mizrachi_amir2 Do you mind sharing how you got the Transform for the two elements?

0 Likes