-
2020-12-23 06:44:17
【单选题】( )的主要作用是承受活载压力和土压力等并将其传递给地基,并保证设计流量通过的必要孔径。(3.0分)
【判断题】在道路工程图中,图上尺寸数字之后不必注写单位,但在注解及技术要求中要注明尺寸单位。
【多选题】涵洞是由( )组成的排水构筑物。(4.0分)
【判断题】道路工程图中当虚线与虚线相交时,相交处不应留空隙。
【单选题】( )是用于宣泄水流的工程构筑物,从路面下方横穿道路,埋置于路基土层中。(3.0分)
【多选题】常见的涵洞洞身形式有( )。(4.0分)
【单选题】隧道洞门图的( )主要表达洞门排水系统的组成及洞内外水的汇集和排水路径。(3.0分)
【单选题】在尺寸标注中,尺寸线、尺寸界线应用( )绘制。
【单选题】( )包括端墙、翼墙、截水墙和缘石等组成部分。(3.0分)
【单选题】隧道衬砌图采用在每一类围岩中用一组垂直于隧道中心线的( )来表达隧道衬砌的结构形式。(3.0分)
【单选题】隧道洞门图的( )主要表达洞门墙的厚度、倾斜度,洞顶排水沟的断面形状、尺寸,洞顶帽石等的厚度,仰坡的坡度,洞内路面的结构、隧道净尺寸等。(3.0分)
【单选题】隧道洞门图的( )主要表达洞门墙的形式、尺寸、洞口衬砌的类型、主要尺寸、洞顶排水沟的位置、排水坡度等。(3.0分)
【多选题】制订《道路工程制图标准》GB50162—92,是为了( )。
【单选题】隧道( )是为了防止围岩变形或坍塌,沿隧道洞身周边用钢筋混凝土等材料修建的永久性支护结构。(3.0分)
【单选题】涵洞侧面图主要表达洞口( )布置情况。(3.0分)
【多选题】为保证图线的准确,( )。
【单选题】( )是涵洞的主要部分。(3.0分)
【单选题】在道路工程图中,线路的里程桩号以( )为单位。
【判断题】相互平行的尺寸线应从被标注的轮廓线由近向远排列,并且小尺寸在外,大尺寸在内。
【多选题】图样上标注的尺寸,应由( )组成。
【单选题】在道路工程图中,坡长和曲线要素均以( )为单位。
【单选题】( )是为了保证隧道使用的净空和结构的安全而设置的永久性衬砌结构。(3.0分)
【判断题】道路工程图中字母不得写成手写体。
【多选题】书写长仿宋体字的要领是( )。
【单选题】( )是为了保证施工的安全、加固岩体和阻止围岩的变形而设置的结构。(3.0分)
【判断题】道路工程图中当点划线与其他线相交时,交点应设在空隙处。
【单选题】隧道工程图中,用( )表示隧道的位置。(3.0分)
【判断题】尺寸数字宜标注在尺寸线上方中部。
【单选题】隧道洞门位于隧道的两端,是隧道的外露部分,俗称( )。(3.0分)
【多选题】图纸幅面,分为( )幅面和( )幅面两种。
【单选题】涵洞平面图一般( )涵洞上方的覆土,或假想土层是透明的。(3.0分)
【多选题】隧道主体构造物通常是指( )。(4.0分)
【多选题】尺寸数字及文字注写要求:( )。
【单选题】在道路工程中,一般采用A3或A3加长的图纸幅面,并且( )装订成册。
【判断题】道路工程图中当虚线与实线相交时,相交处应留空隙。
【单选题】( )是保证涵洞基础和两侧路基免受冲刷、使水流顺畅的构造。(3.0分)
【单选题】隧道工程中,以洞门口在垂直路线中心线上的正面投影作为隧道洞门图的( )。(3.0分)
【多选题】《道路工程制图标准》规定:中粗实线的一般用途是( )。
【多选题】本《道路工程制图标准》GB50162—92,适用于( )的设计、标准设计和竣工的制图。
【单选题】( )是指利用喷混凝土、锚杆或钢拱架支撑的一种或几种组合对围岩进行加固。(3.0分)
【多选题】隧道附属构造物是主体构造物以外的其他建筑物,如( )等。(4.0分)
【判断题】工程字应采用国家正式公布的简化字,除有特殊要求外,不得采用繁体字。
【多选题】常见的涵洞洞口形式有( )。(4.0分)
【单选题】用1∶200的比例作图时,若一线段的实际长度为20m,则在图样的对应线段上标注的尺寸数字应为( )。
【多选题】钢筋混凝土圆管涵工程图主要有( )等。(4.0分)
【单选题】涵洞按( )分类,可分为钢筋混凝土涵、混凝土涵、砖涵、石涵、木涵等。。(3.0分)
【单选题】在道路工程图中,钢筋和钢材的断面以( )为单位。
【单选题】( )是指为保证隧道工程开挖工作面稳定,在开挖之前采取的一种辅助措施。(3.0分)
【多选题】道路工程制图中汉字书写要求有( )。
【单选题】( )是待初次支护的变形基本稳定后,再进行现浇混凝土二次衬砌。(3.0分)
更多相关内容 -
工程建设制图中的主要可见轮廓线应选用
2020-12-30 18:30:291、工程建设制图中的主要可见轮廓线应选用.()AA、粗实线B、中实线C、粗虚线D、中虚线2、建筑平面图中的中心线、对称一般应用。()CA、细实线B、细虚线C、细单点长画线D、吸双点画线3、建筑施工图中定位轴线端部的圆用...1
、工程建设制图中的主要可见轮廓线应选用
.
(
)
A
A
、粗实线
B
、中实线
C
、粗虚线
D
、中虚线
2
、建筑平面图中的中心线、对称一般应用。
(
)
C
A
、细实线
B
、细虚线
C
、细单点长画线
D
、吸双点画线
3
、建筑施工图中定位轴线端部的圆用细实线绘制,直径为(
)
。
A
A
、
8-10mm B
、
11-12mm C
、
5-7mm
D
、
12-14mm
4
、建筑施工图中索引符号的圆的直径为(
)
。
B
A
、
8mm
B
、
10mm
C
、
12mm
D
、
14mm
5
、建筑施工图中祥图符号的原应以直径为(
)粗实线绘制。
C
A
、
10mm
B
、
12mm
C
、
14mm
D
、
16mm
6
、指北针圆的直径宜为(
)用细实线绘制。
D
A
、
14mm
B
、
18mm
C
、
20mm
D
、
24mm
7
、房屋结构常用构件代号“
WB
”表示。
B
A
、空心板
B
、屋面板
C
、密肋板
D
、折板
8
、房屋结构中基础梁的代号为
.D
A
、
TL
B
、
LL
C
、
WL
D
、
JL
9
、房屋结构中框架代号为
.A
A
、
KJ
B
、
GJ
C
、
CJ
D
、
ZJ
10
、房屋结构中空心板的代号为。
C
A
、
CB
B
、
WB
C
、
KB
D
、
ZB
11
、结构施工土中的圈梁表示
(
) .B
A
、
GL
B
、
QL
C
、
JL
D
、
KL
12
、结构施工图中的楼梯梁的代号为。
(
) D
A
、
GL
B
、
DL
C
、
JL
D
、
TL
13
、给排水的压力管道应标注
(
)
标高
.A
A
、管中心
B
、管底
C
、官定
D
、以上都可以
14
、给水排水制图中的沟渠和重立流管道宜标注
(
)
标高。
B
A
、管中心
B
、管内底
C
、管顶
D
、以上都可以
15
、水煤气输送钢管、铸铁管等管材,管径宜以(
)表示
.C
A
、外径
DX
壁厚
B
、内径
d
C
、公称直径
DN
D
、以上都是
16
、钢筋混凝土管、陶土管、耐酸陶瓷管、缸瓦管等管材,管径宜以(
)表示
.A
A
、外径
DX
壁厚
B
、内径
d
C
、公称直径
DN
D
、以上都是
17
、无缝钢管、焊接钢管、铜管、不锈钢管等管材,管径宜以(
)表示
.A
A
、外径
DX
壁厚
B
、内径
d
C
、公称直径
DN
D
、以上都是
18
、给水排水工程图常用代号图例中“——
J
——”表示。
C
A
、废水管
B
、污水管
C
、生活给水管
D
、热水给水管
19
、给水排水工程图“——
RJ
——”表示
(
).A
A
、热水给水管
B
、废水管
C
、污水管
D
、生活水管
20
、给水排水工程图“——
W
——”表示
(
).C
A
、热水给水管
B
、废水管
C
、污水管
D
、生活水管
21
、给水排水工程图“——
F
——”表示
(
).B
A
、热水给水管
B
、废水管
C
、污水管
D
、生活水管
22
、平屋面或坡度不大于
1/10
的屋面,易受雷击的部位是(
)
.C
A
、屋角、屋脊、檐角
B
、屋角、屋脊、檐角、屋檐
C
、檐角、女儿墙、屋檐
D
、屋脊、屋角、女儿墙
23
、坡度大与
1/10
且小于
1/2
的屋面、易雷击的部位是(
)
.B
A
、屋角、屋脊、檐角
B
、屋角、屋脊、檐角、屋檐
C
、檐角、女儿墙、屋檐
D
、屋脊、屋角、女儿墙
24
、坡度大于等于
1/2
的屋面,易受雷击的部位是(
)
A
A
、屋角、屋脊、檐角
B
、屋角、屋脊、檐角、屋檐
C
、檐角、女儿墙、屋檐
D
、屋脊、屋角、女儿墙
25
、避雷针宜采用镀锌圆钢制作,针长
1m
以时,直径不大于(
)
。
B
A
、
10mm
B
、
12mm
C
、
14mm
D
、
16mm
26
、避雷针宜采用镀锌圆钢制作,针长
1m-2m
以时,直径不大于(
)
。
B
A
、
10mm
B
、
12mm
C
、
14mm
D
、
16mm
27
、避雷常(网)是建筑物防雷较普遍采用的方法,避雷常一般应采用直径不小于
8mm
的圆钢或截面不小于(
)厚度不小于
4mm
的扁钢制作。
B
A
、
40
平方毫米
B
、
48
平方毫米
C
、
56
平方毫米
D
、
64
平方毫米
28
、避雷常应高出屋面
(
),
支持卡间距为
1m--1.5m.
B
A
、
60mm-100mm
B
、
100mm-150mm
C
、
150mm-200mm
D
、大于或等于
200mm
29
、避雷装置的引下线采用扁钢制作时
,
扁钢截面不应小于
(
) .
B
A
、
40
平方毫米
B
、
48
平方毫米
C
、
56
平方毫米
D
、
64
平方毫米
30
、建筑物防雷装置的接地体采用圆钢时
,
直径不小于
(
). C
A
、
6mm
B
、
8mm
C
、
10mm
D
、
12mm
31
、防雷装置的接地体为垂直接地体时
,
其长度一般为
(
).C
A
、
1.5m
B
、
2.0m
C
、
2.5m
D
、
3.5m
32
、防雷装置的水平及垂直接地体应高建筑物外墙
,
出入口、人行通不小于(
)
,以
-
高速凸轮轮廓线设计与仿真
2020-07-03 06:03:36为了反映高速凸轮从动部件输出端的运动规律、提高机构运行的稳定性,建立了凸轮机构的动力学模型以及从动部件的运动方程,进而...通过测试,分析了工作频率对凸轮运行时轮廓线的影响,可为优化高速凸轮机构设计提供参考。 -
基于多分辨率动态轮廓线的面积测量与跟踪方法
2021-03-05 10:16:52该方法使用光电式图像瞄准系统采集被测物体的目标图像并构造该图像的高斯金字塔,并采用了多分辨率动态轮廓线且使其由初始位置向目标轮廓边缘收敛;根据基于B样条封闭曲线面积与形心公式,准确计算出图像的目标面积与... -
基于对齐度和互信息的红外与可见光图像配准
2020-10-20 15:29:53摘要:针对红外与可见光图像的特点,在此提出了一种结合边缘对齐度与互信息的图像配准方法。首先通过小波变换边缘检测得到红外与可见光图像的边缘图像,并将对齐度和归一化互信息自适应加权平均得到新的相似性测度... -
浅析基于二维轮廓线重构表面算法
2014-02-13 17:04:10轮廓线重构算法 由一组二维轮廓线重建出物体的三维表面是三维数据场可视化中的一种表面绘制方法。在医学图像可视化以及其他可视化领域中有着广泛的应用。三维表面重建实际上是对物体表面进行三角形划分,从轮廓...轮廓线重构算法
由一组二维轮廓线重建出物体的三维表面是三维数据场可视化中的一种表面绘制方法。在医学图像可视化以及其他可视化领域中有着广泛的应用。三维表面重建实际上是对物体表面进行三角形划分,从轮廓线的角度出发就是将轮廓线上的顶点按照一定规则进行三角形拼接,从而构成可视的三维物体表面,再利用三维显示技术将其显示出来。本文讨论了一种实现轮廓线重构的简易方法,其关键的步骤体现在相邻轮廓线的编织方法以及顶底层轮廓线的三角化上。并且用c++代码来实现之。
轮廓线数据结构表示
首先为了表示输入的轮廓线,需要使用一种数据结构来表示每一层的轮廓线。通常重建的输入会由N个轮廓线组成,每个轮廓线位于不同的高度位置,我们可以把轮廓线认为是以条在X-Y平面上闭合的曲线,而每条轮廓线有着不同的Z值。而二维曲线通常都是用一系列二维点组成的折线近似表示的,这样轮廓线的数据结构可以表示为如下的形式:
struct FloatDouble { float X; float Y; FloatDouble(float x,float y) { X=x;Y=y; } FloatDouble() { X=0; Y=0; } };
struct Box3Float { public: float Min3[3]; float Max3[3]; Box3Float() { Min3[0]=99999; Min3[1]=99999; Min3[2]=99999; Max3[0]=-99999; Max3[1]=-99999; Max3[2]=-99999; } Box3Float(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { Min3[0] = minX; Min3[1] = minY; Min3[2] = minZ; Max3[0] = maxX; Max3[1] = maxY; Max3[2] = maxZ; } void UpdateRange(float x, float y, float z) { if (x < Min3[0]) Min3[0] = x; if (y < Min3[1]) Min3[1] = y; if (z < Min3[2]) Min3[2] = z; if (x > Max3[0]) Max3[0] = x; if (y > Max3[1]) Max3[1] = y; if (z > Max3[2]) Max3[2] = z; } float GetXLength() { return Max3[0]-Min3[0]; } float GetYLength() { return Max3[1]-Min3[1]; } float GetZLength() { return Max3[2]-Min3[2]; } };
class ContourLine { private: std::vector<FloatDouble> points; float z; public: ContourLine():z(0) { } void AddPoint2d(float x,float y) { FloatDouble t(x,y); points.push_back(t); } inline std::vector<FloatDouble>& GetPointList() { return points; } inline int GetLinePointCount() const { return points.size(); } inline void SetZ(float z) { this->z=z; } inline float GetZ() const { return z; } Box3Float GetBox() { Box3Float box; for (size_t i = 0; i < points.size(); i++) { box.UpdateRange(points[i].X, points[i].Y, 0); } return box; } };
这样std::vector<ContourLine>即可以作为轮廓线重构算法的输入类型,重构算法最终输出代表结果表面的Mesh。Mesh结构在之前的文章中多次出现,就不详细描述了。在介绍轮廓线重构算法中,需要首先解决下面的几个子算法问题,所以为了正确理解算法逻辑,首先需要介绍一下这些子算法。
子算法一:判断折线圈是否为逆时针
上面说了一般用来表示平面上一条轮廓线的方法是使用一系列点。按这些点练成折线,最后再将最后一个点与第一个点连起来,便是一条闭合的折线,假设折线是不自交的,则这个线圈一定能够判断它是逆时针还是顺时针。在轮廓线重构算法中,需要保证每一层的轮廓线为是由逆时针的折现圈表示的。所以,这里介绍一种判断折线圈是否为逆时针的方法。
首先在计算几何中,利用解析几何的原理我们知道向量的叉积可以用来判断向量拐弯的方向,例如下图中向量A×B若为正数,则意味着B相对A是向逆时针方向旋转的;为0则A,B共线;否则B是相对A顺时针旋转的。而1/2*abs(A×B)则为AB向量构成三角形的面积。
AB×BC为正 AB×BC为负 逆时针的轮廓线 顺时针的轮廓线 因此一种直观的判断由点A1、A2、......An构成的折线圈是否为逆时针的方法是计算三角形(A1,A2,A3),(A2,A3,A4),(A3,A4,A5).....(An,A1,A2)的面积之和是否为正值。这里不做原理性证明为什么可以这样,详细的原理可以从如下网址查看:
原网址:http://www.mathopenref.com/coordpolygonarea2.html ,打不开的话可见CSDN的备份:http://blog.csdn.net/swfa1/article/details/18146581 。
这里只附上相应的代码:
static float Area(std::vector<FloatDouble>& contour) { int n = contour.size(); float A = 0.0f; for (int p = n - 1, q = 0; q < n; p = q++) { A += contour[p].X * contour[q].Y - contour[q].X * contour[p].Y; } return A * 0.5f; }
上述函数返回true,则折线圈为逆时针。
子算法二: 两层轮廓线编织算法
所谓轮廓线编织,就是把相邻两层的轮廓线上的点采用合适的方式连接起来,形成三角网,但这种连接的方式显然是不唯一的。下图显示了两种不同的编织方式形成的三角网,显然,两者存在形态上的差别。
一种好的编织方式 一种看上去不太好的编织方式 从直观感觉上看,显然前一个三角网中三角形更为规则(较少的钝角三角形)。所以究竟如何生成好的三角网,需要采用合适的策略。这样的策略在相关领域有很多研究成果,提出了不少的方法,这里介绍一个容易理解的法则,叫做最短对角线原则。下图为了说明这个原则,将轮廓线剪开并展平成直线,轮廓线的点则分布在这条直线上,相隔不等的距离。
将轮廓线编织模拟成在两条直线上连接相应的点的连接,采用最短对角线原则连接方式为:若当前Ai已经与Bj相连接,检查由四个点(Ai,Ai+1,Bj+1,Bj)组成的四边形,检测对角线AiBj+1与Ai+1Bj的长度,选择较短的一条作为新三角形的边。
最短对角线连接方式 非最短对角线的连接方式 当创建第一条连接线的时候,对于点A0,需要遍历一次B点的数组,寻找到离A0最近的B点,假设为Bk,则需要将B数组调整为以Bk为首元素,与A方向相同(顺逆时针)的新数组。所以这就解释了为何需要先清楚子算法一的内容。这样,在编织活动开始的时候,A0与B0是最近的点对,A0B0是连接的第一条线,之后的循环过程按最短对角线原则进行。在实现过程中需要使用两个指示变量分别标记A数组和B数组中行进到的位置,有点算法基础的同学会发现这与归并排序中的Merge过程有点相似。循环到A、B数组中有一个访问完为止,这时另一个数组余下的点可以与访问完的数组的最后一个点连接成若干三角形。最后还需要注意要将最后的An-1Bm-1与A0B0组成的四边形用最短对角线法再三角化一次。
在应用这个原则时,当两层轮廓线投影在平面上的位置偏差较大时可能出现的问题,例如下图的情况,在投影偏差较大的时候,可能会导致所有三角形的顶点都是同一点,如下图所示,这样显然没有达到编织轮廓线的目的,解决的方案是将两层轮廓线的几何中心移在一起,这样就会避免这种现象。
综上,编织由点数组A、B表示的轮廓线的过程用文字表述如下:
- 检查A、B数组的方向,将A,B数组调整为逆时针。
- 获取A、B的Box范围并保存,然后将A,B平移到使几何中心到原点(0,0)。
- 为A0寻找B中的最近点,然后以此最近点为B0,将B数组按顺序重新编号。
- 设置A、B数组的位置指示变量i,j,初始化为0
- 当i与j均未达到A和B的长度
- 检查(Ai,Ai+1,Bj+1,Bj)组成的四边形,若AiBj+1短于Ai+1Bj,则创建三角片(Ai,Bj,Bj+1)否则创建三角片(Ai,Bj,Ai+1)
- 若i达到A的长度,则将B中余下的点连A的最后一点构成三角片
- 若j达到B的长度,则将A中余下的点连B的最后一点构成三角片
- 为四边形(An-1,Bm-1,A0,B0)构建按最短对角线原则创建三角片。
下列图片序列简单的反映了这一过程:
初始四边形 第二次迭代 第三次迭代 迭代直到有一个点数组访问完毕 迭代完成 相应的实现代码,写成一个类形式如下,其中QuadUnit类用来表示一个用来使用最短对角线原则的四边形:
class ContourStitcher { private: struct QuadUnit { public: int UpIndex0; int UpIndex1; int DownIndex0; int DownIndex1; double DiaU0D1Len; double DiaU1D0Len; std::vector<FloatDouble>* lineUp; std::vector<FloatDouble>* lineDown; void Init(int upIndex, int downIndex) { UpIndex0 = upIndex; DownIndex0 = downIndex; UpIndex1 = (upIndex + 1); //%lineUp.Count; DownIndex1 = (downIndex + 1); //%lineDown.Count; DiaU0D1Len = GetDLen(UpIndex0, DownIndex1); DiaU1D0Len = GetDLen(UpIndex1, DownIndex0); } void InitLast() { UpIndex0 = lineUp->size() - 1; DownIndex0 = lineDown->size() - 1; UpIndex1 = 0; //%lineUp.Count; DownIndex1 = 0; //%lineDown.Count; DiaU0D1Len = GetDLen(UpIndex0, DownIndex1); DiaU1D0Len = GetDLen(UpIndex1, DownIndex0); } double GetDLen(int index1, int index2) { float x0 = (*lineUp)[index1].X; float y0 = (*lineUp)[index1].Y; float x1 = (*lineDown)[index2].X; float y1 = (*lineDown)[index2].Y; return sqrt((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1)); } }; void Transform(std::vector<FloatDouble>& list, float dx, float dy) { for (size_t i = 0; i < list.size(); i++) { list[i].X += dx; list[i].Y += dy; } } Point3d GetCenter(Box3Float& box3) { return Point3d((box3.Max3[0] + box3.Min3[0]) / 2.0f, (box3.Max3[1] + box3.Min3[1]) / 2.0f, (box3.Max3[2] + box3.Min3[2]) / 2.0f); } public: ContourLine* lineUp; ContourLine* lineDown; std::vector<FloatDouble> lineUpProcessed; std::vector<FloatDouble> lineDownProcessed; Box3Float boxUp; Box3Float boxDown; ContourStitcher(ContourLine* line1, ContourLine* line2) { if (line1->GetZ() > line2->GetZ()) { this->lineUp = line1; this->lineDown = line2; } else { this->lineUp = line2; this->lineDown = line1; } lineUpProcessed.reserve(lineUp->GetLinePointCount()); lineDownProcessed.reserve(lineDown->GetLinePointCount()); CopyArray(lineUp->GetPointList(), lineUpProcessed); CopyArray(lineDown->GetPointList(), lineDownProcessed); boxUp = lineUp->GetBox(); boxDown = lineDown->GetBox(); Point3d cU = GetCenter(boxUp); Point3d cD = GetCenter(boxDown); Transform(lineDownProcessed, -cD.X, -cD.Y); Transform(lineUpProcessed, -cU.X, -cU.Y); int indexDown = GetNearIndex(); AdjustDownArray(indexDown); } ~ContourStitcher() { lineUp=NULL; lineDown=NULL; } private: void CopyArray(std::vector<FloatDouble> &olist, std::vector<FloatDouble> &tarlist) { for (size_t i = 0; i < olist.size(); i++) { tarlist.push_back(FloatDouble(olist[i].X, olist[i].Y)); } } int ContourStitcher::GetNearIndex() { int index = -1; double distense = DBL_MAX; FloatDouble& p = lineUpProcessed[0]; float x0 = p.X; float y0 = p.Y; for (size_t i = 0; i < lineDownProcessed.size(); i++) { float x1 = lineDownProcessed[i].X; float y1 = lineDownProcessed[i].Y; double dis = sqrt((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1)); if (dis < distense) { distense = dis; index = i; } } return index; } void AdjustDownArray(int indexDown) { std::vector<FloatDouble> list; list.reserve(lineDownProcessed.size()); for (size_t i = 0; i < lineDownProcessed.size(); i++) { list.push_back(lineDownProcessed[(indexDown + i) % lineDownProcessed.size()]); } lineDownProcessed.swap(list); } public: Mesh* DoStitching() { Mesh *m = new Mesh(); int* upMap=new int[lineUpProcessed.size()]; float dx1 = GetCenter(boxUp).X; float dy1 = GetCenter(boxUp).Y; float dx2 = GetCenter(boxDown).X; float dy2 =GetCenter( boxDown).Y; int* downMap=new int[lineDownProcessed.size()]; for (size_t i = 0; i < lineDownProcessed.size(); i++) { Point3d p(lineDownProcessed[i].X + dx2, lineDownProcessed[i].Y + dy2, lineDown->GetZ()); downMap[i] = m->AddVertex(p); } for (size_t i = 0; i < lineUpProcessed.size(); i++) { Point3d p(lineUpProcessed[i].X + dx1, lineUpProcessed[i].Y + dy1, lineUp->GetZ()); upMap[i] = m->AddVertex(p); } size_t upIndex = 0; size_t downIndex = 0; QuadUnit quad; quad.lineDown = &lineDownProcessed; quad.lineUp = &lineUpProcessed; while (true) { if (upIndex == lineUpProcessed.size() - 1 || downIndex == lineDownProcessed.size() - 1) { break; } quad.Init(upIndex, downIndex); if (quad.DiaU0D1Len < quad.DiaU1D0Len) { Triangle t(upMap[quad.UpIndex0], downMap[quad.DownIndex0], downMap[quad.DownIndex1]); m->AddFace(t); downIndex++; } else { Triangle t(upMap[quad.UpIndex0], downMap[quad.DownIndex0], upMap[quad.UpIndex1]); m->AddFace(t); upIndex++; } } if (upIndex == lineUpProcessed.size() - 1 || downIndex == lineDownProcessed.size() - 1) { if (downIndex == lineDownProcessed.size() - 1) { int last = lineDownProcessed.size() - 1; while (upIndex != lineUpProcessed.size() - 1) { Triangle t(downMap[last], upMap[upIndex + 1], upMap[upIndex]); m->AddFace(t); upIndex++; } } else { int last = lineUpProcessed.size() - 1; while (downIndex != lineDownProcessed.size() - 1) { Triangle t(upMap[last], downMap[downIndex], downMap[downIndex + 1]); m->AddFace(t); downIndex++; } } } quad.InitLast(); if (quad.DiaU0D1Len < quad.DiaU1D0Len) { Triangle t(upMap[quad.UpIndex0], downMap[quad.DownIndex0], downMap[quad.DownIndex1]); Triangle t2(upMap[quad.UpIndex0], downMap[quad.DownIndex1], upMap[quad.UpIndex1]); m->AddFace(t); m->AddFace(t2); } else { Triangle t(upMap[quad.UpIndex0], downMap[quad.DownIndex0], upMap[quad.UpIndex1]); Triangle t2(upMap[quad.UpIndex1], downMap[quad.DownIndex0], downMap[quad.DownIndex1]); m->AddFace(t); m->AddFace(t2); } delete[] upMap; delete[] downMap; return m; } };
下图是按此原则编织的两层轮廓线的例图:
子算法三:Mesh合并方法简述
在实现了相邻两层轮廓线的三角网格生成操作后,对于已经按Z高度排序的轮廓线C1到Cn,可以使用子算法二对<C1,C2>...<Cn-1,Cn>生成对应的三角网格,其编号为M1,M2,...Mn-1。
考虑到每一个Mesh都是由两层顶点组成,所以这些网格合并成一个大的M网格M需要考虑顶点去重的问题,一个简单的方式是为每层顶点建立一个映射数组f,数组存储着每层顶点在M中的索引位置,这样每当需要添加Mi的顶点和三角片进入M的时候,Mi中低一层的顶点由于肯定在Mi-1加入M时已经加入M,则只添加Mi中高一层的顶点即可,在顶点加入时更新其三角片的顶点新索引。这样在所有三角片加入M后,Mesh便生成完成。由于这个子算法属于算法细节,这里就不单独描述伪代码。包含这部分的代码会在总的实现中贴出来。
合并前独立的两个Mesh 合并后,一些顶点共用 子算法四:任意多边形三角化方法
在轮廓线层之间的三角网格建立起来后,往往还需要把顶面和底面的轮廓线三角化,使得整个三角网形成封闭的拓扑结构,这部分算法摘抄自John W. Ratcliff在http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml上贴出的代码,其输入为点集表示的折线,输出为三角片集合,三角片顶点索引指向点集,这份代码中的Area函数,即是子算法一中判断折线圈方向的函数,该函数计算一个有符号的面积,返回正则说明折线圈为逆时针方向。
下面简要说明一下该算法的和主要思想:先将点顺序调整为逆时针,然后沿着折线圈,迭代着创建连续三个顶点(Ai,Ai+1,Ai+2)组成的三角片,若该三角片的旋转方向也为顺时针,则将该三角片删去,直到最后剩下一个三角片为止。该算法的代码整合为一个静态类如下:
class PolyTriangulator { public: static bool Process(std::vector<FloatDouble>& contour, std::vector<Triangle>& result) { int n = contour.size(); if (n < 3) return false; int* V = new int[n]; if (0.0f < Area(contour)) for (int v = 0; v < n; v++) V[v] = v; else for (int v = 0; v < n; v++) V[v] = (n - 1) - v; int nv = n; int count = 2 * nv; /* error detection */ for (int m = 0, v = nv - 1; nv > 2; ) { if (0 >= (count--)) { return false; } int u = v; if (nv <= u) u = 0; /* previous */ v = u + 1; if (nv <= v) v = 0; /* new v */ int w = v + 1; if (nv <= w) w = 0; /* next */ if (Snip(contour, u, v, w, nv, V)) { int a, b, c, s, t; a = V[u]; b = V[v]; c = V[w]; Triangle tri(a, b, c); result.push_back(tri); m++; for (s = v, t = v + 1; t < nv; s++, t++) V[s] = V[t]; nv--; count = 2 * nv; } } delete []V; return true; } static float Area(std::vector<FloatDouble>& contour) { int n = contour.size(); float A = 0.0f; for (int p = n - 1, q = 0; q < n; p = q++) { A += contour[p].X * contour[q].Y - contour[q].X * contour[p].Y; } return A * 0.5f; } private: static bool InsideTriangle(float Ax, float Ay, float Bx, float By, float Cx, float Cy, float Px, float Py) { float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy; float cCROSSap, bCROSScp, aCROSSbp; ax = Cx - Bx; ay = Cy - By; bx = Ax - Cx; by = Ay - Cy; cx = Bx - Ax; cy = By - Ay; apx = Px - Ax; apy = Py - Ay; bpx = Px - Bx; bpy = Py - By; cpx = Px - Cx; cpy = Py - Cy; aCROSSbp = ax * bpy - ay * bpx; cCROSSap = cx * apy - cy * apx; bCROSScp = bx * cpy - by * cpx; return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); } static bool Snip(std::vector<FloatDouble>& contour, int u, int v, int w, int n, int* V) { int p; float Ax, Ay, Bx, By, Cx, Cy, Px, Py; Ax = contour[V[u]].X; Ay = contour[V[u]].Y; Bx = contour[V[v]].X; By = contour[V[v]].Y; Cx = contour[V[w]].X; Cy = contour[V[w]].Y; if (0.00001f > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) return false; for (p = 0; p < n; p++) { if ((p == u) || (p == v) || (p == w)) continue; Px = contour[V[p]].X; Py = contour[V[p]].Y; if (InsideTriangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py)) return false; } return true; } };
综合算法
在了解了这些子算法的过程之后,可以总结出轮廓线算法的总体步骤如下:
- 为输入轮廓线排序,确保按Z升序排列
- 调整输入轮廓线,确保为均逆时针
- 平移所有轮廓线,使其几何中心重合
- 对所有连续两相邻轮廓线,执行编织算法(子算法二)
- 合并子算法二生成的Mesh
- 使用子算法四三角化顶面和地面,并将三角片与上一步的Mesh合并
- 将轮廓线平移回原来位置。
这样一个集成子算法完成轮廓线重建的类代码如下:
class ContourLineSurfaceGenerator { private: static bool CompareContourline(ContourLine* r1,ContourLine* r2) { return r1->GetZ() < r2->GetZ(); } void Transform(std::vector<FloatDouble>& list, float dx, float dy) { for (size_t i = 0; i < list.size(); i++) { list[i].X += dx; list[i].Y += dy; } } Point3d GetCenter(Box3Float& box3) { return Point3d((box3.Max3[0] + box3.Min3[0]) / 2.0f, (box3.Max3[1] + box3.Min3[1]) / 2.0f, (box3.Max3[2] + box3.Min3[2]) / 2.0f); } private: std::vector<ContourLine*> lines; public: ContourLineSurfaceGenerator(std::vector<ContourLine*> lines) { this->lines = lines; }private: void ReverseNormal(std::vector<Triangle> &list) { for (size_t i = 0; i < list.size(); i++) { int temp = list[i].P0Index; list[i].P0Index = list[i].P2Index; list[i].P2Index = temp; } } bool IsNormalZ2(std::vector<FloatDouble> &vertices, std::vector<Triangle> &faces) { if (faces.empty()) { return true; } else { Triangle &t = faces[0]; Point3d p0(vertices[t.P0Index].X, vertices[t.P0Index].Y, 0.0f); Point3d p1(vertices[t.P1Index].X, vertices[t.P1Index].Y, 0.0f); Point3d p2(vertices[t.P2Index].X, vertices[t.P2Index].Y, 0.0f); Vector v = Triangle::CaculateNormal(p0,p1,p2); if (v.Z > 0) { return true; } else { return false; } } } void FillDownHole(Mesh *m, std::vector<int>* maps, std::vector<FloatDouble> &downContourPrcessed, Box3Float& boxD) { Transform(downContourPrcessed, GetCenter(boxD).X, GetCenter(boxD).Y); std::vector<Triangle> down; PolyTriangulator::Process(downContourPrcessed, down); if (IsNormalZ2(downContourPrcessed, down)) { ReverseNormal(down); } for (size_t i = 0; i < down.size(); i++) { Triangle t = down[i]; t.P0Index = maps[0][t.P0Index]; t.P1Index = maps[0][t.P1Index]; t.P2Index = maps[0][t.P2Index]; m->AddFace(t); } } void FillUpHole(Mesh *m, std::vector<int>* maps, std::vector<FloatDouble> &upContourPrcessed, Box3Float& boxU) { Transform(upContourPrcessed,GetCenter(boxU).X,GetCenter(boxU).Y); std::vector<Triangle> up; PolyTriangulator::Process(upContourPrcessed, up); if (!IsNormalZ2(upContourPrcessed, up)) { ReverseNormal(up); } for (size_t i = 0; i < up.size(); i++) { Triangle t = up[i]; t.P0Index = maps[lines.size() - 1][t.P0Index]; t.P1Index = maps[lines.size() - 1][t.P1Index]; t.P2Index = maps[lines.size() - 1][t.P2Index]; m->AddFace(t); } } void ReverseArray(std::vector<FloatDouble> &list) { size_t count = list.size(); for (size_t i = 0; i < count / 2; ++i) { FloatDouble temp = list[count - i - 1]; list[count - i - 1] = list[i]; list[i] = temp; } } public: Mesh *GenerateSurface() { if (lines.size() <= 1) { return NULL; } std::sort(lines.begin(), lines.end(), CompareContourline); for (size_t i = 0; i < lines.size(); i++) { std::vector<FloatDouble>& linepoints = lines[i]->GetPointList(); if (0.0f > PolyTriangulator::Area(linepoints)) { ReverseArray(linepoints); } } Mesh *m = new Mesh(); std::vector<int>* maps=new std::vector<int>[lines.size()]; for (size_t i = 0; i < lines.size(); i++) { maps[i].resize(lines[i]->GetLinePointCount(),-1); } std::vector<FloatDouble> upContourPrcessed; Box3Float boxU = lines[lines.size() - 1]->GetBox(); std::vector<FloatDouble> downContourPrcessed; Box3Float boxD = lines[0]->GetBox(); for (size_t i = 0; i < lines.size() - 1; i++) { ContourStitcher cs(lines[i],lines[i + 1]); if (i == 0) { downContourPrcessed.insert(downContourPrcessed.end(),cs.lineDownProcessed.begin(),cs.lineDownProcessed.end()); } if (i == lines.size() - 2) { upContourPrcessed.insert(upContourPrcessed.end(),cs.lineUpProcessed.begin(),cs.lineUpProcessed.end()); } Mesh *submesh = cs.DoStitching(); size_t Z0Count = lines[i]->GetLinePointCount(); size_t Z2Count = lines[i + 1]->GetLinePointCount(); if (submesh->Vertices.size() != Z0Count + Z2Count) throw std::exception(); for (size_t j = 0; j < Z0Count; j++) { if (maps[i][j] == -1) { maps[i][j] = m->AddVertex(submesh->Vertices[j]); } } for (size_t j = 0; j < Z2Count; j++) { maps[i + 1][j] = m->AddVertex(submesh->Vertices[j + Z0Count]); } for (size_t j = 0; j < submesh->Faces.size(); j++) { Triangle t = submesh->Faces[j]; if (t.P0Index < (int)Z0Count) { t.P0Index = maps[i][t.P0Index]; } else { t.P0Index = maps[i + 1][t.P0Index - Z0Count]; } if (t.P1Index < (int)Z0Count) { t.P1Index = maps[i][t.P1Index]; } else { t.P1Index = maps[i + 1][t.P1Index - Z0Count]; } if (t.P2Index <(int)Z0Count) { t.P2Index = maps[i][t.P2Index]; } else { t.P2Index = maps[i + 1][t.P2Index - Z0Count]; } m->AddFace(t); } delete submesh; } FillUpHole(m,maps,upContourPrcessed, boxU); FillDownHole(m, maps, downContourPrcessed, boxD); delete[] maps; return m; } };
实验效果
本实验采用的轮廓线一共有四层,每一层轮廓线由如下图四条在取自X-Y平面上格点的点组成。数据的预览图如下:
最下层轮廓 第2层轮廓 第3层轮廓 第4层轮廓 生成的结果预览如下:
本文的项目工程的下载:http://files.cnblogs.com/chnhideyoshi/BlogAlgCp.rar
-
基于图像轮廓分析的LCD 线路缺陷检测
2020-08-28 10:43:02为了避免图像配准精度对液晶显示屏( LCD) 线路缺陷检测准确率的影响,采用一种基于图像轮廓分析的新方法,基于深度优先搜索寻找图像轮廓,并根据格林公式计算轮廓面积,将待检测LCD 的线路轮廓面积与标准模板的... -
论文研究-基于格式塔心理学和Eulerspiral的轮廓修复算法.pdf
2019-07-22 20:14:07对角点轮廓遮挡, 利用过角点的两条曲线的可见部分构造两条Euler spiral, 根据Euler spiral的扩展性对构造的两条Euler spiral进行延拓并求交, 从而修复角点遮挡轮廓。方法能自动确定遮挡发生的位置, 能够对T型节点... -
在OpenCV里用drawContours画轮廓
2019-12-25 10:48:25在OpenCV里,找到物体的轮廓是最常用的功能,为什么这样说呢?因为太多的应用要使用这个功能了,比如数物体的个数,在种子实验室里常常要使用计算种子的个数,这时就需要拍照种子的照片,然后根据照片来数出种子的...在OpenCV里,找到物体的轮廓是最常用的功能,为什么这样说呢?因为太多的应用要使用这个功能了,比如数物体的个数,在种子实验室里常常要使用计算种子的个数,这时就需要拍照种子的照片,然后根据照片来数出种子的个数,以便以后计算种子的发芽率。又比如农业上的应用,大家都喜欢吃虾,但是虾苗的培育是需要很高的技术,所以养成年虾和虾苗的农户就不一样了。在买卖虾苗的过程中,由于虾苗的个头比较小,需要大量人工来数虾苗的个数,这时就可以采用拍照的方式,在虾苗的照片再找到轮廓的个数,就可以点算虾苗了。又比如养猪专业户里,如果有数万头小猪,当喂食时,怎么样判断所有小猪都过来吃了呢?其实这种情况里也是可以采用拍照的方式,在照片里数猪的轮廓个数,如果轮廓的数量与养的猪数量一样,说明所有小猪都来吃饭了,说明所有小猪是健康的。在找到轮廓之后,往往需要把轮廓标记出来,这个标记就需要使用drawContours函数,这个函数的定义如下:
其中第一个参数image表示目标图像,即是需要在里面画轮廓的图像
-
机械制图及计算机绘图试题库版.doc.docx
2021-07-08 01:17:27寸光阴不可轻寸光阴不可轻PAGEPAGE #寸光阴不可轻寸光阴不可轻PAGEPAGE #《机械制图及计算机绘图》试题库一、填空题零件的可见轮廓线应用 _绘制,对称图形的对称中心线、轴线用 线绘制。答案:粗实线;点画比例是指... -
电气图纸及接线知识总结
2020-08-21 03:58:45用电气图形符号、带注释的围框或简化外形表示电气系统或设备中组成部分之间相互关系及其连接关系的一种图。广义地说表明两个或两个以上变量之间关系的曲线,用以说明系统、成套装置或设备中各组成部分的相互关系或... -
平面曲线零件恒速运动的测试及数据分析
2020-06-29 16:09:37按照平面曲线恒速运动简化数学模型计算的运动参数,在设计的测试装置上,以偏心轮零件为试件,用运动控制卡控制试件和测量装置的运动,测量试件轮廓的实际线速度。通过改变影响运动的参数进行测试和分析,实际线速度的... -
高分辨率遥感影像支持下的水玉线沿线地质信息提取
2020-10-15 20:06:43通过遥感(RS)技术在辽宁省水玉线输电线路地质灾害调查和应急中的应用前景,应用GF-2高分辨率卫星,从影像遥感解译技术的角度得出辽宁省水玉线高压输电线路地质灾害类型,分别是不稳定斜坡、不稳定边坡、崩塌、泥石流... -
印制线路板高频电路布线技巧
2020-07-27 18:27:12本文拟在简介高频电路布线一般要求的同时,以Protel for Windows V1.5 软件为例来介绍一下高频电路布线时,Protel 软件能提供的一些特殊对策。 -
Protel软件在高频布线中的技巧
2020-08-01 14:14:12数字器件正朝着高速、低耗、小体积、高抗干扰性的方向发展,这一发展趋势对印刷电路板的设计提出了很多新要求。 -
VTK笔记-使用vtkCutter类对多边形取切面轮廓
2022-01-08 16:40:37vtkCutter类 vtkCutter可以使用使用用户指定的隐式函数切割vtkDataSet。 vtkCutter是一个过滤器,可以使用vtkImplicitFunction 的任何子类来切割数据。也就是说,对应于隐式...(相比之下,裁剪采用 N 维单元并创建 N -
动态线滤波探索可视化
2018-10-09 16:54:33该文档基于动态线滤波较详细的描述了血液流动的可视化探索 -
AutoCAD机械作图标准图框-标准线型样式(CAD2007及以上版本可打开).dwg
2022-07-06 09:42:333.图样中,机件的可见轮廓线用粗实线画出,不可见轮廓线用虚线画出,尺寸线和尺寸界线用细实线画出来,对称中心线和轴线用细点划线画出。虚线、细实线和细点划线的图线宽度约为粗实线的1/3。 4.比例是指图中图形... -
AutoCAD机械作图标准图框-标准线型样式(高版本CAD).dwg
2022-07-06 09:41:233.图样中,机件的可见轮廓线用粗实线画出,不可见轮廓线用虚线画出,尺寸线和尺寸界线用细实线画出来,对称中心线和轴线用细点划线画出。虚线、细实线和细点划线的图线宽度约为粗实线的1/3。 4.比例是指图中图形... -
电路板采用网格覆铜还是实心覆铜,你用对了吗?
2019-11-11 21:00:00关注、星标公众号,不错过精彩内容来源:21ic电子网编排:strongerHuang一、什么是覆铜所谓覆铜,就是将电路板上闲置的空间作为基准面,然后用固体铜填充,这些铜区... -
《计算机图形学》-Bézier曲线生成算法探究与实现
2022-05-15 17:16:30参考《计算机图形学》第4版详细介绍了Bézier曲线的生成算法探究与实现,包括Bézier曲线发展历史、公式推导、常用Bézier曲线、Bézier曲线拼接等原理。原文最后还附上关于二次和三次Bézier曲线的源代码供大家参考... -
opencv 基础(6):基于OpenCV的轮廓检测
2022-01-20 14:37:06轮廓线在计算机视觉中的应用 一些非常酷的应用程序已经建立,使用轮廓进行运动检测或分割。下面是一些例子: 运动检测: 在监控视频中,运动检测技术的应用非常广泛,包括室内外安全环境、交通控制、体育活动中的行为... -
基于改进非下采样轮廓波的图像融合算法
2014-04-17 20:37:11基于改进非下采样轮廓波的图像融合算法 一篇非常不错的PDF文档 -
红外图像和可见光图像异源图像配准问题研究
2022-06-15 20:33:57本文旨在研究一种具有高准确率和鲁棒性的融合图像障碍物检测技术,通过把红外和可见光图像进行图像配准和融合,获取高质量的异源融合图像,根据融合图像的特点采用有效的障碍物检测算法,将图像中的障碍物准确检出。... -
基于3DSOM的侧影轮廓方法空间三维模型重建
2021-02-25 18:16:46基于3DSOM的侧影轮廓方法空间三维模型重建1 背景知识1.1 三维信息获取方法1.2 侧影轮廓方法原理及其流程2 三维模型制作2.1 马铃薯三维模型制作2.1.1 多角度图像导入2.1.2 图像掩饰2.1.3 表面生成与优化2.1.4 纹理... -
02·为什么你自学了这么久还当不上助理?-素材3.11(6).zip
2022-04-12 23:48:0102·为什么你自学了这么久还当不上助理?-素材3.11(6).zip -
基于图像分析技术的纱线黑板均匀度检测
2021-03-28 09:49:46基于图像分析技术的纱线黑板均匀度检测 -
电气图纸及接线介绍
2020-08-02 18:40:39本文介绍了电气图的分类、特点及各类常用符号。 -
基于NSCT的红外与可见光图像融合算法
2015-05-04 11:12:44针对红外与可见光图像融合, 提出了一种基于 NSCT 的图像融合方法。首先对图像进行 NSCT 分解;然后对分 解后的子带系数采用基于区域能量匹配度的融合规则分别进行融合:对于低频子带, 使用区域能量和方差构造决策 值...