ちょっと前にこちらを公開しました。
GitHub - kantoku-code/Fusion360_DrawCurveOnSurface: Fusion360 DrawCurve OnSurface
指定した面上にクリックした境界・頂点を結ぶ線を描くアドインです。
地味な感じで何度か修正入れてます・・・。
フォーラムの方にも書いたのですが、このアドインの一番の欠点は
複数面にわたって線を描くことが出来ないんです。
(境界・頂点以外を指定出来ない事も・・・)
複数面に結ぶための処理方法が良くわからないんで、連日調べているものの
糸口が見つからない。誰かに相談したいものの誰にどんな内容で相談して
良いのかすら見当がつかないです。
そこで突貫でサーフェスのUVを可視化する為のスクリプトを作りました。
・・・紫外線じゃない方のUVです。
#FusionAPI_python Script #Author-kantoku #Description-マウスカーソル部分のUVを可視化 import adsk.core, adsk.fusion, traceback _app = adsk.core.Application.cast(None) _ui = adsk.core.UserInterface.cast(None) _handlers = [] _fact = None # 俺コマンド用情報 _cmdInfo = ['UVviewer','UVviewer','UVviewer'] # SelectionCommandInput用情報 _selSktInfo = ['dlgSel','何も選択出来ません','何も選択出来ません'] class CommandDestroyHandler(adsk.core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args): try: adsk.terminate() except: if _ui: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) class PreSelectHandler(adsk.core.SelectionEventHandler): def __init__(self): super().__init__() def notify(self, args): try: args = adsk.core.SelectionEventArgs.cast(args) args.isSelectable = False sel = args.selection ent = sel.entity entType :str = ent.objectType.split('::')[-1] global _fact if entType == 'BRepFace': _fact.setFace(ent) else: _fact.setFace(None) except: if _ui: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) class MouseMoveHandler(adsk.core.MouseEventHandler): def __init__(self): super().__init__() def notify(self, args :adsk.core.MouseEventArgs): try: global _fact _fact.setMouse( args.viewport, args.viewportPosition) _fact.update() args.viewport.refresh() except: if _ui: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) class CommandCreatedHandler(adsk.core.CommandCreatedEventHandler): def __init__(self): super().__init__() def notify(self, args): try: # -- Command -- global _ui, _handlers cmd = adsk.core.Command.cast(args.command) cmd.isPositionDependent = True cmd.isOKButtonVisible = False # -- Event -- onDestroy = CommandDestroyHandler() cmd.destroy.add(onDestroy) _handlers.append(onDestroy) # MouseMove onMouseMove = MouseMoveHandler() cmd.mouseMove.add(onMouseMove) _handlers.append(onMouseMove) # preSelect onPre = PreSelectHandler() cmd.preSelect.add(onPre) _handlers.append(onPre) # -- dialog -- global _selInfo inputs = cmd.commandInputs inputs.addSelectionInput(_selSktInfo[0], _selSktInfo[1], _selSktInfo[2]) # -- other -- global _fact _fact = DrawUVFactry() except: if _ui: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) class DrawUVFactry(): _vp = adsk.core.Viewport.cast(None) _face = adsk.fusion.BRepFace.cast(None) _clone = adsk.fusion.BRepFace.cast(None) _musPos = adsk.core.Point2D.cast(None) _cgGroup = adsk.fusion.CustomGraphicsGroup.cast(None) red = adsk.core.Color.create(255,0,0,255) _solidRed = adsk.fusion.CustomGraphicsSolidColorEffect.create(red) blue = adsk.core.Color.create(0,0,255,255) _solidBlue = adsk.fusion.CustomGraphicsSolidColorEffect.create(blue) def __init__(self): self.refreshCG() def __del__(self): self.removeCG() def removeCG(self): des :adsk.fusion.Design = _app.activeProduct cgs = [cmp.customGraphicsGroups for cmp in des.allComponents] cgs = [cg for cg in cgs if cg.count > 0] if len(cgs) < 1: return for cg in cgs: gps = [c for c in cg] gps.reverse() for gp in gps: gp.deleteMe() def refreshCG(self): self.removeCG() des :adsk.fusion.Design = _app.activeProduct root :adsk.fusion.Component = des.rootComponent self._cgGroup = root.customGraphicsGroups.add() def setMouse(self, vp :adsk.core.Viewport, musPos :adsk.core.Point2D): self._vp = vp self._musPos = musPos def setFace(self, face :adsk.fusion.BRepFace): if self._face == face: return self._face = face if face: tmpBrep = adsk.fusion.TemporaryBRepManager.get() cloneBody = tmpBrep.copy(face) self._clone = cloneBody.faces[0] else: self._clone = None def update(self): self.refreshCG() if not self._face: return pos3d = self._vp.viewToModelSpace(self._musPos) cam = self._vp.camera vec = cam.eye.vectorTo(cam.target) musPnt = adsk.core.Point3D.create( pos3d.x + vec.x, pos3d.y + vec.y, pos3d.z + vec.z) musInf = adsk.core.Line3D.create(pos3d, musPnt).asInfiniteLine() geo :adsk.core.Surface = self._clone.geometry ints = musInf.intersectWithSurface(geo) if ints.count < 1: return pnt :adsk.core.Point3D = min(ints, key = (lambda p:cam.eye.distanceTo(p))) eva :adsk.core.SurfaceEvaluator = self._clone.evaluator res, prm = eva.getParameterAtPoint(pnt) # print('{}:{}'.format(prm.x,prm.y)) crvsU = eva.getIsoCurve(prm.x, False) crvsV = eva.getIsoCurve(prm.y, True) for crv in crvsU: crvCg = self._cgGroup.addCurve(crv) crvCg.color = self._solidRed crvCg.weight = 2 for crv in crvsV: crvCg = self._cgGroup.addCurve(crv) crvCg.color = self._solidBlue crvCg.weight = 2 def run(context): try: global _app, _ui _app = adsk.core.Application.get() _ui = _app.userInterface des :adsk.fusion.Design = _app.activeProduct root :adsk.fusion.Component = des.rootComponent cmdDefs :adsk.core.CommandDefinitions = _ui.commandDefinitions global _cmdInfo cmdDef :adsk.core.CommandDefinition = cmdDefs.itemById(_cmdInfo[0]) if cmdDef: cmdDef.deleteMe() cmdDef = cmdDefs.addButtonDefinition(_cmdInfo[0],_cmdInfo[1],_cmdInfo[2]) global _handlers onCommandCreated = CommandCreatedHandler() cmdDef.commandCreated.add(onCommandCreated) _handlers.append(onCommandCreated) cmdDef.execute() adsk.autoTerminate(False) except: if _ui: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
こんな感じです。
マウスカーソルをキャプチャするのが面倒な為写ってませんが、赤と青が
交差している部分にマウスカーソルがあります。
ボディ上にマウスカーソルを置くとその位置のUVラインを表示します。
(恐らく)赤がUで青がVです。
そのうち、他人には役立たないと思われる小さなスクリプト類を、まとめて
置いておくところをGithubに作ろう。とても手元で管理しきれ無さそう。
この技術を何とか手に入れたい。狙っているのはスケッチのラインをボディに
ラップさせる処理です。こちらに公開されているものがあるのですが、
GitHub - hanskellner/Fusion360WrapSketch: Wrap sketch curves around a cylinder
制約が多い上、開発が止まってます。
昔、コードを読んだ際の記憶だと、全て丁寧に座標値を計算させて
ラッピングさせていたようですが、その方法だと確かに限界があります。
単一面であれば、僕は他の方法で出来る事を既に知っていますよ。