NCF参数化建筑论坛

标题: 马赛克【附代码】 [打印本页]

作者: 夜神    时间: 2010-6-22 16:11
标题: 马赛克【附代码】
[attach]8853[/attach]
代码未经过完全测试,可能个别情况下会出错。
发现bug请指出,谢谢。
'========================================

Option Explicit
run
SUB run
makeMosiac Rhino.GetObject("请选择物体", 0),Rhino.IntegerBox("最短方向的方块数",6),Rhino.RealBox("方块缩小比例",0.9)
END SUB
'--------------------------------------------
' nDensity:最小boundingBox边长的分段数
' rShrink:方块缩小比例
'--------------------------------------------
FUNCTION makeMosiac(obj,nDensity,rShrink)
DIM objs : objs=array(obj)
DIM pBox, boundingBox : pBox=Rhino.BoundingBox(objs)
DIM nX,nY,nZ  '包围盒三边的分段数
DIM minSide  '最短边代码
DIM lSide(2)  '包围盒三边长
DIM objTemp
DIM lCube   '马赛克边长
DIM iX,iY,iZ  '三个边的截线数
'计算最短边、马赛克边长、三个方向的马赛克数
lSide(0)=pBox(1)(0)-pBox(0)(0)
lSide(1)=pBox(2)(1)-pBox(1)(1)
lSide(2)=pBox(4)(2)-pBox(0)(2)
IF lSide(0)<=lSide(1) AND lSide(0)<=lSide(2) THEN
  minSide=0
  lCube=lSide(minSide)/nDensity
  iX=nDensity
  iY=int(lSide(1)/lCube+0.5) '四舍五入
  iZ=int(lSide(2)/lCube+0.5)
END IF
IF lSide(1)<=lSide(0) AND lSide(1)<=lSide(2) THEN
  minSide=1
  lCube=lSide(minSide)/nDensity
  iX=int(lSide(0)/lCube+0.5)
  iY=nDensity
  iZ=int(lSide(2)/lCube+0.5)
END IF
IF lSide(2)<=lSide(0) AND lSide(2)<=lSide(1) THEN
  minSide=2
  lCube=lSide(minSide)/nDensity
  iX=int(lSide(0)/lCube+0.5)
  iY=int(lSide(1)/lCube+0.5)
  iZ=nDensity
END IF
'定义马赛克空间, 并初始化为零(该空间没有马赛克)
DIM i,j,k,m,s
DIM p() : REDIM p((iX+1)*(iY+1)*(iZ+1))
FOR i=0 TO iX
  FOR j=0 TO iY
   FOR k=0 TO iZ
    p(i*(iY+1)*(iZ+1)+j*(iZ+1)+k)=0
   NEXT
  NEXT
NEXT
DIM iRoundUp '圆整后的坐标序号
DIM pCube(7)
'拆分物体
DIM nObjs : nObjs=UBound(objs)  '选择要马赛克的物体的数目
DIM nSfs  : nSfs=0 '打散后的NURBS曲面总数
DIM sfs()  : REDIM sfs(nSfs) '打散后的NURBS曲面
DIM sfsInEach,sfsInEachPlane,pVertice,pMeshFaces
DIM arrVerticeNum,nMeshFace '顶点序号;Mesh内面片数 '
FOR i=0 TO nObjs '对每一个所选的物体
  IF Rhino.IsSurface(objs(i))=vbTRUE AND Rhino.IsSurfaceTrimmed(objs(i))=vbFALSE THEN  '是单曲面,且不是裁剪曲面
   sfs(UBound(sfs))=objs(i)
   REDIM PRESERVE sfs(UBound(sfs)+1)
  ELSE  '是复合曲面或裁剪曲面
   Rhino.SelectObject objs(i)   
   Rhino.Command "-Mesh PolygonDensity 12  Enter Enter "  '数字12表示离散后的mesh精度,越大越精细,计算量也越大
   objTemp=Rhino.FirstObject(vbTRUE)   'Mesh面
   pMeshFaces=Rhino.MeshFaces(objTemp, vbTRUE)  'Mesh内所有顶点的集合
   arrVerticeNum=Rhino.MeshFaceVertices(objTemp)  'Mesh内各面角点序号集合
   nMeshFace=UBound(arrVerticeNum)  '面片总数
   Rhino.DeleteObject objTemp  '删除Mesh
   FOR j=0 TO nMeshFace '为每一个Mesh面片建立曲面
    objTemp=Rhino.AddSrfPt(Array(pMeshFaces(j*4+0),pMeshFaces(j*4+1),pMeshFaces(j*4+2),pMeshFaces(j*4+3)))
    sfs(UBound(sfs))=objTemp
    REDIM PRESERVE sfs(UBound(sfs)+1)
   NEXT
  END IF
