对若干封闭圆曲线的放样问题

在开发双尖拱的实体创建脚本开发中,想通过沿着世界坐标系x轴方向的若干平行的卵圆曲线(yoz平面上)放样生成,但遇到了问题:在rs.AddLoftSrf()中的object_ids ({guid, guid, …]): ordered list of the curves to loft through不支持Rhino.Geometry.Line生成的curves,请问大神,该如何进行后续放样形成实体??

脚本如下:

# -*- coding:UTF-8 -*-
from array import array

str_parameters_file = 'Arch.json'
import Rhino
import scriptcontext
import rhinoscriptsyntax as rs
import sys
import json
import System
import math

sys.path.append('..\网格添加参数和表面网格化')
from addpara import addpara
from wanggehua import wanggehua


# 双尖拱形线平面方程
def CubicArchFunction(x, phi, d=9.936):  # d:inch 与m 的转化关系
    point = [0, 0, 0]
    x = x / d  # 转化为英寸
    phi = math.radians(phi)  # 角度转化为弧度
    if -2.5 <= x < 0:
        th = math.sin(math.radians(46.6)) ** 2
        gx = math.sqrt(1 - th * (x / 2.5) ** 2) - math.cos(math.radians(46.6))
        y = gx * math.cos(phi) / (1 - math.cos(math.radians(46.6)))
        z = gx * math.sin(phi) / (1 - math.cos(math.radians(46.6)))
        point[0] = x * d
        point[1] = y * d
        point[2] = z * d
    if 0 <= x <= 5:
        th = math.sin(math.radians(22.62)) ** 2
        gx = math.sqrt(1 - th * (x / 5) ** 2) - math.cos(math.radians(22.62))
        y = gx * math.cos(phi) / (1 - math.cos(math.radians(22.62)))
        z = gx * math.sin(phi) / (1 - math.cos(math.radians(22.62)))
        point[0] = x * d
        point[1] = y * d
        point[2] = z * d
    return point


# 点列表转为3d点结构
def listtopointed(center):
    center = Rhino.Geometry.Point3d(center[0], center[1], center[2])
    return center


# 离散x轴,生成x点离散列表,点个数表,和归一化点个数表,为放样函数提供列表
def creat_crt_point(a, b, step, d=9.936):
    a = a * d
    b = b * d
    lenth = int((a - b) / step) + 1
    num = list(range(lenth))

    reslut = [0, 1, 2]
    numguiyihua = num[:]
    numx = num[:]

    for x in num:
        numguiyihua[x] = num[x] / (len(num) - 1)
        numx[x] = num[x] * step + b

    reslut[0] = num
    reslut[1] = numx
    reslut[2] = numguiyihua

    return reslut


def creat_phi_points(a, b, step, ):  # 创造-pi~pi的点列表
    results = range(a, b, step)
#    RHI = results[:]
#    for i in range(len(results)):
#        RHI[i] = math.radians(results[i])
    return results


