一大清早看到两则新闻,一个是“英国5岁男童成为世界上最年轻的微软认证电脑专家”,一个是“多名成人冲进小学殴打老师,称不许欺负小少爷”。
我想很多时候我们是输在了起跑线上,中国可能出现年轻的微软MVP认证专家吗?很难,有钱人家都宠着自己的孩子,没钱人家都忙着挣钱没时间管理孩子,再说我们上一代真正懂IT技术的有多少?所以我们输在了起跑线上,这世界上有“点石成金”之术,但是没人在我们很小的时候告诉我们,没人在我们很小的时候就教我们,我们并非不聪明,只是错过了太多。
"悟自往之不鉴,知来者之可追!“
我们很多人都知道,在软件的世界里面,代码可以解决一切问题,但是为什么不去学习?
太忙了?
不懂英文?
不知道如何入门?
年纪太大了?
......
这些都是借口,也许我们没有领略编程的奥秘,也许只是我们太懒惰。
我的师傅刚来公司根本不懂编程,四年的时间,每天晚上到半夜甚至凌晨几点睡觉学习Lsp,四年后成为了公司的Lsp大师,有的时候别人月薪几万不是白来的。你懂的人家也懂,你不懂的人家也懂,你只能拿设计经验去拼,而很多设计经验技巧方法,在IT的世界中不堪一击。有个搞幕墙的老师傅,跟我讲这样提料提料如何方便,然后我写了几行代码,瞬间做出同样的事情,他惊呆了。他说你要是早来几年就好了,能解决我们很多问题。
好吧,废话不说了,我们再看一个例子,链接如下
http://www.xuexiniu.com/thread-80291-1-1.html
这是论坛上的朋友发的一个问题,基本上无人问津,实际上这个问题已经超出了新手问题的范围。
这里面主要涉及了一个Curve.Spline.Catenary电池,很多人都很奇怪,为啥多段线的方向突然变了?都知道变了,但是都不知道为什么,如果你不懂代码,这是一个无法解决的问题。
这里我们只找出方向改变一根线来研究一下(源文件见附件),
我们看到,本来我们是一根Pt1到pt2的线,但是现在方向反了,究竟是为什么?
同样的点,我们将点移动一下,移动到X负半轴
用cat获取的线奇迹般的正确了,实际上到此为止,你已经得到了结论,这个电池有bug,或者在某些电脑上有bug.
我们来看一下里面代码吧,这个代码比较复杂,涉及了各种矩阵变幻
- Private Function SolveCatenary(ByVal A As Point3d, ByVal B As Point3d, ByVal G As Vector3d, ByVal length As Double) As Polyline
- Dim b As Point3d = A
- Dim a As Point3d = B
- Dim transform As Transform = Transform.Translation(-A.X, -A.Y, -A.Z)
- Dim xform As Transform = (Transform.Rotation(G, -Vector3d.ZAxis, Point3d.Origin) * transform)
- A.Transform(xform)
- B.Transform(xform)
- If (B.X < 0) Then
- If GH_Document.IsEscapeKeyDown Then
- Return Nothing
- End If
- Return Me.SolveCatenary(a, b, G, length)
- End If
- Dim startDirection As New Vector3d((B.X - A.X), (B.Y - A.Y), 0)
- Dim transform4 As Transform = Transform.Rotation(startDirection, Vector3d.XAxis, Point3d.Origin)
- Dim identity As Transform = Transform.Identity
- If (startDirection.Length < 10) Then
- Dim scaleFactor As Double = (10 / startDirection.Length)
- identity = Transform.Scale(Point3d.Origin, scaleFactor)
- length = (length * scaleFactor)
- End If
- Dim transform6 As Transform = (identity * transform4)
- A.Transform(transform6)
- B.Transform(transform6)
- Dim transform7 As Transform = (transform6 * xform)
- Dim inverseTransform As Transform = Transform.Identity
- If Not transform7.TryGetInverse(inverseTransform) Then
- Me.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Transformation into Catenary solver coordinates failed.")
- Return Nothing
- End If
- A.DistanceTo(B)
- If (Math.Abs(CDbl((A.X - B.X))) < (0.01 * GH_Component.DocumentTolerance)) Then
- Dim polyline As Polyline = Me.SimpleChain(A, B, G, length)
- polyline.Transform(inverseTransform)
- Return polyline
- End If
- Dim num2 As Integer = 50
- num2 = Math.Min(num2, 100)
- Try
- Dim delegate2 As CatenaryDelegate = Me.Catenary(A.X, A.Z, B.X, B.Z, length, (0.1 * GH_Component.DocumentTolerance))
- If (delegate2 Is Nothing) Then
- Dim polyline2 As Polyline = Me.SimpleChain(A, B, G, length)
- polyline2.Transform(inverseTransform)
- Return polyline2
- End If
- Dim collection As Point3d() = New Point3d(num2 - 1) {}
- Dim num3 As Double = ((B.X - A.X) / CDbl((num2 - 1)))
- Dim x As Double = A.X
- Dim i As Integer
- For i = 0 To num2 - 1
- collection(i) = New Point3d(x, A.Y, delegate2.Invoke(x))
- x = (x + num3)
- Next i
- Dim polyline3 As New Polyline(collection)
- polyline3.Transform(inverseTransform)
- Dim pointd3 As Point3d = polyline3.Item(0)
- Dim pointd4 As Point3d = polyline3.Item(0)
- If (pointd3.DistanceTo(A) > pointd4.DistanceTo(B)) Then
- polyline3.Reverse
- End If
- Return polyline3
- Catch exception As Exception
- Me.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, exception.Message)
- Return Nothing
- End Try
-
复制代码 里面有很多内容,反汇编得到的代码也比较乱,我么找出重点看到
If (pointd3.DistanceTo(A) > pointd4.DistanceTo(B)) Then
polyline3.Reverse
End If
这个地方有个翻转的操作.我们再来看看Polyline3是怎么得到的
- Dim collection As Point3d() = New Point3d(num2 - 1) {}
- Dim num3 As Double = ((B.X - A.X) / CDbl((num2 - 1)))
- Dim x As Double = A.X
- Dim i As Integer
- For i = 0 To num2 - 1
- collection(i) = New Point3d(x, A.Y, delegate2.Invoke(x))
- x = (x + num3)
- Next i
- Dim polyline3 As New Polyline(collection)
- polyline3.Transform(inverseTransform)
复制代码
经过一系列转换后的点A,B(就是我们输入的点)已经不再原来位置了,如下图
程序中通过转换后的pt1,pt2的到了Polyline3然后Polyline3进行了一次矩阵转换回到了原来的位置。
但是在判断这个翻转的时候
If (pointd3.DistanceTo(A) > pointd4.DistanceTo(B)) Then
polyline3.Reverse
End If
这里的A和B也就是Pt1,Pt2本来应该是原始的A,B,作者却错用了转换后的Pt1,Pt2,这样肯定会出问题啦。
实际上这也是我们写代码中经常遇到到的一个bug,就是某个变量操作了很多次后,我们还以为它没变化,当成以前的来用。
通过首行代码
Dim b As Point3d = A
Dim a As Point3d = B
我们不难发现,作者实际上已经储存了原始的点,在判断翻转的时候,我们只需要使用a,b即可(在C#中区分大小写,VB中不区分,这里可见Reflector反编译器对于VB代码的反编译也有bug)
可能是作者手误,偏偏写成了大小A,B。
原因查完了,我们可以直接动手修改代码了,如何修改我就不说了,说的太多容易被封号呀。我的官方论坛账号和SEG插件都还在封锁状态,这段时间又比较忙,好蛋疼。
在官方论坛上面,我给他们发现的bug不下于数百个,上面讨论的很多问题都是前无古人的,但是偏偏被Jessson封掉了,让任何人都看不到帖子,我倒是不在乎,那些问题我都解决了,但是你让后来者碰到同样问题的人麻烦了,这是在惩罚谁?
下面附件中的Curve.gha中修复了这个bug,替换掉自带的Curve.gha即可使用,路径"C:\Program Files\Common Files\McNeel\Rhinoceros\5.0\Plug-ins\Grasshopper (b45a29b1-4343-4035-989e-044e8580d9cf)\0.9.76.0\Components\Curve.gha"(每个人的电脑可能不一样,自己找一下)
替换后效果
精彩分享:
欢迎传播此微信号:SecondEffectGroup
|
|
举报