WolframAlpha.com
WolframCloud.com
All Sites & Public Resources...
Products & Services
Wolfram|One
Mathematica
Wolfram|Alpha Notebook Edition
Programming Lab
Finance Platform
SystemModeler
Wolfram Player
Wolfram Engine
WolframScript
Enterprise Private Cloud
Enterprise Mathematica
Wolfram|Alpha Appliance
Enterprise Solutions
Corporate Consulting
Technical Consulting
Wolfram|Alpha Business Solutions
Resource System
Data Repository
Neural Net Repository
Function Repository
Wolfram|Alpha
Wolfram|Alpha Pro
Problem Generator
API
Data Drop
Products for Education
Mobile Apps
Wolfram Player
Wolfram Cloud App
Wolfram|Alpha for Mobile
Wolfram|Alpha-Powered Apps
Services
Paid Project Support
Wolfram U
Summer Programs
All Products & Services »
Technologies
Wolfram Language
Revolutionary knowledge-based programming language.
Wolfram Cloud
Central infrastructure for Wolfram's cloud products & services.
Wolfram Science
Technology-enabling science of the computational universe.
Wolfram Notebooks
The preeminent environment for any technical workflows.
Wolfram Engine
Software engine implementing the Wolfram Language.
Wolfram Natural Language Understanding System
Knowledge-based broadly deployed natural language.
Wolfram Data Framework
Semantic framework for real-world data.
Wolfram Universal Deployment System
Instant deployment across cloud, desktop, mobile, and more.
Wolfram Knowledgebase
Curated computable knowledge powering Wolfram|Alpha.
All Technologies »
Solutions
Engineering, R&D
Aerospace & Defense
Chemical Engineering
Control Systems
Electrical Engineering
Image Processing
Industrial Engineering
Mechanical Engineering
Operations Research
More...
Finance, Statistics & Business Analysis
Actuarial Sciences
Bioinformatics
Data Science
Econometrics
Financial Risk Management
Statistics
More...
Education
All Solutions for Education
Trends
Machine Learning
Multiparadigm Data Science
Internet of Things
High-Performance Computing
Hackathons
Software & Web
Software Development
Authoring & Publishing
Interface Development
Web Development
Sciences
Astronomy
Biology
Chemistry
More...
All Solutions »
Learning & Support
Learning
Wolfram Language Documentation
Fast Introduction for Programmers
Wolfram U
Videos & Screencasts
Wolfram Language Introductory Book
Webinars & Training
Summer Programs
Books
Need Help?
Support FAQ
Wolfram Community
Contact Support
Premium Support
Paid Project Support
Technical Consulting
All Learning & Support »
Company
About
Company Background
Wolfram Blog
Events
Contact Us
Work with Us
Careers at Wolfram
Internships
Other Wolfram Language Jobs
Initiatives
Wolfram Foundation
MathWorld
Computer-Based Math
A New Kind of Science
Wolfram Technology for Hackathons
Student Ambassador Program
Wolfram for Startups
Demonstrations Project
Wolfram Innovator Awards
Wolfram + Raspberry Pi
Summer Programs
More...
All Company »
Search
WOLFRAM COMMUNITY
Connect with users of Wolfram technologies to learn, solve problems and share ideas
Join
Sign In
Dashboard
Groups
People
Search
Message Boards
Answer
(
Unmark
)
Mark as an Answer
GROUPS:
Staff Picks
Data Science
Mathematics
Recreation
Visual Arts
Geometry
Graphics and Visualization
Wolfram Language
Optimization
Machine Learning
17
Silvia Hao
[GIF] Ribbons of three materials: splines, neural nets & contour surfaces
Silvia Hao, CTO at Glimscape Technology
Posted
25 days ago
1960 Views
|
7 Replies
|
23 Total Likes
Follow this post
|
( ^ Click the GIF for a 3840x1280 wallpaper! :)
— or how to fit B-spline onto contour surface
Happy New Year to everyone who reached this post! Today we are going to explore a mixed power of B-spline and neural network!
When plotting contour surface, have you, like me, done things like increasing
PlotPoints
so to have smooth looking surface and mesh lines, in the cost of bloomed up notebook size and/or less responsive
Graphics3D
result? If the answer is yes, then please do take a look at the approach of B-spline. As a
nice function approximator
, we may not need that much control points to have a applause B-spline if it’s just for meeting the eyes. And for RAM efficiency, we are going to do the computing with differentiable programming, through Wolfam Language’s neural network framework.
Helper functions
C
l
e
a
r
A
l
l
[
F
i
n
d
D
i
v
i
s
i
o
n
s
E
x
a
c
t
]
F
i
n
d
D
i
v
i
s
i
o
n
s
E
x
a
c
t
[
r
a
n
g
e
:
{
_
,
_
}
,
n
_
I
n
t
e
g
e
r
?
(
#
>
=
2
&
)
]
:
=
R
e
s
c
a
l
e
[
R
a
n
g
e
[
n
]
/
/
N
/
/
R
e
s
c
a
l
e
,
{
0
,
1
}
,
r
a
n
g
e
]
F
i
n
d
D
i
v
i
s
i
o
n
s
E
x
a
c
t
[
n
_
I
n
t
e
g
e
r
?
(
#
>
=
2
&
)
]
:
=
F
i
n
d
D
i
v
i
s
i
o
n
s
E
x
a
c
t
[
{
0
,
1
}
,
n
]
C
l
e
a
r
A
l
l
[
p
i
p
e
,
b
r
a
n
c
h
,
b
r
a
n
c
h
S
e
q
]
p
i
p
e
=
R
i
g
h
t
C
o
m
p
o
s
i
t
i
o
n
;
b
r
a
n
c
h
=
T
h
r
o
u
g
h
@
*
{
#
#
}
&
;
b
r
a
n
c
h
S
e
q
=
p
i
p
e
[
b
r
a
n
c
h
@
#
#
,
A
p
p
l
y
@
S
e
q
u
e
n
c
e
]
&
;
The contour surface model — a well-known example
For demonstration I’ll use one of my favourite example, the transcendental periodic implicit surface in
ContourPlot3D
’s documentation, constrained in a ball region:
C
l
e
a
r
A
l
l
[
,
ℛ
]
=
F
u
n
c
t
i
o
n
[
{
x
,
y
,
z
}
,
C
o
s
[
x
]
S
i
n
[
y
]
+
C
o
s
[
y
]
S
i
n
[
z
]
+
C
o
s
[
z
]
S
i
n
[
x
]
]
;
ℛ
=
B
a
l
l
[
{
0
,
0
,
0
}
,
π
]
;
c
o
n
t
o
u
r
G
r
a
p
h
=
C
o
n
t
o
u
r
P
l
o
t
3
D
[
[
x
,
y
,
z
]
0
,
{
x
,
y
,
z
}
∈
ℛ
,
P
l
o
t
P
o
i
n
t
s
4
0
,
M
a
x
R
e
c
u
r
s
i
o
n
0
,
M
e
s
h
S
t
y
l
e
G
r
a
y
L
e
v
e
l
[
.
7
]
,
R
e
g
i
o
n
B
o
u
n
d
a
r
y
S
t
y
l
e
N
o
n
e
,
B
o
x
e
d
F
a
l
s
e
,
A
x
e
s
F
a
l
s
e
,
L
i
g
h
t
i
n
g
"
A
c
c
e
n
t
"
,
C
o
n
t
o
u
r
S
t
y
l
e
W
h
i
t
e
]
We are going to find mesh lines (curves) on
with their terminals being randomly selected from the surface of ball
ℛ
:
C
l
e
a
r
A
l
l
[
b
ℛ
]
b
ℛ
=
A
n
d
[
[
x
,
y
,
z
]
0
,
{
x
,
y
,
z
}
∈
R
e
g
i
o
n
B
o
u
n
d
a
r
y
[
ℛ
]
]
/
/
p
i
p
e
[
I
m
p
l
i
c
i
t
R
e
g
i
o
n
[
#
,
{
x
,
y
,
z
}
]
&
,
D
i
s
c
r
e
t
i
z
e
R
e
g
i
o
n
[
#
,
B
o
x
e
d
T
r
u
e
,
A
x
e
s
T
r
u
e
]
&
]
The B-spline curve model
As we have talked about in past posts, a uniform B-spline curve is simply a linear combination of its control points with BSplineBasis as the weights:
C
(
t
)
:
=
n
∑
i
=
1
P
i
N
i
,
d
(
t
)
,
t
∈
[
0
,
1
]
(
1
)
For our purpose here, we discretize the curve
C
(
t
)
by a naïve uniform sample over
t
∈
[
0
,
1
]
, so it becomes:
C
c
×
s
×
d
:
=
N
s
×
n
·
P
n
×
c
×
d
,
(
2
)
where
N
is the discrete B-spline basis matrix,
P
is the array of control points. The meaning of their dimensions are
S
y
m
b
o
l
M
e
a
n
i
n
g
V
a
r
i
a
b
l
e
n
a
m
e
T
y
p
i
c
a
l
v
a
l
u
e
c
n
u
m
b
e
r
o
f
c
u
r
v
e
s
$
c
u
r
v
e
N
u
m
1
1
s
s
a
m
p
l
e
s
i
z
e
$
s
a
m
p
l
e
N
u
m
1
0
0
d
e
m
b
e
d
d
e
d
d
i
m
e
n
s
i
o
n
$
e
m
b
e
d
d
e
d
D
i
m
3
n
n
u
m
b
e
r
o
f
c
o
n
t
r
o
l
p
o
i
n
t
s
$
C
P
t
s
N
u
m
5
Prototype for the curve
As we have shown, the curves are represented as
C
=
N
·
P
. But we can’t just throw a
LinearLayer
for it because we want the terminals predefined and fixed while keeping the “internal” control points trainable. So instead we separate them as
C
c
×
s
×
d
:
=
N
s
×
n
·
J
o
i
n
P
s
t
a
r
t
i
n
g
t
e
r
m
i
n
a
l
1
×
c
×
d
,
P
m
i
d
d
l
e
(
n
-
2
)
×
c
×
d
,
P
e
n
d
i
n
g
t
e
r
m
i
n
a
l
1
×
c
×
d
(
3
)
<
<
N
e
u
r
a
l
N
e
t
w
o
r
k
s
`
C
l
e
a
r
A
l
l
[
c
u
r
v
e
P
r
o
t
o
t
y
p
e
]
c
u
r
v
e
P
r
o
t
o
t
y
p
e
=
N
e
t
G
r
a
p
h
[
(
*
s
*
n
*
)
"
b
a
s
i
s
"
P
l
a
c
e
h
o
l
d
e
r
L
a
y
e
r
[
I
n
p
u
t
P
o
r
t
s
{
}
,
O
u
t
p
u
t
P
o
r
t
s
{
M
a
t
r
i
x
T
[
]
}
]
,
"
s
t
a
r
t
C
p
t
s
"
R
e
p
l
i
c
a
t
e
L
a
y
e
r
[
1
]
,
"
e
n
d
C
p
t
s
"
R
e
p
l
i
c
a
t
e
L
a
y
e
r
[
1
]
,
(
*
(
n
-
2
)
*
c
*
d
*
)
"
m
i
d
C
p
t
s
"
N
e
t
A
r
r
a
y
L
a
y
e
r
[
"
O
u
t
p
u
t
"
T
e
n
s
o
r
O
f
R
a
n
k
T
[
3
]
]
,
(
*
n
*
c
*
d
*
)
"
c
p
t
s
"
C
a
t
e
n
a
t
e
L
a
y
e
r
[
]
,
"
c
u
r
v
e
"
D
o
t
L
a
y
e
r
[
]
,
(
*
c
*
s
*
d
*
)
"
c
u
r
v
e
S
e
t
"
T
r
a
n
s
p
o
s
e
L
a
y
e
r
[
]
,
{
T
h
r
e
a
d
[
(
N
e
t
P
o
r
t
/
@
{
"
s
t
a
r
t
"
,
"
e
n
d
"
}
)
{
"
s
t
a
r
t
C
p
t
s
"
,
"
e
n
d
C
p
t
s
"
}
]
,
{
"
s
t
a
r
t
C
p
t
s
"
,
"
m
i
d
C
p
t
s
"
,
"
e
n
d
C
p
t
s
"
}
"
c
p
t
s
"
,
{
"
b
a
s
i
s
"
,
"
c
p
t
s
"
}
"
c
u
r
v
e
"
"
c
u
r
v
e
S
e
t
"
}
/
/
F
l
a
t
t
e
n
,
(
*
c
*
d
*
)
"
s
t
a
r
t
"
M
a
t
r
i
x
T
[
]
,
(
*
c
*
d
*
)
"
e
n
d
"
M
a
t
r
i
x
T
[
]
]
Replacing
“basis”
and
“midCpts”
layers with concrete
NetArrayLayer
will instantize the prototype:
M
o
d
u
l
e
[
{
$
s
a
m
p
l
e
N
u
m
=
5
,
$
C
P
t
s
N
u
m
=
3
,
$
c
u
r
v
e
N
u
m
=
1
1
,
$
e
m
b
e
d
d
e
d
D
i
m
=
2
,
d
a
t
a
,
n
e
t
}
,
n
e
t
=
N
e
t
R
e
p
l
a
c
e
P
a
r
t
[
c
u
r
v
e
P
r
o
t
o
t
y
p
e
,
{
"
b
a
s
i
s
"
N
e
t
A
r
r
a
y
L
a
y
e
r
[
"
A
r
r
a
y
"
R
a
n
d
o
m
R
e
a
l
[
1
,
{
$
s
a
m
p
l
e
N
u
m
,
$
C
P
t
s
N
u
m
}
]
]
,
{
"
m
i
d
C
p
t
s
"
,
"
A
r
r
a
y
"
}
R
a
n
d
o
m
R
e
a
l
[
1
,
{
$
C
P
t
s
N
u
m
-
2
,
$
c
u
r
v
e
N
u
m
,
$
e
m
b
e
d
d
e
d
D
i
m
}
]
}
]
;
d
a
t
a
=
R
a
n
d
o
m
R
e
a
l
[
1
,
{
2
,
$
c
u
r
v
e
N
u
m
,
$
e
m
b
e
d
d
e
d
D
i
m
}
]
/
/
A
s
s
o
c
i
a
t
i
o
n
T
h
r
e
a
d
[
{
"
s
t
a
r
t
"
,
"
e
n
d
"
}
,
#
]
&
;
d
a
t
a
/
/
p
i
p
e
[
n
e
t
,
M
a
p
T
h
r
e
a
d
[
{
#
2
,
L
i
n
e
@
#
1
}
&
,
{
#
,
#
/
/
L
e
n
g
t
h
/
/
F
i
n
d
D
i
v
i
s
i
o
n
s
E
x
a
c
t
/
/
M
a
p
[
C
o
l
o
r
D
a
t
a
@
"
R
a
i
n
b
o
w
"
]
}
]
&
,
G
r
a
p
h
i
c
s
]
]
B-spline basis
To specify a set of B-spline basis through
BSplineBasis
, we need to firstly decide how “smooth” we want the curves to be (the degree of the spline
$bsDegree
), and how capable of fitting wiggle shapes we want the curves to be (the number of control points for each spline
$CPtsNum
). Then the uniform knots can be determined unambiguously. To discretize the basis we need to specify the sample size
$sampleNum
. The basis set will then be generated and stored in an un-trainable
NetArrayLayer
:
C
l
e
a
r
A
l
l
[
b
a
s
i
s
N
e
t
]
b
a
s
i
s
N
e
t
[
$
s
a
m
p
l
e
N
u
m
_
I
n
t
e
g
e
r
?
P
o
s
i
t
i
v
e
,
{
$
C
P
t
s
N
u
m
_
I
n
t
e
g
e
r
?
P
o
s
i
t
i
v
e
,
$
b
s
D
e
g
r
e
e
_
I
n
t
e
g
e
r
?
P
o
s
i
t
i
v
e
,
$
f
u
l
l
K
n
o
t
_
L
i
s
t
}
]
:
=
T
a
b
l
e
[
B
S
p
l
i
n
e
B
a
s
i
s
[
{
$
b
s
D
e
g
r
e
e
,
$
f
u
l
l
K
n
o
t
}
,
i
-
1
,
#
]
,
{
i
,
$
C
P
t
s
N
u
m
}
]
/
/
p
i
p
e
[
M
a
p
@
F
u
n
c
t
i
o
n
,
A
p
p
l
y
@
b
r
a
n
c
h
,
M
a
p
,
b
r
a
n
c
h
S
e
q
[
I
d
e
n
t
i
t
y
,
F
i
n
d
D
i
v
i
s
i
o
n
s
E
x
a
c
t
[
$
s
a
m
p
l
e
N
u
m
]
&
]
,
C
o
n
s
t
r
u
c
t
,
N
e
t
A
r
r
a
y
L
a
y
e
r
[
"
A
r
r
a
y
"
#
,
L
e
a
r
n
i
n
g
R
a
t
e
M
u
l
t
i
p
l
i
e
r
s
N
o
n
e
]
&
]
C
l
e
a
r
[
$
b
s
D
e
g
r
e
e
,
$
C
P
t
s
N
u
m
,
$
b
s
K
n
o
t
,
$
s
a
m
p
l
e
N
u
m
]
$
b
s
D
e
g
r
e
e
=
3
;
$
C
P
t
s
N
u
m
=
4
;
I
f
[
N
o
t
[
$
C
P
t
s
N
u
m
-
$
b
s
D
e
g
r
e
e
+
1
≥
2
]
,
E
c
h
o
@
"
$
C
P
t
s
N
u
m
a
n
d
$
b
s
D
e
g
r
e
e
i
s
n
o
t
c
o
m
p
a
t
i
b
l
e
.
"
]
;
$
b
s
K
n
o
t
=
{
C
o
n
s
t
a
n
t
A
r
r
a
y
[
0
,
$
b
s
D
e
g
r
e
e
]
,
R
a
n
g
e
[
$
C
P
t
s
N
u
m
-
$
b
s
D
e
g
r
e
e
+
1
]
/
/
R
e
s
c
a
l
e
,
C
o
n
s
t
a
n
t
A
r
r
a
y
[
1
,
$
b
s
D
e
g
r
e
e
]
}
/
/
F
l
a
t
t
e
n
;
$
s
a
m
p
l
e
N
u
m
=
1
0
0
;
b
a
s
i
s
N
e
t
[
$
s
a
m
p
l
e
N
u
m
,
{
$
C
P
t
s
N
u
m
,
$
b
s
D
e
g
r
e
e
,
$
b
s
K
n
o
t
}
]
/
/
p
i
p
e
[
C
o
n
s
t
r
u
c
t
,
T
r
a
n
s
p
o
s
e
,
L
i
s
t
L
i
n
e
P
l
o
t
]
Instance of curves
Replacing “basis” layer with
basisNet
will instantize a group of B-spline curves:
M
o
d
u
l
e
{
$
c
u
r
v
e
N
u
m
=
5
,
$
e
m
b
e
d
d
e
d
D
i
m
=
2
,
n
e
t
,
d
a
t
a
}
,
n
e
t
=
N
e
t
R
e
p
l
a
c
e
P
a
r
t
[
c
u
r
v
e
P
r
o
t
o
t
y
p
e
,
{
"
b
a
s
i
s
"
b
a
s
i
s
N
e
t
[
$
s
a
m
p
l
e
N
u
m
,
{
$
C
P
t
s
N
u
m
,
$
b
s
D
e
g
r
e
e
,
$
b
s
K
n
o
t
}
]
,
{
"
m
i
d
C
p
t
s
"
,
"
A
r
r
a
y
"
}
R
a
n
d
o
m
R
e
a
l
[
1
,
{
$
C
P
t
s
N
u
m
-
2
,
$
c
u
r
v
e
N
u
m
,
$
e
m
b
e
d
d
e
d
D
i
m
}
]
,
"
s
t
a
r
t
"
{
$
c
u
r
v
e
N
u
m
,
$
e
m
b
e
d
d
e
d
D
i
m
}
}
]
;
E
c
h
o
[
n
e
t
]
;
d
a
t
a
=
R
a
n
d
o
m
R
e
a
l
[
1
,
{
2
,
$
c
u
r
v
e
N
u
m
,
$
e
m
b
e
d
d
e
d
D
i
m
}
]
/
/
A
s
s
o
c
i
a
t
i
o
n
T
h
r
e
a
d
[
{
"
s
t
a
r
t
"
,
"
e
n
d
"
}
,
#
]
&
;
n
e
t
/
/
p
i
p
e
b
r
a
n
c
h
[
I
d
e
n
t
i
t
y
,
p
i
p
e
[
N
e
t
T
a
k
e
[
#
,
"
c
p
t
s
"
]
,
T
r
a
n
s
p
o
s
e
]
&
]
,
A
p
p
l
y
@
b
r
a
n
c
h
,
#
[
d
a
t
a
]
&
,
M
a
p
T
h
r
e
a
d
(
*
G
r
o
u
n
d
t
r
u
t
h
B
-
s
p
l
i
n
e
c
u
r
v
e
:
*
)
{
#
2
,
B
S
p
l
i
n
e
C
u
r
v
e
[
#
1
〚
2
〛
,
S
p
l
i
n
e
D
e
g
r
e
e
$
b
s
D
e
g
r
e
e
,
S
p
l
i
n
e
K
n
o
t
s
$
b
s
K
n
o
t
]
}
,
(
*
N
N
c
o
m
p
u
t
e
d
c
u
r
v
e
:
*
)
{
#
2
,
D
a
s
h
e
d
,
A
b
s
o
l
u
t
e
T
h
i
c
k
n
e
s
s
[
3
]
,
L
i
n
e
@
#
1
〚
1
〛
}
,
(
*
C
o
n
t
r
o
l
l
i
n
e
a
n
d
p
o
i
n
t
s
:
*
)
{
L
i
g
h
t
e
r
@
#
2
,
L
i
n
e
@
#
1
〚
2
〛
}
,
E
d
g
e
F
o
r
m
[
L
i
g
h
t
e
r
@
#
2
]
,
F
a
c
e
F
o
r
m
,
T
r
a
n
s
l
a
t
e
[
D
i
s
k
[
{
0
,
0
}
,
.
0
1
]
,
#
]
&
@
#
1
2
&
,
{
#
,
#
/
/
L
e
n
g
t
h
/
/
F
i
n
d
D
i
v
i
s
i
o
n
s
E
x
a
c
t
/
/
M
a
p
[
C
o
l
o
r
D
a
t
a
@
"
R
a
i
n
b
o
w
"
]
}
&
,
G
r
a
p
h
i
c
s
»
The contour surface as a neural network
On the surface side, we are going to construct a neural network that takes a group of
d
(
d
=
$
e
m
b
e
d
d
e
d
D
i
m
=
3
)
dimensional points as input, gives a total score on how well those points fit on the surface:
C
l
e
a
r
A
l
l
[
$
e
m
b
e
d
d
e
d
D
i
m
,
s
u
r
f
a
c
e
M
a
t
c
h
N
e
t
]
$
e
m
b
e
d
d
e
d
D
i
m
=
3
;
s
u
r
f
a
c
e
M
a
t
c
h
N
e
t
=
M
o
d
u
l
e
[
{
s
a
m
p
l
e
P
o
i
n
t
s
}
,
s
a
m
p
l
e
P
o
i
n
t
s
=
S
t
r
i
n
g
T
e
m
p
l
a
t
e
[
"
x
`
`
"
]
/
@
R
a
n
g
e
[
$
e
m
b
e
d
d
e
d
D
i
m
]
;
N
e
t
G
r
a
p
h
[
(
*
D
e
s
t
r
u
c
t
i
n
p
u
t
c
u
r
v
e
a
r
r
a
y
t
o
d
p
o
r
t
s
:
*
)
"
c
u
r
v
e
2
p
t
s
"
N
e
t
G
r
a
p
h
[
F
l
a
t
t
e
n
@
{
P
a
r
t
L
a
y
e
r
/
@
R
a
n
g
e
[
$
e
m
b
e
d
d
e
d
D
i
m
]
,
T
r
a
n
s
p
o
s
e
L
a
y
e
r
[
1
-
1
]
}
,
F
l
a
t
t
e
n
@
{
(
$
e
m
b
e
d
d
e
d
D
i
m
+
1
)
R
a
n
g
e
[
$
e
m
b
e
d
d
e
d
D
i
m
]
,
T
h
r
e
a
d
[
R
a
n
g
e
[
$
e
m
b
e
d
d
e
d
D
i
m
]
(
N
e
t
P
o
r
t
/
@
s
a
m
p
l
e
P
o
i
n
t
s
)
]
}
]
,
(
*
F
e
e
d
i
n
t
o
f
o
r
m
u
l
a
o
f
t
h
e
s
u
r
f
a
c
e
:
*
)
"
s
u
r
f
a
c
e
"
T
h
r
e
a
d
i
n
g
L
a
y
e
r
@
(
*
F
i
t
g
o
o
d
n
e
s
s
a
s
a
m
e
a
n
s
q
u
a
r
e
d
l
o
s
s
:
*
)
,
"
f
i
t
g
o
o
d
n
e
s
s
"
{
E
l
e
m
e
n
t
w
i
s
e
L
a
y
e
r
[
2
#
&
]
,
S
u
m
m
a
t
i
o
n
L
a
y
e
r
[
]
}
,
{
N
e
t
P
o
r
t
[
"
I
n
p
u
t
"
]
"
c
u
r
v
e
2
p
t
s
"
,
(
N
e
t
P
o
r
t
[
"
c
u
r
v
e
2
p
t
s
"
,
#
]
&
/
@
s
a
m
p
l
e
P
o
i
n
t
s
)
"
s
u
r
f
a
c
e
"
"
f
i
t
g
o
o
d
n
e
s
s
"
}
,
"
I
n
p
u
t
"
T
e
n
s
o
r
W
i
t
h
M
i
n
R
a
n
k
T
[
2
]
]
]
Our dimension setting
TensorWithMinRankT[2]
is general enough, so
surfaceMatchNet
works as expected for both
s
×
d
and
c
×
s
×
d
sample point set:
i
s
o
S
u
r
f
=
N
e
t
T
a
k
e
[
s
u
r
f
a
c
e
M
a
t
c
h
N
e
t
,
"
s
u
r
f
a
c
e
"
]
;
Example of
5
1
0
points:
R
a
n
d
o
m
P
o
i
n
t
[
ℛ
,
5
1
0
]
/
/
p
i
p
e
[
b
r
a
n
c
h
S
e
q
[
I
d
e
n
t
i
t
y
,
p
i
p
e
[
E
c
h
o
T
i
m
i
n
g
[
i
s
o
S
u
r
f
@
#
,
"
i
s
o
S
u
r
f
t
i
m
i
n
g
"
]
&
,
T
h
r
e
a
d
[
2
#
<
0
.
0
1
]
&
]
]
,
P
i
c
k
,
G
r
a
p
h
i
c
s
3
D
[
{
A
b
s
o
l
u
t
e
P
o
i
n
t
S
i
z
e
[
1
]
,
P
o
i
n
t
@
#
}
]
&
,
A
b
s
o
l
u
t
e
T
i
m
i
n
g
]
⌚
i
s
o
S
u
r
f
t
i
m
i
n
g
0
.
0
3
9
7
8
7
6
0
.
2
4
9
4
8
4
,
Example of 8 groups with
4
1
0
points per group:
T
u
p
l
e
s
[
{
-
1
,
1
}
,
3
]
/
/
p
i
p
e
[
M
a
p
@
p
i
p
e
[
{
{
0
,
0
,
0
}
,
#
π
}
&
,
N
,
M
a
p
@
S
o
r
t
,
T
r
a
n
s
p
o
s
e
,
A
p
p
l
y
@
C
u
b
o
i
d
,
F
u
n
c
t
i
o
n
[
o
c
t
a
n
t
,
R
e
g
i
o
n
I
n
t
e
r
s
e
c
t
i
o
n
[
ℛ
,
o
c
t
a
n
t
]
/
/
R
a
n
d
o
m
P
o
i
n
t
[
#
,
4
1
0
]
&
]
]
,
D
e
v
e
l
o
p
e
r
`
T
o
P
a
c
k
e
d
A
r
r
a
y
,
b
r
a
n
c
h
S
e
q
[
I
d
e
n
t
i
t
y
,
p
i
p
e
[
E
c
h
o
T
i
m
i
n
g
[
i
s
o
S
u
r
f
@
#
,
"
i
s
o
S
u
r
f
t
i
m
i
n
g
"
]
&
,
U
n
i
t
S
t
e
p
[
.
0
1
-
2
#
]
&
,
T
r
a
n
s
p
o
s
e
]
]
,
P
i
c
k
[
#
#
,
1
]
&
,
M
a
p
T
h
r
e
a
d
[
{
#
2
,
P
o
i
n
t
@
#
1
}
&
,
{
#
,
#
/
/
L
e
n
g
t
h
/
/
F
i
n
d
D
i
v
i
s
i
o
n
s
E
x
a
c
t
/
/
M
a
p
[
C
o
l
o
r
D
a
t
a
@
"
R
a
i
n
b
o
w
"
]
}
]
&
,
G
r
a
p
h
i
c
s
3
D
[
{
A
b
s
o
l
u
t
e
P
o
i
n
t
S
i
z
e
[
1
]
,
#
}
]
&
,
A
b
s
o
l
u
t
e
T
i
m
i
n
g
]
⌚
i
s
o
S
u
r
f
t
i
m
i
n
g
0
.
0
2
5
1
4
3
2
1
.
6
4
3
2
4
,
Solve the fitting problem with neural network optimizer
Now we have a curve model
curvePrototype
that outputs
c
curves in
d
dimensional space with sample size
s
, in a shape of
c
×
s
×
d
array, it’s easy to pipe its output to the contour surface measurement net
surfaceMatchNet
, so to get a whole training target on how well the B-spline curves lie on the surface:
N
e
t
G
r
a
p
h
[
{
c
u
r
v
e
P
r
o
t
o
t
y
p
e
,
s
u
r
f
a
c
e
M
a
t
c
h
N
e
t
}
,
{
1
2
}
]
/
/
I
n
f
o
r
m
a
t
i
o
n
[
#
,
"
F
u
l
l
S
u
m
m
a
r
y
G
r
a
p
h
i
c
"
]
&
We select
2
×
c
random points from the boundary region
b
ℛ
as the terminal points of the
c
curves, and ask for a fit-goodness equals zero:
C
l
e
a
r
[
$
c
u
r
v
e
N
u
m
,
t
e
r
m
i
n
a
l
P
o
i
n
t
S
e
t
,
t
r
a
i
n
i
n
g
D
a
t
a
]
$
c
u
r
v
e
N
u
m
=
1
0
0
;
t
e
r
m
i
n
a
l
P
o
i
n
t
S
e
t
=
R
a
n
d
o
m
P
o
i
n
t
[
b
ℛ
,
{
2
,
$
c
u
r
v
e
N
u
m
}
]
;
t
r
a
i
n
i
n
g
D
a
t
a
=
t
e
r
m
i
n
a
l
P
o
i
n
t
S
e
t
/
/
p
i
p
e
[
A
p
p
e
n
d
[
0
]
,
A
s
s
o
c
i
a
t
i
o
n
T
h
r
e
a
d
[
{
"
s
t
a
r
t
"
,
"
e
n
d
"
,
"
f
i
t
g
o
o
d
n
e
s
s
"
}
,
#
]
&
,
M
a
p
[
D
e
v
e
l
o
p
e
r
`
T
o
P
a
c
k
e
d
A
r
r
a
y
]
]
;
Generally, higher spline degree and more control points result in better fitting:
C
l
e
a
r
[
$
b
s
D
e
g
r
e
e
,
$
C
P
t
s
N
u
m
,
$
b
s
K
n
o
t
,
$
s
a
m
p
l
e
N
u
m
]
$
b
s
D
e
g
r
e
e
=
5
;
$
C
P
t
s
N
u
m
=
7
;
I
f
$
C
P
t
s
N
u
m
-
$
b
s
D
e
g
r
e
e
+
1
≥
2
,
E
c
h
o
@
S
t
y
l
e
"
$
C
P
t
s
N
u
m
a
n
d
$
b
s
D
e
g
r
e
e
a
r
e
c
o
m
p
a
t
i
b
l
e
.
"
,
B
o
l
d
,
,
E
c
h
o
@
S
t
y
l
e
"
$
C
P
t
s
N
u
m
a
n
d
$
b
s
D
e
g
r
e
e
a
r
e
n
o
t
c
o
m
p
a
t
i
b
l
e
.
"
,
B
o
l
d
,
;
$
b
s
K
n
o
t
=
{
C
o
n
s
t
a
n
t
A
r
r
a
y
[
0
,
$
b
s
D
e
g
r
e
e
]
,
R
a
n
g
e
[
$
C
P
t
s
N
u
m
-
$
b
s
D
e
g
r
e
e
+
1
]
/
/
R
e
s
c
a
l
e
,
C
o
n
s
t
a
n
t
A
r
r
a
y
[
1
,
$
b
s
D
e
g
r
e
e
]
}
/
/
F
l
a
t
t
e
n
;
$
s
a
m
p
l
e
N
u
m
=
1
0
0
;
»
$
C
P
t
s
N
u
m
a
n
d
$
b
s
D
e
g
r
e
e
a
r
e
c
o
m
p
a
t
i
b
l
e
.
n
n
R
e
s
u
l
t
=
M
o
d
u
l
e
[
{
m
i
d
C
p
t
s
,
n
e
t
,
t
r
a
i
n
e
d
}
,
m
i
d
C
p
t
s
=
F
i
n
d
D
i
v
i
s
i
o
n
s
E
x
a
c
t
[
$
C
P
t
s
N
u
m
]
〚
2
;
;
-
2
〛
/
/
{
1
-
#
,
#
}
.
{
t
r
a
i
n
i
n
g
D
a
t
a
@
"
s
t
a
r
t
"
,
t
r
a
i
n
i
n
g
D
a
t
a
@
"
e
n
d
"
}
&
/
/
N
;
n
e
t
=
M
o
d
u
l
e
[
{
c
u
r
v
e
n
e
t
}
,
c
u
r
v
e
n
e
t
=
N
e
t
R
e
p
l
a
c
e
P
a
r
t
[
c
u
r
v
e
P
r
o
t
o
t
y
p
e
,
{
"
b
a
s
i
s
"
b
a
s
i
s
N
e
t
[
$
s
a
m
p
l
e
N
u
m
,
{
$
C
P
t
s
N
u
m
,
$
b
s
D
e
g
r
e
e
,
$
b
s
K
n
o
t
}
]
,
{
"
m
i
d
C
p
t
s
"
,
"
A
r
r
a
y
"
}
m
i
d
C
p
t
s
,
"
s
t
a
r
t
"
{
$
c
u
r
v
e
N
u
m
,
$
e
m
b
e
d
d
e
d
D
i
m
}
}
]
;
N
e
t
G
r
a
p
h
[
"
c
u
r
v
e
"
c
u
r
v
e
n
e
t
,
"
s
u
r
f
a
c
e
"
s
u
r
f
a
c
e
M
a
t
c
h
N
e
t
,
{
"
c
u
r
v
e
"
"
s
u
r
f
a
c
e
"
N
e
t
P
o
r
t
[
"
f
i
t
g
o
o
d
n
e
s
s
"
]
}
]
]
;
O
f
f
[
N
e
t
T
r
a
i
n
:
:
n
o
v
a
l
i
d
a
t
i
o
n
]
;
t
r
a
i
n
e
d
=
N
e
t
T
r
a
i
n
[
n
e
t
,
{
t
r
a
i
n
i
n
g
D
a
t
a
}
,
A
l
l
,
L
o
s
s
F
u
n
c
t
i
o
n
"
f
i
t
g
o
o
d
n
e
s
s
"
,
B
a
t
c
h
S
i
z
e
1
,
T
i
m
e
G
o
a
l
Q
u
a
n
t
i
t
y
[
1
0
,
"
M
i
n
u
t
e
s
"
]
,
T
r
a
i
n
i
n
g
S
t
o
p
p
i
n
g
C
r
i
t
e
r
i
o
n
"
C
r
i
t
e
r
i
o
n
"
"
L
o
s
s
"
,
W
o
r
k
i
n
g
P
r
e
c
i
s
i
o
n
"
R
e
a
l
6
4
"
,
M
e
t
h
o
d
"
R
M
S
P
r
o
p
"
]
;
O
n
[
N
e
t
T
r
a
i
n
:
:
n
o
v
a
l
i
d
a
t
i
o
n
]
;
t
r
a
i
n
e
d
]
;
/
/
A
b
s
o
l
u
t
e
T
i
m
i
n
g
{
0
.
7
8
2
2
1
8
,
N
u
l
l
}
Mean fit-goodness per point:
n
n
R
e
s
u
l
t
[
"
R
o
u
n
d
L
o
s
s
"
]
$
c
u
r
v
e
N
u
m
$
s
a
m
p
l
e
N
u
m
0
.
0
0
2
4
3
1
3
We can see the result indeed fits well to the contour surface:
n
n
R
e
s
u
l
t
[
"
T
r
a
i
n
e
d
N
e
t
"
]
/
/
p
i
p
e
[
N
e
t
P
a
r
t
[
#
,
1
]
&
,
N
e
t
T
a
k
e
[
#
,
"
c
p
t
s
"
]
&
,
#
@
t
r
a
i
n
i
n
g
D
a
t
a
&
,
T
r
a
n
s
p
o
s
e
,
M
a
p
T
h
r
e
a
d
[
{
#
2
,
B
S
p
l
i
n
e
C
u
r
v
e
[
#
1
,
S
p
l
i
n
e
D
e
g
r
e
e
$
b
s
D
e
g
r
e
e
,
S
p
l
i
n
e
K
n
o
t
s
$
b
s
K
n
o
t
]
}
&
,
{
#
,
#
/
/
L
e
n
g
t
h
/
/
F
i
n
d
D
i
v
i
s
i
o
n
s
E
x
a
c
t
/
/
M
a
p
@
C
o
l
o
r
D
a
t
a
@
"
R
a
i
n
b
o
w
"
}
]
&
,
G
r
a
p
h
i
c
s
3
D
[
{
A
b
s
o
l
u
t
e
T
h
i
c
k
n
e
s
s
[
2
]
,
#
}
]
&
,
S
h
o
w
[
c
o
n
t
o
u
r
G
r
a
p
h
,
#
]
&
]
It takes two splines to make a ribbon
Last section gives us a convenient way to fit BSpline curve onto contour surface. And one pair of such curves
with sufficient close shape
will make a nice ribbon as tensor product
BSplineSurface
. (Please refer to
my last community post
.)
S
a
y
w
e
a
r
e
c
r
e
a
t
i
n
g
5
g
r
o
u
p
×
2
0
0
r
i
b
b
o
n
/
g
r
o
u
p
,
t
h
e
n
w
e
c
a
n
f
i
r
s
t
l
y
i
n
i
t
i
a
l
i
z
e
i
t
w
i
t
h
5
g
r
o
u
p
×
2
0
0
c
u
r
v
e
/
g
r
o
u
p
1
0
0
0
c
u
r
v
e
s
,
w
h
i
c
h
a
r
e
5
g
r
o
u
p
×
2
0
0
c
u
r
v
e
/
g
r
o
u
p
×
2
t
e
r
m
i
n
a
l
p
o
i
n
t
/
c
u
r
v
e
2
0
0
0
t
e
r
m
i
n
a
l
p
o
i
n
t
s
:
$
c
u
r
v
e
N
u
m
=
5
×
2
0
0
×
2
;
t
e
r
m
i
n
a
l
P
o
i
n
t
S
e
t
1
=
R
a
n
d
o
m
P
o
i
n
t
[
b
ℛ
,
{
5
,
2
0
0
,
2
}
]
;
G
r
a
p
h
i
c
s
3
D
[
{
A
b
s
o
l
u
t
e
P
o
i
n
t
S
i
z
e
[
1
]
,
P
o
i
n
t
@
F
l
a
t
t
e
n
[
t
e
r
m
i
n
a
l
P
o
i
n
t
S
e
t
1
,
2
]
}
,
I
m
a
g
e
S
i
z
e
S
m
a
l
l
]
For each terminal point
P
in
terminalPointSet1
, we look for its accompanying point
′
P
such that
′
P
∈
b
ℛ
∧
′
P
-
P
=
w
i
d
t
h
r
i
b
b
o
n
=
0
.
1
:
r
i
b
b
o
n
W
i
d
t
h
=
.
1
;
t
e
r
m
i
n
a
l
P
o
i
n
t
S
e
t
2
=
M
a
p
[
F
u
n
c
t
i
o
n
[
t
p
,
{
x
,
y
,
z
}
/
.
F
i
n
d
R
o
o
t
[
{
[
x
,
y
,
z
]
0
,
N
o
r
m
[
{
x
,
y
,
z
}
]
π
,
N
o
r
m
[
{
x
,
y
,
z
}
-
t
p
]
r
i
b
b
o
n
W
i
d
t
h
}
,
{
{
x
,
y
,
z
}
,
t
p
+
.
0
1
}
]
]
,
t
e
r
m
i
n
a
l
P
o
i
n
t
S
e
t
1
,
{
3
}
]
;
{
t
e
r
m
i
n
a
l
P
o
i
n
t
S
e
t
1
,
t
e
r
m
i
n
a
l
P
o
i
n
t
S
e
t
2
}
/
/
p
i
p
e
[
T
r
a
n
s
p
o
s
e
[
#
,
{
4
,
1
,
2
,
3
,
5
}
]
&
,
F
l
a
t
t
e
n
[
#
,
2
]
&
,
M
a
p
T
h
r
e
a
d
[
{
#
2
,
L
i
n
e
[
#
1
]
}
&
,
{
#
,
#
/
/
L
e
n
g
t
h
/
/
F
i
n
d
D
i
v
i
s
i
o
n
s
E
x
a
c
t
/
/
M
a
p
@
C
o
l
o
r
D
a
t
a
[
"
R
a
i
n
b
o
w
"
]
}
]
&
,
{
A
b
s
o
l
u
t
e
T
h
i
c
k
n
e
s
s
[
2
0
]
,
C
a
p
F
o
r
m
[
N
o
n
e
]
,
#
}
&
,
F
l
a
t
t
e
n
,
G
r
a
p
h
i
c
s
3
D
[
#
,
I
m
a
g
e
S
i
z
e
M
e
d
i
u
m
]
&
]
Then we combine both set into single one suitable for previous neural net:
t
e
r
m
i
n
a
l
P
o
i
n
t
S
e
t
=
{
t
e
r
m
i
n
a
l
P
o
i
n
t
S
e
t
1
,
t
e
r
m
i
n
a
l
P
o
i
n
t
S
e
t
2
}
/
/
T
r
a
n
s
p
o
s
e
[
#
,
{
3
,
1
,
2
,
4
,
5
}
]
&
/
/
F
l
a
t
t
e
n
[
#
,
2
]
&
/
/
T
r
a
n
s
p
o
s
e
;
t
e
r
m
i
n
a
l
P
o
i
n
t
S
e
t
/
/
D
i
m
e
n
s
i
o
n
s
{
2
,
2
0
0
0
,
3
}
H
e
r
e
t
h
e
d
i
m
e
n
s
i
o
n
i
s
c
h
a
n
g
e
d
f
r
o
m
2
c
u
r
v
e
/
r
i
b
b
o
n
,
5
g
r
o
u
p
,
2
0
0
r
i
b
b
o
n
/
g
r
o
u
p
,
2
t
e
r
m
i
n
a
l
p
o
i
n
t
/
c
u
r
v
e
,
3
d
i
m
e
n
s
i
o
n
/
p
o
i
n
t
t
o
5
g
r
o
u
p
,
2
0
0
r
i
b
b
o
n
/
g
r
o
u
p
,
2
c
u
r
v
e
/
r
i
b
b
o
n
,
2
t
e
r
m
i
n
a
l
p
o
i
n
t
/
c
u
r
v
e
,
3
d
i
m
e
n
s
i
o
n
/
p
o
i
n
t
t
o
5
g
r
o
u
p
×
2
0
0
r
i
b
b
o
n
/
g
r
o
u
p
×
2
c
u
r
v
e
/
r
i
b
b
o
n
=
2
0
0
0
c
u
r
v
e
,
2
t
e
r
m
i
n
a
l
p
o
i
n
t
/
c
u
r
v
e
,
3
d
i
m
e
n
s
i
o
n
/
p
o
i
n
t
t
o
2
t
e
r
m
i
n
a
l
p
o
i
n
t
/
c
u
r
v
e
,
2
0
0
0
c
u
r
v
e
,
3
d
i
m
e
n
s
i
o
n
/
p
o
i
n
t
,
w
h
i
c
h
f
i
t
s
t
h
e
r
e
q
u
i
r
e
d
d
a
t
a
s
h
a
p
e
2
×
c
×
d
f
o
r
t
h
e
t
r
a
i
n
i
n
g
d
a
t
a
o
f
t
h
e
f
i
n
a
l
n
e
u
r
a
l
n
e
t
i
n
l
a
s
t
s
e
c
t
i
o
n
.
A similar training process with sufficiently small learning rate (
∼
-
5
1
0
) should produce something like
$
b
s
D
e
g
r
e
e
=
3
;
$
C
P
t
s
N
u
m
=
4
;
$
b
s
K
n
o
t
=
{
C
o
n
s
t
a
n
t
A
r
r
a
y
[
0
,
$
b
s
D
e
g
r
e
e
]
,
R
a
n
g
e
[
$
C
P
t
s
N
u
m
-
$
b
s
D
e
g
r
e
e
+
1
]
/
/
R
e
s
c
a
l
e
,
C
o
n
s
t
a
n
t
A
r
r
a
y
[
1
,
$
b
s
D
e
g
r
e
e
]
}
/
/
F
l
a
t
t
e
n
;
r
e
s
u
l
t
F
o
r
R
i
b
b
o
n
s
=
r
e
s
u
l
t
f
o
r
r
i
b
b
o
n
s
H
e
a
d
:
L
i
s
t
D
i
m
e
n
s
i
o
n
s
:
{
2
0
0
0
,
4
,
3
}
B
y
t
e
c
o
u
n
t
:
1
9
2
2
1
6
;
w
h
i
c
h
h
a
s
a
s
h
a
p
e
a
s
2
0
0
0
c
u
r
v
e
,
4
c
o
n
t
r
o
l
p
o
i
n
t
/
c
u
r
v
e
,
3
d
i
m
e
n
s
i
o
n
/
p
o
i
n
t
.
Visualizations
As we mentioned before, ribbons are visualized as
BSplineSurface
:
r
e
s
u
l
t
F
o
r
R
i
b
b
o
n
s
/
/
p
i
p
e
(
*
p
a
r
t
i
t
i
o
n
c
o
n
t
r
o
l
-
p
o
i
n
t
s
e
t
i
n
t
o
g
r
o
u
p
s
a
n
d
r
i
b
b
o
n
s
:
*
)
A
r
r
a
y
R
e
s
h
a
p
e
[
#
,
{
5
,
2
0
0
,
2
,
4
,
3
}
]
&
,
p
i
p
e
[
b
r
a
n
c
h
S
e
q
[
I
d
e
n
t
i
t
y
,
(
*
c
o
m
p
u
t
e
d
i
s
t
a
n
c
e
o
f
t
h
e
2
c
t
r
l
-
p
o
i
n
t
s
s
e
t
o
f
t
h
e
2
e
d
g
e
-
c
u
r
v
e
s
o
f
t
h
e
s
a
m
e
r
i
b
b
o
n
:
*
)
M
a
p
[
p
i
p
e
[
{
1
,
-
1
}
.
#
&
,
M
a
p
@
N
o
r
m
,
T
o
t
a
l
,
#
<
5
&
]
,
#
,
{
2
}
]
&
]
,
(
*
s
e
l
e
c
t
r
i
b
b
o
n
s
w
i
t
h
s
u
f
f
i
c
i
e
n
t
l
y
n
a
r
r
o
w
w
i
d
t
h
:
*
)
P
i
c
k
]
,
M
a
p
@
p
i
p
e
[
(
*
v
i
s
u
a
l
i
z
e
a
s
i
n
g
l
e
g
r
o
u
p
:
*
)
M
a
p
[
(
*
v
i
s
u
a
l
i
z
e
a
s
i
n
g
l
e
r
i
b
b
o
n
:
*
)
B
S
p
l
i
n
e
S
u
r
f
a
c
e
[
#
,
S
p
l
i
n
e
D
e
g
r
e
e
{
A
u
t
o
m
a
t
i
c
,
$
b
s
D
e
g
r
e
e
}
,
S
p
l
i
n
e
K
n
o
t
s
{
A
u
t
o
m
a
t
i
c
,
$
b
s
K
n
o
t
}
]
&
]
]
,
(
*
p
l
a
c
e
w
h
e
r
e
t
h
e
s
t
y
l
i
n
g
h
a
p
p
e
n
s
:
*
)
E
d
g
e
F
o
r
m
[
]
,
T
o
o
n
S
h
a
d
i
n
g
,
,
,
#
&
,
G
r
a
p
h
i
c
s
3
D
[
#
,
L
i
g
h
t
i
n
g
"
N
e
u
t
r
a
l
"
,
B
o
x
e
d
F
a
l
s
e
,
V
i
e
w
V
e
c
t
o
r
{
{
-
2
8
.
5
,
-
1
2
.
5
,
5
}
,
{
0
,
0
,
-
0
.
2
}
}
,
V
i
e
w
V
e
r
t
i
c
a
l
{
-
0
.
4
2
,
0
.
2
1
,
0
.
8
8
}
]
&
Playing with the
different shadings
and
Lighting
etc. gives all kinds of interesting visualizations:
r
e
s
u
l
t
F
o
r
R
i
b
b
o
n
s
/
/
p
i
p
e
(
*
p
a
r
t
i
t
i
o
n
c
o
n
t
r
o
l
-
p
o
i
n
t
s
e
t
i
n
t
o
g
r
o
u
p
s
a
n
d
r
i
b
b
o
n
s
:
*
)
A
r
r
a
y
R
e
s
h
a
p
e
[
#
,
{
5
,
2
0
0
,
2
,
4
,
3
}
]
&
,
p
i
p
e
[
b
r
a
n
c
h
S
e
q
[
I
d
e
n
t
i
t
y
,
(
*
c
o
m
p
u
t
e
d
i
s
t
a
n
c
e
o
f
t
h
e
2
c
t
r
l
-
p
o
i
n
t
s
s
e
t
o
f
t
h
e
2
e
d
g
e
-
c
u
r
v
e
s
o
f
t
h
e
s
a
m
e
r
i
b
b
o
n
:
*
)
M
a
p
[
p
i
p
e
[
{
1
,
-
1
}
.
#
&
,
M
a
p
@
N
o
r
m
,
T
o
t
a
l
,
#
<
5
&
]
,
#
,
{
2
}
]
&
]
,
(
*
s
e
l
e
c
t
r
i
b
b
o
n
s
w
i
t
h
s
u
f
f
i
c
i
e
n
t
l
y
n
a
r
r
o
w
w
i
d
t
h
:
*
)
P
i
c
k
]
,
M
a
p
@
p
i
p
e
[
(
*
v
i
s
u
a
l
i
z
e
a
s
i
n
g
l
e
g
r
o
u
p
:
*
)
M
a
p
T
h
r
e
a
d
[
(
*
v
i
s
u
a
l
i
z
e
a
s
i
n
g
l
e
r
i
b
b
o
n
:
*
)
(
*
p
l
a
c
e
w
h
e
r
e
t
h
e
s
t
y
l
i
n
g
h
a
p
p
e
n
s
:
*
)
{
E
d
g
e
F
o
r
m
[
]
,
F
a
c
e
F
o
r
m
[
{
S
p
e
c
u
l
a
r
i
t
y
[
1
,
1
0
]
,
O
p
a
c
i
t
y
[
.
3
]
,
#
2
}
,
N
o
n
e
]
,
B
S
p
l
i
n
e
S
u
r
f
a
c
e
[
#
1
,
S
p
l
i
n
e
D
e
g
r
e
e
{
A
u
t
o
m
a
t
i
c
,
$
b
s
D
e
g
r
e
e
}
,
S
p
l
i
n
e
K
n
o
t
s
{
A
u
t
o
m
a
t
i
c
,
$
b
s
K
n
o
t
}
]
}
&
,
{
#
,
#
/
/
L
e
n
g
t
h
/
/
F
i
n
d
D
i
v
i
s
i
o
n
s
E
x
a
c
t
/
/
M
a
p
[
C
o
l
o
r
D
a
t
a
[
"
D
e
e
p
S
e
a
C
o
l
o
r
s
"
]
]
}
]
&
]
,
G
r
a
p
h
i
c
s
3
D
#
,
L
i
g
h
t
i
n
g
"
A
m
b
i
e
n
t
"
,
,
B
a
c
k
g
r
o
u
n
d
,
B
o
x
e
d
F
a
l
s
e
,
V
i
e
w
V
e
c
t
o
r
{
{
-
2
1
.
7
,
1
6
.
2
,
-
3
.
3
7
}
,
{
0
,
0
,
-
0
.
2
}
}
,
V
i
e
w
V
e
r
t
i
c
a
l
{
0
.
0
5
,
0
.
8
9
,
0
.
4
6
}
&
Or finner ribbons for
StippleShading
or
HalftoneShading
:
r
e
s
u
l
t
F
o
r
S
t
i
p
p
l
e
=
r
e
s
u
l
t
f
o
r
s
t
i
p
p
l
i
n
g
a
n
d
h
a
l
f
t