def AddArch(str_path):
    """
    已知Arch的宽、高、半径这三个特征参数,
    创建AddArch的mesh结构,生成AddArch.3dm
    =============== =================================================================
    **参数**
    *str_path*      (str)几何模型参数json文件路径 如:str_parameters_file='**.json'
    **返回值**
    *Rhino.Commands.Result.Success*   :返回建立成功的标志`
    =============== =================================================================
    **json文件需要参数**
    #在yoz平面上创建Arch圆曲线,通过放样,从而生成Arch
    'step' :    (float)#步进,
    *"SavePath" (str) 保存路径名 ,默认"Arch.3dm"*
    """
    # 提取参数
    dict_para = None
    try:
        with open(str_path, 'r') as load_file:
            dict_para = json.load(load_file)
    except:
        print("no nonfigure file Or file is not completed")
    # 参数初始化
    arch_a = 5
    arch_b = -2.5
    step = 0.1
    d = 9.936
    points_phi = creat_phi_points(-180, 180, 1)

    # 创建Arch.yoz面上圆形曲线的控制点
    points_x = creat_crt_point(arch_a, arch_b, step, d)[1]  # 得到x轴的实际坐标值点列表
    parameters = creat_crt_point(arch_a, arch_b, step, d)[2]  # 得到x轴的归一化坐标[0~1]
    points_yz = points3d_yz = points_phi[:]
    Curve = parameters[:]
    points = []
    # 生成若干Arch圆曲线列表
    for i in range(len(points_x)):
        for j in range(len(points_phi)):
            points_yz[j] = CubicArchFunction(points_x[i], points_phi[j], d=9.936)  # 方程得到对应x和phi(x,y,z)点值
            points3d_yz[j] = listtopointed(points_yz[j])
        points.append(points3d_yz)
        # 再转化为每个x(i)对应的曲线
        if i != 0 and i!= len(points_x)-1:
            for k in range(len(points_phi)):
                if k == len(points_phi)-1:
                    Curve[i] = Rhino.Geometry.Line(points[i][k], points[i][0])
                elif 0 <= k <= len(points_phi)-1:
                    Curve[i] = Rhino.Geometry.Line(points[i][k], points[i][k+1])
        elif i == 0 or i == len(points_x)-1: 
            Curve[i] = points[i][0]
            


    # 放样 loft
    lines = Curve[:]
    for i in range(1,len(Curve)-1):
        lines[i] = Curve[i].ToNurbsCurve()
    if lines:
        Arch = rs.AddLoftSrf(lines.items, start=None, end=None, loft_type=0, simplify_method=0, value=0, closed=False)
        print Arch

    
if __name__ == "__main__":
    scriptcontext.doc.Objects.Clear()
    AddArch(str_parameters_file)



如果一定要用 rs. AddLoftSrf() 的话,需要先把曲线添加到文档中以获得 GUID

将曲线添加到 DOC:

scriptcontext.doc.Objects.AddCurve()

谢谢!针对已经得到的Rhino.Geometry.line格式的一系列曲线,如果不使用rs.AddLoftSrf()的话,请问版主是还有其他方法、方式吗,我并没有在Rhino.Geometry找到相关放样的功能函数?
还有我使用的犀牛6的py Editor中 ,比如rs中有些函数功能和Rhino函数库的函数有些是相似的,这几个函数库之间到底有什么区分和内在联系呢。
image

你用 Rhino.Geometry.Line 生成的这些线,可以直接用下面这个方法放样:

Rhino.Geometry.Brep.CreateFromLoft (IEnumerable(Curve), Point3d, Point3d, LoftType, Boolean)

rhinoscriptsyntax 是面向脚本开发封装的高级函数库,把”底层“的一些功能直接封装成函数了,调用函数,获得相应的返回结果。

Rhino 其实就是 RhinoCommon,上面的 rhinoscriptsyntax 就是在 RhinoCommon 基础上写的。

从 RhinoCommon 中拿了一部分写脚本比较常用的的功能放到了 scriptcontext中。

Eto 是做窗体用的。

1 个赞

感谢,我使用版主所说的方法,发现: [Rhino.Geometry.Brep.CreateFromLoft]所需要的是IEnumerable[Curve], 而我使用的 Rhino.Geometry.PolyLine生成的曲线是Python中普通list形式,如下图所示:



我想要将list转化为需要的IEnumerable[Curve]:
分别寻找了下面的方法

Curve = Rhino.Collections.CurveList.GetEnumerator(Curve)

Curve = Rhino.Collections.CurveList.Transform(Curve, Enumerator)

发现使用Curvelist.GetEnumerator时,需要的是Rhinolist格式,
Message:expected RhinoList[Curve], got list
而我使用RhinoLIst.GetEnumerator时, 告诉我Message: ‘type’ object has no attribute ‘GetEnumerator’
想使用Transform类的,发现也转化不了

