こちらの続きです。
凸包に挑んでみる5 - C#ATIA
結局あっさり諦め、利用しやすそうな軽めのライブラリを探しました。
Start Small: 3D Convex hull in Python
blenderaddons/chull.py at master · varkenvarken/blenderaddons · GitHub
本来、'blender' 向けのようなのですが、他のライブラリとの依存が無く
このファイル 'chull.py' だけで利用できました。
その為、このスプリクトと同一フォルダ内に 'chull.py' を置いておく必要があります。
#FusionAPI_python test_ConvexHull3D #Author-kantoku #Description-新たなスケッチを作成し、ランダムに3Dな点を作成し、3Dな凸包を作成 # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. import adsk.core, adsk.fusion, traceback import random, os, sys this_dir = os.path.dirname(os.path.abspath(__file__)) sys.path.append(this_dir) #thx-varkenvarken #chttps://michelanders.blogspot.com/2012/02/3d-convex-hull-in-python.html #https://github.com/varkenvarken/blenderaddons/blob/master/chull.py import chull def run(context): #Create Point Count p_count = 100 ui = None try: #extension chull.Vertex.toPnt = ToPoint3d chull.Face.toSkt = ToSketch adsk.core.Point3D.toVec = ToCHullVector adsk.fusion.Sketch.initSurf = InitSurface #preparation app = adsk.core.Application.get() ui = app.userInterface des = app.activeProduct root = des.rootComponent #RandomPoint skt = root.sketches.add(root.xYConstructionPlane) skt.name = 'points' CreateRandomPoint(skt, -10.0, 10.0, p_count) #time import time t = time.time() #coordinate array pnts = [p.geometry.asArray() for p in skt.sketchPoints] del pnts[0] #remove origin point #edges sketch skt = root.sketches.add(root.xYConstructionPlane) skt.name = 'edges' #ConvexHull face_count = InitConvexHull(pnts,skt) #finish ui.messageBox('Point Count:{}\nface Count:{}\ntime:{:.2f}s' .format(p_count,face_count,time.time()- t)) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) #ConvexHull def InitConvexHull(point3d_list,target_sketch): if len(point3d_list) < 4: return #hull pnts = [chull.Vector(ary[0],ary[1],ary[2]) for ary in point3d_list] hull = chull.Hull(pnts) #edges [f.toSkt(target_sketch) for f in hull.faces] #faces target_sketch.initSurf() return len(hull.faces) #RandomPoint def CreateRandomPoint(skt, low, upp, count): pnts = [adsk.core.Point3D.create( random.uniform(low,upp),random.uniform(low,upp),random.uniform(low,upp)) for dmy in range(count)] skt_Pnts = skt.sketchPoints [skt_Pnts.add(pnt) for pnt in pnts] # --- extension method --- #chull.Vertex def ToPoint3d(self): return adsk.core.Point3D.create( self.v.x,self.v.y,self.v.z) #chull.Face def ToSketch(self, skt): #Vertex pnts = skt.sketchPoints ps = [pnts.add(p.toPnt()) for p in self.vertex] #edge lins = skt.sketchCurves.sketchLines edges =[(ps[0],ps[1]),(ps[1],ps[2]),(ps[2],ps[0])] [lins.addByTwoPoints(p0,p1) for p0,p1 in edges] #adsk.core.Point3D def ToCHullVector(self): ary = self.asArray() return chull.Vector(ary[0],ary[1],ary[2]) #adsk.fusion.Sketch def InitSurface(self,tolerance = 0.001): if len(self.profiles) < 1: return newBodyOpe = adsk.fusion.FeatureOperations.NewBodyFeatureOperation comp = self.parentComponent feats = comp.features objs = adsk.core.ObjectCollection.create() [objs.add(v) for v in self.profiles] patches = feats.patchFeatures pats = patches.add(patches.createInput(objs,newBodyOpe)) objs.clear() [objs.add(v) for v in pats.bodies] tol = adsk.core.ValueInput.createByReal(tolerance) stitches = feats.stitchFeatures stitches.add(stitches.createInput(objs, tol, newBodyOpe))
結果的に、ベクトル演算等細かなことは一切不要でした。
VBAっぽさを消す為、拡張メソッドを作成しポコポコ呼び出して終わりです。
動画は1分程ですが、半分は処理待ち・・・遅いのは面の作成で
凸包の頂点はほぼ一瞬で求まっています。
質問者さんにちゃんとレスしてあげたかったな。