NEXT
Rhino.UnSelectAllObjects
REDIM PRESERVE sfs(UBound(sfs)-1)
nSfs=UBound(sfs)
DIM pNorm,pStart,pEnd,sectLine,pSect,nSectPoints
'第一轮:平行Z轴
dim pTemp() :redim pTemp(0)
FOR i=0 TO iX
  FOR j=0 TO iY
   pStart=Array(pBox(0)(0)+i*lCube, pBox(0)(1)+j*lCube, pBox(0)(2))
   pEnd=Array(pBox(0)(0)+i*lCube, pBox(0)(1)+j*lCube, pBox(4)(2))
   sectLine=Rhino.AddLine(pStart,pEnd)
   FOR m=0 TO nSfs
    pSect=Rhino.CurveSurfaceIntersection(sectLine, sfs(m))
    IF IsArray(pSect)=vbTRUE THEN  '有交叉点,(此句费解,去掉IF后pSect就不是数组了)
     nSectPoints=UBound(pSect,1) '交叉点个数
     FOR k=0 TO nSectPoints
      iRoundUp=int((pSect(k,1)(2)-pStart(2))/lCube+0.5) '把交叉点位置圆整到马赛克中心
      p(i*(iY+1)*(iZ+1)+j*(iZ+1)+iRoundUp)=1 '该位置的马赛克状态为1(有马赛克)
      pTemp(ubound(pTemp))=Rhino.AddPoint(pSect(k,1))
      redim preserve pTemp(ubound(pTemp)+1)
     NEXT
    END IF
   NEXT
   Rhino.DeleteObject sectLine
  NEXT
NEXT
'第二轮:平行X轴
FOR k=0 TO iZ
  FOR j=0 TO iY
   pStart=Array(pBox(0)(0), pBox(0)(1)+j*lCube, pBox(0)(2)+k*lCube)
   pEnd=Array(pBox(2)(0), pBox(0)(1)+j*lCube, pBox(0)(2)+k*lCube)
   sectLine=Rhino.AddLine(pStart,pEnd)
   FOR m=0 TO nSfs
    pSect=Rhino.CurveSurfaceIntersection(sectLine, sfs(m))
    IF IsArray(pSect) THEN '有交叉点
     nSectPoints=UBound(pSect,1) '交叉点个数
     FOR i=0 TO nSectPoints
      iRoundUp=int((pSect(i,1)(0)-pStart(0))/lCube+0.5)
      p(iRoundUp*(iY+1)*(iZ+1)+j*(iZ+1)+k)=1
      pTemp(ubound(pTemp))=Rhino.AddPoint(pSect(i,1))
      redim preserve pTemp(ubound(pTemp)+1)
     NEXT
    END IF
   NEXT
   Rhino.DeleteObject sectLine
  NEXT
NEXT
'第三轮:平行Y轴
FOR k=0 TO iZ
  FOR i=0 TO iX
   pStart=Array(pBox(0)(0)+i*lCube, pBox(0)(1), pBox(0)(2)+k*lCube)
   pEnd=Array(pBox(0)(0)+i*lCube, pBox(3)(1), pBox(0)(2)+k*lCube)
   sectLine=Rhino.AddLine(pStart,pEnd)
   FOR m=0 TO nSfs
    pSect=Rhino.CurveSurfaceIntersection(sectLine, sfs(m))
    IF IsArray(pSect) THEN '有交叉点
     nSectPoints=UBound(pSect,1) '交叉点个数
     FOR j=0 TO nSectPoints
      iRoundUp=int((pSect(j,1)(1)-pStart(1))/lCube+0.5)
      p(i*(iY+1)*(iZ+1)+iRoundUp*(iZ+1)+k)=1
      pTemp(ubound(pTemp))=Rhino.AddPoint(pSect(j,1))
      redim preserve pTemp(ubound(pTemp)+1)
     NEXT
    END IF
   NEXT
   Rhino.DeleteObject sectLine
  NEXT
NEXT
redim preserve pTemp(ubound(pTemp)-1)
'根据记录的方块属性画方块
dim lCube2  '缩后的Cube边长
lCube2=rShrink*lCube
FOR i=0 TO iX
  FOR j=0 TO iY
   FOR k=0 TO iZ
    IF p(i*(iY+1)*(iZ+1)+j*(iZ+1)+k)=1  THEN
     pCube(0)=Array(pBox(0)(0)+i*lCube-lCube2/2,pBox(0)(1)+j*lCube-lCube2/2,pBox(0)(2)+k*lCube-lCube2/2)
     pCube(1)=Array(pBox(0)(0)+i*lCube+lCube2/2,pBox(0)(1)+j*lCube-lCube2/2,pBox(0)(2)+k*lCube-lCube2/2)
     pCube(2)=Array(pBox(0)(0)+i*lCube+lCube2/2,pBox(0)(1)+j*lCube+lCube2/2,pBox(0)(2)+k*lCube-lCube2/2)
     pCube(3)=Array(pBox(0)(0)+i*lCube-lCube2/2,pBox(0)(1)+j*lCube+lCube2/2,pBox(0)(2)+k*lCube-lCube2/2)
     pCube(4)=Array(pBox(0)(0)+i*lCube-lCube2/2,pBox(0)(1)+j*lCube-lCube2/2,pBox(0)(2)+k*lCube+lCube2/2)
     pCube(5)=Array(pBox(0)(0)+i*lCube+lCube2/2,pBox(0)(1)+j*lCube-lCube2/2,pBox(0)(2)+k*lCube+lCube2/2)
     pCube(6)=Array(pBox(0)(0)+i*lCube+lCube2/2,pBox(0)(1)+j*lCube+lCube2/2,pBox(0)(2)+k*lCube+lCube2/2)
     pCube(7)=Array(pBox(0)(0)+i*lCube-lCube2/2,pBox(0)(1)+j*lCube+lCube2/2,pBox(0)(2)+k*lCube+lCube2/2)
     Rhino.AddBox pCube
    END IF
   NEXT
  NEXT
NEXT
Rhino.DeleteObjects sfs '删除原始物体
Rhino.DeleteObjects pTemp '删除点
makeMosiac=sfs
END FUNCTION
作者: 夜神    时间: 2010-6-22 16:13
这是个简化版,是为了方便初学者阅读。
还有个效率更高的版本,代码长度有这个三倍长。
作者: yanhui314    时间: 2010-6-22 17:00
唉,我还不能上升到简化的程度,只求能做出来,呵呵
作者: njyqqq    时间: 2010-6-22 17:29
简化版和那个版本效果一样??差别在那??
作者: 夜神    时间: 2010-6-22 19:56
简化版和那个版本效果一样??差别在那??
njyqqq 发表于 2010-6-22 17:29

功能都一样,不打折扣,只是高效版本的速度要快的多。当然,作为代价,程序复杂了许多。
作者: 城市边缘工厂    时间: 2010-6-22 21:30
楼主犀利。进来看看。
作者: panhao1    时间: 2010-6-22 21:43
就单纯做一个类似的效果而言 这种算法显然过于冗长
使用Rhino.CurveSurfaceIntersection
这个就很耗时间

为什么不用判定点是否在brep内部那个命令呢?
那个命令就可以判定点是否在brep表面
完全被有必要拆分brep 再一个个面去求
作者: 夜神    时间: 2010-6-22 22:25
本帖最后由 夜神 于 2010-6-22 22:28 编辑
就单纯做一个类似的效果而言 这种算法显然过于冗长
使用Rhino.CurveSurfaceIntersection
这个就很耗时间

为什么不用判定点是否在brep内部那个命令呢?
那个命令就可以判定点是否在brep表面
完全被有必要拆分 ...
panhao1 发表于 2010-6-22 21:43

