Community
Fusion API and Scripts
Got a new add-in to share? Need something specialized to be scripted? Ask questions or share what you’ve discovered with the community.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Bug: Reversed normal when doing difference with temporory rotated bodies?

1 REPLY 1
Reply
Message 1 of 2
JesusFreke
155 Views, 1 Reply

Bug: Reversed normal when doing difference with temporory rotated bodies?

I was doing some design work using temporary brep bodies, and ran into a situation where the normal of a planar face seemed to be inexplicably reversed. I've simplified things into a minimal-ish reproducible example script.

 

import adsk.core
import adsk.fusion
from adsk.core import Matrix3D, Point3D, OrientedBoundingBox3D, Vector3D
import math

def run(_):
design().designType = adsk.fusion.DesignTypes.DirectDesignType

side = box(10, 6, .75)
side = rx(side, 90)
side = rz(side, 90)

back = box(10, 6, .75)
pin = translate(
box(.5, 2, .75),
-.25, 2, 0)

brep().booleanOperation(back, pin,
adsk.fusion.BooleanTypes.UnionBooleanType)
rx(back, 90)
translate(back,
.5, 10, 0)

brep().booleanOperation(side, back,
adsk.fusion.BooleanTypes.DifferenceBooleanType)

side_occurrence = create_occurrence(side)

translate(back, 2, 0, 0)
create_occurrence(back)

for face in side_occurrence.bRepBodies[0].faces:
# The face we want has an area of 2
if abs(2 - face.area) < .001:
ui().activeSelections.add(face)
print(face.geometry.normal.asArray())
print(face.geometry.evaluator.getNormalAtPoint(face.pointOnFace)[1].asArray())

def app():
return adsk.core.Application.get()

def design():
return adsk.fusion.Design.cast(app().activeProduct)

def ui():
return app().userInterface

def root():
return design().rootComponent

def brep():
return adsk.fusion.TemporaryBRepManager.get()

def box(x, y, z):
return brep().createBox(OrientedBoundingBox3D.create(
Point3D.create(x/2, y/2, z/2),
Vector3D.create(1, 0, 0),
Vector3D.create(0, 1, 0),
x, y, z))

def translate(body, x, y, z):
translation = Matrix3D.create()
translation.translation = adsk.core.Vector3D.create(x, y, z)

brep().transform(body, translation)
return body

def rotate(body, axis, angle):
transform = Matrix3D.create()
rotation = Matrix3D.create()
rotation.setToRotation(math.radians(angle), axis, Point3D.create(0, 0, 0))
transform.transformBy(rotation)
brep().transform(body, transform)
return body

def rx(body, angle):
return rotate(body, Vector3D.create(1, 0, 0), angle)

def rz(body, angle):
return rotate(body, Vector3D.create(0, 0, 1), angle)

def create_occurrence(body):
occurrence = root().occurrences.addNewComponent(Matrix3D.create())
occurrence.component.bRepBodies.add(body)
return occurrence

 

This results in the following object, with the offending face selected:

 

fusion_reversed_normals.png

 

The normal of the selected face is (0.0, -1.0, -2.2204460492503126e-16). However, if you look at the selected face, it's normal is clearly in the positive y direction

 

As part of trying to create the minimal reproduction, I noticed that I couldn't reproduce the issue if I created the boxes in the correct orientation to begin with. It only occurs if I create them laying down flat, and then rotate them into the correct orientation.

1 REPLY 1
Message 2 of 2
JesusFreke
in reply to: JesusFreke

Nevermind, I just figured it out. I just noticed the BRepFace.isParamReversed property, which is set to indicate the normal from the geometry object is reversed.

 

I confirmed that isParamReversed is True in this case, and also that face.evaluator.getNormalAtPoint() returns the correct normal. My script was previously using face.geometry.normal, or face.geometry.evaluator.getNormalAtPoint(), both of which are affected by the isParamReversed property

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report