9 changed files with 333 additions and 10 deletions
@ -0,0 +1,38 @@ |
|||
import torch |
|||
import torch.nn as nn |
|||
import torch.nn.functional as F |
|||
|
|||
class ANN_b_spline_Model(nn.Module): |
|||
def __init__(self,in_dim=25+8,l1=36,l2=36*2,l3=36*3,l4=36*4,l5=36*5,l6=36*6,l7=36*5,l8=36*4,out_dim=36*2): |
|||
super().__init__() |
|||
self.fc1=nn.Linear(in_dim,l1) |
|||
self.fc2=nn.Linear(l1,l2) |
|||
self.fc3=nn.Linear(l2,l3) |
|||
self.fc4=nn.Linear(l3,l4) |
|||
|
|||
self.fc5=nn.Linear(l4,l5) |
|||
self.fc6=nn.Linear(l5,l6) |
|||
self.fc7=nn.Linear(l6,l7) |
|||
self.fc8=nn.Linear(l7,l8) |
|||
|
|||
|
|||
self.out=nn.Linear(l8,out_dim) # -> 6*6*2 |
|||
|
|||
|
|||
def forward(self,x): |
|||
density = x[:25] |
|||
displace = x[25:] |
|||
|
|||
x = F.relu(self.fc1(x)) |
|||
x = F.relu(self.fc2(x)) |
|||
x = F.relu(self.fc3(x)) |
|||
x = F.relu(self.fc4(x)) |
|||
|
|||
x = F.relu(self.fc5(x)) |
|||
x = F.relu(self.fc6(x)) |
|||
x = F.relu(self.fc7(x)) |
|||
x = F.relu(self.fc8(x)) |
|||
|
|||
x = self.out(x) |
|||
|
|||
return x |
@ -0,0 +1,28 @@ |
|||
def BaseFunction(i, k, u, knot): |
|||
''' |
|||
Calculate base function using Cox-deBoor function. |
|||
:param i: index of base function |
|||
:param k: order (degree + 1) |
|||
:param u: parameter |
|||
:param knot: knot vector |
|||
:return: base function |
|||
''' |
|||
Nik_u = 0 |
|||
if k == 1: |
|||
if u >= knot[i] and u < knot[i + 1]: |
|||
Nik_u = 1.0 |
|||
else: |
|||
Nik_u = 0.0 |
|||
else: |
|||
length1 = knot[i + k - 1] - knot[i] |
|||
length2 = knot[i + k] - knot[i + 1] |
|||
if not length1 and not length2: |
|||
Nik_u = 0 |
|||
elif not length1: |
|||
Nik_u = (knot[i + k] - u) / length2 * BaseFunction(i + 1, k - 1, u, knot) |
|||
elif not length2: |
|||
Nik_u = (u - knot[i]) / length1 * BaseFunction(i, k - 1, u, knot) |
|||
else: |
|||
Nik_u = (u - knot[i]) / length1 * BaseFunction(i, k - 1, u, knot) + \ |
|||
(knot[i + k] - u) / length2 * BaseFunction(i + 1, k - 1, u, knot) |
|||
return Nik_u |
@ -0,0 +1,101 @@ |
|||
import utils.b_spline.BaseFunction as bf |
|||
import numpy as np |
|||
|
|||
|
|||
def curve_interpolation(D, N, k, param, knot): |
|||
''' |
|||
Given a set of N data points, D0, D1, ..., Dn and a degree k, |
|||
find a B-spline curve of degree k defined by N control points |
|||
that passes all data points in the given order. |
|||
:param D: data points (N x 2) |
|||
:param N: the number of data points |
|||
:param k: degree |
|||
:param param: parameters |
|||
:param knot: knot vector |
|||
:return: control points (N x 2) |
|||
''' |
|||
Nik = np.zeros((N, N)) |
|||
|
|||
for i in range(N): |
|||
for j in range(N): |
|||
Nik[i][j] = bf.BaseFunction(j, k+1, param[i], knot) |
|||
Nik[N-1][N-1] = 1 |
|||
print(Nik) |
|||
Nik_inv = np.linalg.inv(Nik) |
|||
print(Nik_inv) |
|||
P = [] |
|||
for i in range(len(D)): |
|||
P.append(np.dot(Nik_inv, D[i]).tolist()) |
|||
print(P) |
|||
return P |
|||
|
|||
|
|||
def curve_approximation(D, N, H, k, param, knot): |
|||
''' |
|||
Given a set of N data points, D0, D1, ..., Dn, a degree k, |
|||
and a number H, where N > H > k >= 1, find a B-spline curve |
|||
of degree k defined by H control points that satisfies the |
|||
following conditions: |
|||
1. this curve contains the first and last data points; |
|||
2. this curve approximates the data polygon in the sense |
|||
of least square; |
|||
:param D: data points (N x 2) |
|||
:param H: the number of control points |
|||
:param k: degree |
|||
:param param: parameters |
|||
:param knot: knot vector |
|||
:return: control points (H x 2) |
|||
''' |
|||
P = [] |
|||
if H >= N or H <= k: |
|||
print('Parameter H is out of range') |
|||
return P |
|||
|
|||
for idx in range(len(D)): |
|||
P_ = np.zeros((1, H)) |
|||
P_[0][0] = D[idx][0] |
|||
P_[0][H-1] = D[idx][N-1] |
|||
Qk = np.zeros((N - 2, 1)) |
|||
Nik = np.zeros((N, H)) |
|||
for i in range(N): |
|||
for j in range(H): |
|||
Nik[i][j] = bf.BaseFunction(j, k+1, param[i], knot) |
|||
# print(Nik) |
|||
|
|||
for j in range(1, N - 1): |
|||
Qk[j - 1] = D[idx][j] - Nik[j][0] * P_[0][0] - Nik[j][H - 1] * P_[0][H - 1] |
|||
|
|||
N_part = Nik[1: N - 1, 1: H - 1] |
|||
# print(N_part) |
|||
Q = np.dot(N_part.transpose(), Qk) |
|||
# print(Q) |
|||
M = np.dot(np.transpose(N_part), N_part) |
|||
P_[0][1:H - 1] = np.dot(np.linalg.inv(M), Q).transpose() |
|||
P.append(P_.tolist()[0]) |
|||
|
|||
return P |
|||
|
|||
|
|||
def curve(P, N, k, param, knot): |
|||
''' |
|||
Calculate B-spline curve. |
|||
:param P: Control points |
|||
:param N: the number of control points |
|||
:param k: degree |
|||
:param param: parameters |
|||
:param knot: knot vector |
|||
:return: data point on the b-spline curve |
|||
''' |
|||
Nik = np.zeros((len(param), N)) |
|||
|
|||
for i in range(len(param)): |
|||
for j in range(N): |
|||
Nik[i][j] = bf.BaseFunction(j, k+1, param[i], knot) |
|||
Nik[len(param)-1][N - 1] = 1 |
|||
# print(Nik) |
|||
# D = np.dot(Nik, P) |
|||
D = [] |
|||
for i in range(len(P)): |
|||
D.append(np.dot(Nik, P[i]).tolist()) |
|||
# print(D) |
|||
return D |
@ -0,0 +1,55 @@ |
|||
import numpy as np |
|||
import utils.b_spline.parameter_selection as ps |
|||
import utils.b_spline.bspline_curve as bc |
|||
|
|||
|
|||
def surface(P, p, q, piece_uv, knot_uv): |
|||
''' |
|||
Calculate points on the surface. |
|||
:param P: control points |
|||
:param p: degree of u direction (u) |
|||
:param q: degree of v direction (v) |
|||
:param piece_uv: the number of points on u/v direction |
|||
:return: data points on the surface |
|||
''' |
|||
P_X = P[0] |
|||
P_Y = P[1] |
|||
P_Z = P[2] |
|||
M = len(P_X) |
|||
N = len(P_X[0]) |
|||
|
|||
param_u = np.linspace(0, 1, piece_uv[0]) |
|||
param_v = np.linspace(0, 1, piece_uv[1]) |
|||
|
|||
Nik_u = np.zeros((piece_uv[0], M)).tolist() |
|||
Nik_v = np.zeros((piece_uv[1], N)).tolist() |
|||
|
|||
D_tmp = [np.zeros((piece_uv[0], N)).tolist(), |
|||
np.zeros((piece_uv[0], N)).tolist(), |
|||
np.zeros((piece_uv[0], N)).tolist()] |
|||
|
|||
knot_u = knot_uv[0] |
|||
for i in range(N): |
|||
P_control_X = [x[i] for x in P_X] |
|||
P_control_Y = [y[i] for y in P_Y] |
|||
P_control_Z = [z[i] for z in P_Z] |
|||
P_control = [P_control_X, P_control_Y, P_control_Z] |
|||
D_col = bc.curve(P_control, M, p, param_u, knot_u) |
|||
for j in range(len(D_col[0])): |
|||
D_tmp[0][j][i] = D_col[0][j] |
|||
D_tmp[1][j][i] = D_col[1][j] |
|||
D_tmp[2][j][i] = D_col[2][j] |
|||
|
|||
D = [np.zeros((piece_uv[0], piece_uv[1])).tolist(), |
|||
np.zeros((piece_uv[0], piece_uv[1])).tolist(), |
|||
np.zeros((piece_uv[0], piece_uv[1])).tolist()] |
|||
|
|||
knot_v = knot_uv[1] |
|||
for i in range(piece_uv[0]): |
|||
P_control = [D_tmp[0][i], D_tmp[1][i], D_tmp[2][i]] |
|||
D_ = bc.curve(P_control, N, q, param_v, knot_v) |
|||
D[0][i] = D_[0] |
|||
D[1][i] = D_[1] |
|||
D[2][i] = D_[2] |
|||
|
|||
return D |
@ -0,0 +1,71 @@ |
|||
import numpy as np |
|||
|
|||
|
|||
def uniform_spaced(n): |
|||
''' |
|||
Calculate parameters using the uniform spaced method. |
|||
:param n: the number of the data points |
|||
:return: parameters |
|||
''' |
|||
parameters = np.linspace(0, 1, n) |
|||
return parameters |
|||
|
|||
|
|||
def chord_length(n, P): |
|||
''' |
|||
Calculate parameters using the chord length method. |
|||
:param n: the number of the data points |
|||
:param P: data points |
|||
:return: parameters |
|||
''' |
|||
parameters = np.zeros((1, n)) |
|||
for i in range(1, n): |
|||
dis = 0 |
|||
for j in range(len(P)): |
|||
dis = dis + (P[j][i] - P[j][i-1])**2 |
|||
dis = np.sqrt(dis) |
|||
parameters[0][i] = parameters[0][i-1] + dis |
|||
for i in range(1, n): |
|||
parameters[0][i] = parameters[0][i]/parameters[0][n-1] |
|||
return parameters[0] |
|||
|
|||
|
|||
def centripetal(n, P): |
|||
''' |
|||
Calculate parameters using the centripetal method. |
|||
:param n: the number of data points |
|||
:param P: data points |
|||
:return: parameters |
|||
''' |
|||
a = 0.5 |
|||
parameters = np.zeros((1, n)) |
|||
for i in range(1, n): |
|||
dis = 0 |
|||
for j in range(len(P)): |
|||
dis = dis + (P[j][i]-P[j][i-1])**2 |
|||
dis = np.sqrt(dis) |
|||
parameters[0][i] = parameters[0][i-1] + np.power(dis, a) |
|||
for i in range(1, n): |
|||
parameters[0][i] = parameters[0][i] / parameters[0][n-1] |
|||
return parameters[0] |
|||
|
|||
|
|||
def knot_vector(param, k, N): |
|||
''' |
|||
Generate knot vector. |
|||
:param param: parameters |
|||
:param k: degree |
|||
:param N: the number of data points |
|||
:return: knot vector |
|||
''' |
|||
m = N + k |
|||
knot = np.zeros((1, m+1)) |
|||
for i in range(k + 1): |
|||
knot[0][i] = 0 |
|||
for i in range(m - k, m + 1): |
|||
knot[0][i] = 1 |
|||
for i in range(k + 1, m - k): |
|||
for j in range(i - k, i): |
|||
knot[0][i] = knot[0][i] + param[j] |
|||
knot[0][i] = knot[0][i] / k |
|||
return knot[0] |
@ -0,0 +1,20 @@ |
|||
import utils.b_spline.parameter_selection as ps |
|||
import numpy as np |
|||
import utils.b_spline.bspline_curve as bc |
|||
import utils.b_spline.bspline_surface as bs |
|||
import matplotlib.pyplot as plt |
|||
from mpl_toolkits.mplot3d import Axes3D |
|||
import torch |
|||
|
|||
def surface_inter(P_control): |
|||
k = q = 2 |
|||
piece_uv = [6, 6] |
|||
knot_uv = [[0,0,0, 0.3,0.5,0.7, 1,1,1], [0,0,0, 0.3,0.5,0.7, 1,1,1]] |
|||
|
|||
P_control = torch.cat((P_control.reshape(2,6,6), torch.zeros(1, 6, 6)), dim=0) |
|||
P_control = P_control.detach().numpy().tolist() |
|||
|
|||
P_piece = bs.surface(P_control, k, q, piece_uv, knot_uv) |
|||
P_piece = torch.Tensor(P_piece)[:2,:,:].permute(1,2,0).reshape(72) |
|||
|
|||
return P_piece |
Loading…
Reference in new issue