有这个命令吗?晕!
我在另一个程序里写过这个算法,就是为了避开使用Rhino.CurveSurfaceIntersection
作者: stratagem    时间: 2010-6-23 00:05
只能路过看看。。。。
作者: claudemit    时间: 2010-6-23 00:17
爬进来学习 lz大好人啊
作者: uuuf8    时间: 2010-6-24 02:30
本帖最后由 uuuf8 于 2010-6-24 02:36 编辑

确实没必要拆分

ps:虽然做的东西类似 但是彼此的逻辑还是有很大不同啊  这点很有意思
作者: 李薇薇    时间: 2010-6-24 17:57
好有趣,想学
作者: 董羽天    时间: 2010-6-25 12:40
嗯 学习了
作者: divedragon    时间: 2010-6-26 12:42
感谢楼主分享啊。。。。。。。。
作者: qiqiyunyan1986    时间: 2010-6-29 19:05
看着就好复杂
作者: sharkliang    时间: 2010-10-23 17:21
感谢楼主分享啊
作者: taliesin    时间: 2010-10-26 10:12
谢谢楼主分享  好东西大家学习
作者: liuchong625    时间: 2010-11-17 15:03
还是不错的说!
作者: Viking    时间: 2010-11-17 17:00
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷
甚好甚好甚好甚好甚好甚好甚好甚好甚好甚好甚好甚好甚好
这货是什么?! lz 我爱你!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
作者: Viking    时间: 2010-11-17 17:02
强烈要求斑竹再给他加n分!
喵了个咪 真是赞哉!  哦喵~
作者: ccocean    时间: 2010-11-17 21:56
谢谢楼主,崇拜啊。。。。什么我才能写出这样的代码?
作者: huangchang0528    时间: 2010-12-11 23:03
这个····太厉害了
作者: triko    时间: 2010-12-31 17:19
完全是看热闹
作者: ukcolour    时间: 2011-1-30 08:37
很不错的一段
作者: renping88    时间: 2011-3-20 02:05
MAD中钢大厦表皮的模拟
作者: bxsqrym    时间: 2011-4-2 11:44
好复杂哈倒了
作者: gaga    时间: 2011-4-2 22:45
貌似很复杂的样子
作者: gaga    时间: 2011-4-5 11:10
好漂亮啊,哪天我才会啊
作者: bxsqrym    时间: 2011-4-10 19:00
NNNNNNBBBBBB
作者: renping88    时间: 2011-4-13 04:32
ds                  w
作者: renping88    时间: 2011-4-13 04:32
w                        ew
作者: wawa    时间: 2011-4-28 12:34
very good!!!!!!!!
作者: kewangzhenxiang    时间: 2011-4-28 13:17
我没照度了,,,送电给我吧。。。
作者: mqcjackson    时间: 2011-10-14 14:03
我觉得做得挺好的……小白~~
作者: anboyh    时间: 2011-11-7 15:23
谢谢楼主分享。
作者: M-chibitora    时间: 2011-11-8 00:46
牛人啊!!!学习了哈哈
作者: hying    时间: 2011-12-10 14:02
顶。。。!
作者: howldyx    时间: 2011-12-14 21:09
感谢楼主分享啊。。。。。。。。
作者: howldyx    时间: 2011-12-14 22:07
收藏之哈哈哈
作者: s.k.    时间: 2011-12-14 23:09
我要学编程啊
作者: jasonbb88    时间: 2011-12-27 11:23
厉害~~~~~~~
作者: 蚊子    时间: 2011-12-27 12:54
什么都看不见啊
作者: bizquit    时间: 2012-1-1 17:12
楼主强大啊


作者: 鹰眼黑客    时间: 2012-2-10 23:48
楼主的分享精神值得赞扬。
作者: 多吃水果蔬菜    时间: 2012-2-28 11:44
做的真好!羡慕你!
作者: liuliu8244    时间: 2012-10-16 21:19
学习一下,lz继续加油
作者: 阿兹海默青年    时间: 2014-1-8 00:37
到现在都还没这么牛逼
作者: 左手◆23年    时间: 2014-2-13 09:43
感谢楼主分享,赞一个
作者: mgltju    时间: 2022-7-11 09:18
论坛高手云集,厉害厉害




欢迎光临 NCF参数化建筑论坛 (http://www.ncf-china.com/) Powered by Discuz! X3.2