こちらの続きです。
毛を生やす4 - C#ATIA
え~今回は毛を生やしません。
前回のサーフェスを作る・作らないは、その面が該当するボディにとっての外側・内側を
判断し外側と判定した面の場合のみ作っていました。
(そもそも外側・内側の境界って何なのかな?)
これをボディ丸ごと処理するようにしたものがこちらです。
import traceback
import adsk
import adsk.core as core
import adsk.fusion as fusion
_app: core.Application = None
_ui: core.UserInterface = None
_handlers = []
_selFace: core.SelectionCommandInput = None
CMD_INFO = {
'id': 'kantoku_test',
'name': 'test',
'tooltip': 'test'
}
class MyCommandCreatedHandler(core.CommandCreatedEventHandler):
def __init__(self):
super().__init__()
def notify(self, args: core.CommandCreatedEventArgs):
try:
global _handlers
cmd: core.Command = core.Command.cast(args.command)
onDestroy = MyCommandDestroyHandler()
cmd.destroy.add(onDestroy)
_handlers.append(onDestroy)
onExecutePreview = MyExecutePreviewHandler()
cmd.executePreview.add(onExecutePreview)
_handlers.append(onExecutePreview)
inputs: core.CommandInputs = cmd.commandInputs
global _selFace
_selFace = inputs.addSelectionInput(
"_selFaceId",
"ボディ",
"外側のみ抜き出すボディを選んで!",
)
_selFace.addSelectionFilter(core.SelectionCommandInput.Bodies)
except:
_ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
class MyExecutePreviewHandler(core.CommandEventHandler):
def __init__(self):
super().__init__()
def notify(self, args: core.CommandEventArgs):
args.isValidResult = True
body: fusion.BRepBody = _selFace.selection(0).entity
outerBody: fusion.BRepBody = get_shell_faces(body)
if not outerBody:
return
comp: fusion.Component = body.parentComponent
des: fusion.Design = comp.parentDesign
baseFeat: fusion.BaseFeature = None
if des.designType == fusion.DesignTypes.ParametricDesignType:
baseFeat = comp.features.baseFeatures.add()
bodies: fusion.BRepBodies = comp.bRepBodies
if baseFeat:
baseFeat.startEdit()
bodies.add(outerBody, baseFeat)
baseFeat.finishEdit()
else:
bodies.add(outerBody, baseFeat)
def get_shell_faces(
body: fusion.BRepBody,) -> fusion.BRepBody:
comp: fusion.Component = body.parentComponent
tmpFeat: fusion.TemporaryBRepManager = fusion.TemporaryBRepManager.get()
outerBody: fusion.BRepBody = None
face: fusion.BRepFace = None
for face in body.faces:
meshCalculator: fusion.TriangleMeshCalculator = face.meshManager.createMeshCalculator()
meshCalculator.maxAspectRatio = 1
meshCalculator.maxSideLength = 0.1 if face.area < 1 else face.area * 0.1
triMesh: fusion.TriangleMesh = meshCalculator.calculate()
nodes = list(triMesh.nodeCoordinates)
normals = list(triMesh.normalVectors)
limit = int(len(nodes) * 0.3)
innerPoints: int = 0
for p, v in zip(nodes,normals):
v2: core.Vector3D = v.copy()
v2.scaleBy(0.01)
p2: core.Point3D = p.copy()
p2.translateBy(v2)
hitBodies = comp.findBRepUsingRay(
p2,
v,
fusion.BRepEntityTypes.BRepBodyEntityType,
-1,
False,
None,
)
if hitBodies.count < 1:
continue
for hitBody in hitBodies:
if hitBody.entityToken == body.entityToken:
innerPoints += 1
break
if innerPoints > limit:
break
if not innerPoints > limit:
if outerBody:
tmpFeat.booleanOperation(
outerBody,
tmpFeat.copy(face),
fusion.BooleanTypes.UnionBooleanType,
)
else:
outerBody = tmpFeat.copy(face)
return outerBody
class MyCommandDestroyHandler(core.CommandEventHandler):
def __init__(self):
super().__init__()
def notify(self, args: core.CommandEventArgs):
adsk.terminate()
def run(context):
try:
global _app, _ui
_app = core.Application.get()
_ui = _app.userInterface
cmdDef: core.CommandDefinition = _ui.commandDefinitions.itemById(
CMD_INFO['id']
)
if not cmdDef:
cmdDef = _ui.commandDefinitions.addButtonDefinition(
CMD_INFO['id'],
CMD_INFO['name'],
CMD_INFO['tooltip']
)
global _handlers
onCommandCreated = MyCommandCreatedHandler()
cmdDef.commandCreated.add(onCommandCreated)
_handlers.append(onCommandCreated)
cmdDef.execute()
adsk.autoTerminate(False)
except:
if _ui:
_ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
前回のデータで試すとこんな感じです。


久々にこうしておきます。
"これはいったい何に使うの?" と思われた方には役に立たないでしょうね。