zoukankan      html  css  js  c++  java
  • 非结构化网格内等值线绘制

    参考自 Implicit Surface Intersections--Mike Garrity

    示例

    绘制函数 (y-xcdot mathrm{tan}(z) = 0) 与圆柱 (x^2 + y^2 = 1) 的交线。

    一般绘制交线的方法有以下几种:

    1. 寻找解析解,
    2. 寻找交点,并且使用追踪方法构造曲线,
    3. 计算网格中交点,绘制曲面。

    本文使用的就是第三种方法,主要过程包括:

    1. 寻找等值线所在单元,
    2. 寻找单元插值节点,
    3. 每个单元内将插值点逐段连接。

    首先构造曲面 (y-xcdot mathrm{tan}(z) = 0) 并且找出所有满足 (x^2 + y^2 > 1) 的节点,将结果保存在变量mask内。

    [x3, y3,z3] = meshgrid(linspace(-1.25, 1.25, 150), ...
                           linspace(-1.25, 1.25, 150), ...
                           linspace(0, 2*pi, 150));
    f2 = y3-x3.*tan(z3);
    hel = isosurface(x3, y3, z3, f2, 0);
    
    %% Draw faces
    patch(hel,'FaceColor',[1 .5 0],'EdgeColor','none');
    view(3)
    camlight
    ax = gca;
    set(ax,'XLim',[-inf inf],'YLim',[-inf inf],'ZLim',[-inf inf],'DataAspectRatio',[1 1 1])
    box on
    xlabel('x(mm)')
    ylabel('y(mm)')
    zlabel('Lambda[rad]')
    
    %% Find vertex
    r = sqrt(hel.vertices(:,1).^2 + hel.vertices(:,2).^2);
    cylrad = 1;
    mask = r>cylrad;
    
    

    下面通过统计每个三角形内满足要求的节点个数,得到插值线所在单元序号cross及其三个节点编号crossing_tris

    outcount = sum(mask(hel.faces),2);
    cross = (outcount == 2) | (outcount == 1);
    crossing_tris = hel.faces(cross,:);
    

    下一步需要把这些单元转化为线段以表示等值线。首先把这些把每个单元内节点进行整理,将插值点所在的两个边交点排在三个节点的第一个位置,具体过程如下:

    1. 将只有一个节点满足 (x^2 + y^2 > 1) 的单元内,另外两个节点标记为1,此节点标记为0。这样所有单元内都只有唯一一个标记为0的节点,此节点就是插值点所在两个边的交点。
    out_vert = mask(crossing_tris);
    flip = sum(out_vert,2) == 1;
    out_vert(flip,:) = 1-out_vert(flip,:);
    
    1. 将三个节点交换顺序并将序号储存在变量overt中,交点在前,后面两个仍按顺序(逆时针或顺时针)排列。
    ntri = size(out_vert,1);
    overt = zeros(ntri,3);
    for i=1:ntri
        v1i = find(~out_vert(i,:));
        v2i = 1 + mod(v1i,3);
        v3i = 1 + mod(v1i+1,3);
        overt(i,:) = crossing_tris(i,[v1i v2i v3i]);
    end
    
    1. 计算每个单元内插值节点坐标,其中uv分别为插值点在两边上所占比率。
    u = (cylrad - r(overt(:,1))) ./ (r(overt(:,2)) - r(overt(:,1)));
    v = (cylrad - r(overt(:,1))) ./ (r(overt(:,3)) - r(overt(:,1)));
    
    uverts = repmat((1-u),[1 3]).*hel.vertices(overt(:,1),:) + repmat(u,[1 3]).*hel.vertices(overt(:,2),:);
    vverts = repmat((1-v),[1 3]).*hel.vertices(overt(:,1),:) + repmat(v,[1 3]).*hel.vertices(overt(:,3),:);
    

    最终将获得的插值节点坐标储存在变量xyz中,便可得到最终两曲面交线。

    x = nan(2,ntri);
    x(1,:) = uverts(:,1)';
    x(2,:) = vverts(:,1)';
    y = nan(3,ntri);
    y(1,:) = uverts(:,2)';
    y(2,:) = vverts(:,2)';
    z = nan(3,ntri);
    z(1,:) = uverts(:,3)';
    z(2,:) = vverts(:,3)';
    
    h = line(x(:),y(:),z(:));
    

  • 相关阅读:
    Linux删除tunnel的方法
    rpm 强制更新安装
    普通用户使用kubectl
    网络通信过程中mac地址和ip地址的必要性
    Quartz.net开源作业调度框架使用详解
    C# 开源组件--Word操作组件DocX
    用c#创建支持多语言的WinForm应用程序
    使用JavaScript获取日期加随机数生成单号
    C# winform treeView checkbox全选反选
    DevExpress控件的GridControl控件小结
  • 原文地址:https://www.cnblogs.com/li12242/p/5700151.html
Copyright © 2011-2022 走看看