我对于这种类的转化一直很迷惑,每个函数库都有自己的命名类型例如Collections有自己的类:rhinolist, CurveList等,可是怎么转化成这种类型呢?还是说RhinoCommon里面有专门的库文件实现rhino通用类型格式的转换?
不知道该从何下手,希望大神能解答下,感激不尽。

不太清楚你的具体问题是啥,最好发一下自己的代码。
只要实现IEnumerable接口的数据类型都是可以的,python自带的列表也行。

分享一个简单的案例。

#coding=utf-8

import Rhino.RhinoDoc as rd
import Rhino.Geometry as rg

cvs = []
for i in xrange(20):
    cvs.append(rg.Circle(rg.Point3d(0,0,i),5).ToNurbsCurve())

breps = rg.Brep.CreateFromLoft(cvs,rg.Point3d.Unset,rg.Point3d.Unset,rg.LoftType.Normal,False)
[rd.ActiveDoc.Objects.AddBrep(b) for b in breps]
rd.ActiveDoc.Views.Redraw()

1 个赞

感谢,我通过对比案例,找到了问题所在 :joy:, 我原先生成的Curve,是polyLine[list]形式,而使用 [Rhino.Geometry.Brep.CreateFromLoft]需要的是curve[list]形式,不是polyline.因此我直接对原ToNurbsCurve(),之后再放样就可以走通了。
但是放样的时候发现,无法做到模型两端点封闭,虽然生成了前后两端点是polyline形式, 长度是0,实际上就是一个点,无法直接对含长度为0的polyline放样。因此我对curve[list]进行了切片[[1:len(Curve)]],舍去了前后端点,才能放样。

    # 对曲线列表Curve放样 loft
    loft_type = Rhino.Geometry.LoftType.Normal
    start = Rhino.Geometry.Point3d.Unset
    end = Rhino.Geometry.Point3d.Unset
    closed = False
    brep = Rhino.Geometry.Brep.CreateFromLoft(Curve[1:len(Curve)], start, end, loft_type, closed)

但这样导致了模型不封闭(我使用rs.AddLoftSrf也无法封闭),希望有个解决办法。

附:全文代码

# -*- coding:UTF-8 -*-
from array import array

str_parameters_file = 'Arch.json'
import Rhino
import scriptcontext
import rhinoscriptsyntax as rs
import sys
import json
import System
import math

sys.path.append('..\网格添加参数和表面网格化')
from addpara import addpara
from wanggehua import wanggehua


# 双尖拱形线平面方程
def CubicArchFunction(x, phi, d=9.936):  # d:inch 与m 的转化关系
    point = [0, 0, 0]
    x = x / d  # 转化为英寸
    phi = math.radians(phi)  # 角度转化为弧度
    if -2.5 <= x < 0:
        th = math.sin(math.radians(46.6)) ** 2
        gx = math.sqrt(1 - th * (x / 2.5) ** 2) - math.cos(math.radians(46.6))
        y = gx * math.cos(phi) / (1 - math.cos(math.radians(46.6)))
        z = gx * math.sin(phi) / (1 - math.cos(math.radians(46.6)))
        point[0] = x * d
        point[1] = y * d
        point[2] = z * d
    if 0 <= x <= 5:
        th = math.sin(math.radians(22.62)) ** 2
        gx = math.sqrt(1 - th * (x / 5) ** 2) - math.cos(math.radians(22.62))
        y = gx * math.cos(phi) / (1 - math.cos(math.radians(22.62)))
        z = gx * math.sin(phi) / (1 - math.cos(math.radians(22.62)))
        point[0] = x * d
        point[1] = y * d
        point[2] = z * d
    return point


# 点列表转为3d点结构
def listtopointed(center):
    center = Rhino.Geometry.Point3d(center[0], center[1], center[2])
    return center


# 离散x轴,生成x点离散列表,点个数表,和归一化点个数表,为loft函数提供列表
def creat_crt_point(a, b, step, d=9.936):
    a = a * d
    b = b * d
    lenth = int((a - b) / step) + 1
    num = list(range(lenth))

    reslut = [0, 1, 2]
    numguiyihua = num[:]
    numx = num[:]

    for x in num:
        numguiyihua[x] = num[x] / (len(num) - 1)
        numx[x] = num[x] * step + b

    reslut[0] = num   # 得到序列号
    reslut[1] = numx  # 得到x轴的实际坐标值点列表
    reslut[2] = numguiyihua   # 得到x轴的归一化坐标[0~1]

    return reslut


def creat_phi_points(a, b, step):  # 创造-pi~pi的点列表
    results = range(a, b, step)
#    RHI = results[:]
#    for i in range(len(results)):
#    RHI[i] = math.radians(results[i])
    return results


def AddArch(str_path):
    """
    已知Arch的2个尖端位置参数,及方程形式
    创建AddArch的mesh结构,生成AddArch.3dm
    =============== =================================================================
    **参数**
    *str_path*      (str)几何模型参数json文件路径 如:str_parameters_file='Ovate.json'
    **返回值**
    *Rhino.Commands.Result.Success*   :返回建立成功的标志`
    =============== =================================================================
    **json文件需要参数**
    #在yoz平面上创建Arch圆曲线,通过Rhino.pipe,从而生成Arch
    'step' :    (float)#步进,
    *"SavePath" (str) 保存路径名 ,默认"Arch.3dm"*
    """
    # 提取参数
    dict_para = None
    try:
        with open(str_path, 'r') as load_file:
            dict_para = json.load(load_file)
    except:
        print("no nonfigure file Or file is not completed")
    # 参数初始化
    arch_a = 5
    arch_b = -2.5
    step = 0.5
    d = 9.936
    points_phi = creat_phi_points(-180, 182, 2)  # 让每个x对应的曲线进行封闭,最后一点与第一点重合

    # 创建Arch.yoz面上圆形曲线的控制点
    points_x = creat_crt_point(arch_a, arch_b, step, d)[1]  # 得到x轴的实际坐标值点列表
    parameters = creat_crt_point(arch_a, arch_b, step, d)[2]  # 得到x轴的归一化坐标[0~1]
    points_yz = points3d_yz = points_phi[:]
    Curve = parameters[:]
    points = []

    # 生成若干Arch圆曲线列表Curve
    for i in range(len(points_x)):
        for j in range(len(points_phi)):
            points_yz[j] = CubicArchFunction(points_x[i], points_phi[j], d=9.936)  # 方程得到对应x和phi(x,y,z)点值
            points3d_yz[j] = listtopointed(points_yz[j])
        points.append(points3d_yz)  
        # 再转化为每个x(i)对应的曲线
#        if i != 0 :
        Curve[i] = Rhino.Geometry.Polyline(points[i])
        Curve[i] = Curve[i].ToNurbsCurve()

    # 对曲线列表Curve放样 loft
    loft_type = Rhino.Geometry.LoftType.Normal
    start = Rhino.Geometry.Point3d.Unset
    end = Rhino.Geometry.Point3d.Unset
    closed = False
    brep = Rhino.Geometry.Brep.CreateFromLoft(Curve[1:len(Curve)], start, end, loft_type, closed)

    # 调函生成网格
    class2 = wanggehua(brep[0], dict_para)
    class2.BrepToMesh11()

if __name__ == "__main__":
    scriptcontext.doc.Objects.Clear()
    # 使用配置文件的目的是方便FS进程调用
    AddArch(str_parameters_file)

附:预期的理想模型 :
image
生成的未封闭模型:

附:我尝试更改了Rhino.Geometry.Brep.CreateFromLoft()的start\end 参数,设置了端点:

start_point = [5*d,0,0]  # d = 9.936 英寸单位转化
end_point = [-2.5*d,0,0]
start = Rhino.Geometry.Point3d(start_point)
end = Rhino.Geometry.Point3d(end_point)

但无法得到封闭的理想模型: