class BSplineCurve {
constructor(controlPoints, degree, knotVector = null) {
this.controlPoints = controlPoints;
this.degree = degree;
this.n = controlPoints.length - 1; // Son kontrol noktası indeksi
// Knot vector otomatik oluştur (uniform/clamped)
if (knotVector === null) {
this.knotVector = this.createClampedKnotVector();
} else {
this.knotVector = knotVector;
}
this.m = this.knotVector.length - 1; // Son knot indeksi
}
createClampedKnotVector() {
const knots = [];
const k = this.degree;
const n = this.n;
// Başlangıç: k+1 tane 0
for (let i = 0; i <= k; i++) {
knots.push(0);
}
// Orta kısım: uniform spacing
for (let i = 1; i < n - k + 1; i++) {
knots.push(i / (n - k + 1));
}
// Son: k+1 tane 1
for (let i = 0; i <= k; i++) {
knots.push(1);
}
return knots;
}
// De Boor algoritması ile değerlendirme
evaluate(t) {
// Knot span bulma
const span = this.findSpan(t);
// De Boor algoritması
const points = [];
for (let i = 0; i <= this.degree; i++) {
points.push({ ...this.controlPoints[span - this.degree + i] });
}
for (let r = 1; r <= this.degree; r++) {
for (let i = this.degree; i >= r; i--) {
const alpha = this.calculateAlpha(span, i, r, t);
points[i] = {
x: (1 - alpha) * points[i-1].x + alpha * points[i].x,
y: (1 - alpha) * points[i-1].y + alpha * points[i].y,
z: (1 - alpha) * points[i-1].z + alpha * points[i].z
};
}
}
return points[this.degree];
}
findSpan(t) {
const n = this.n;
const k = this.degree;
// Edge cases
if (t >= this.knotVector[n + 1]) return n;
if (t <= this.knotVector[k]) return k;
// Binary search
let low = k;
let high = n + 1;
let mid = Math.floor((low + high) / 2);
while (t < this.knotVector[mid] || t >= this.knotVector[mid + 1]) {
if (t < this.knotVector[mid]) {
high = mid;
} else {
low = mid;
}
mid = Math.floor((low + high) / 2);
}
return mid;
}
calculateAlpha(span, i, r, t) {
const u = this.knotVector;
const denominator = u[span + i - r + 1] - u[span + i - this.degree];
if (Math.abs(denominator) < 1e-10) return 0;
return (t - u[span + i - this.degree]) / denominator;
}
// B-spline baz fonksiyonu hesaplama (Cox-de Boor formula)
basisFunction(i, k, t) {
const u = this.knotVector;
if (k === 0) {
return (u[i] <= t && t < u[i + 1]) ? 1 : 0;
}
let left = 0, right = 0;
if (u[i + k] !== u[i]) {
left = (t - u[i]) / (u[i + k] - u[i]) * this.basisFunction(i, k - 1, t);
}
if (u[i + k + 1] !== u[i + 1]) {
right = (u[i + k + 1] - t) / (u[i + k + 1] - u[i + 1]) * this.basisFunction(i + 1, k - 1, t);
}
return left + right;
}
// Türev hesaplama
derivative(order = 1) {
if (order <= 0) return this;
if (order > this.degree) return null;
const newDegree = this.degree - order;
const newControlPoints = [];
// Recursive türev hesaplama
let currentPoints = [...this.controlPoints];
let currentKnots = [...this.knotVector];
let currentDegree = this.degree;
for (let derivOrder = 1; derivOrder <= order; derivOrder++) {
const tempPoints = [];
for (let i = 0; i <= this.n - derivOrder; i++) {
const denominator = currentKnots[i + currentDegree + 1] - currentKnots[i + derivOrder];
if (Math.abs(denominator) > 1e-10) {
const factor = currentDegree / denominator;
tempPoints.push({
x: factor * (currentPoints[i + 1].x - currentPoints[i].x),
y: factor * (currentPoints[i + 1].y - currentPoints[i].y),
z: factor * (currentPoints[i + 1].z - currentPoints[i].z)
});
} else {
tempPoints.push({ x: 0, y: 0, z: 0 });
}
}
currentPoints = tempPoints;
currentDegree -= 1;
}
return new BSplineCurve(currentPoints, newDegree,
this.knotVector.slice(order, -order));
}
}
// NURBS Curve (Rational B-Spline)
class NURBSCurve extends BSplineCurve {
constructor(controlPoints, degree, weights, knotVector = null) {
super(controlPoints, degree, knotVector);
this.weights = weights || new Array(controlPoints.length).fill(1);
}
evaluate(t) {
// Homojen koordinatlar
const homogeneousPoints = this.controlPoints.map((point, i) => ({
x: point.x * this.weights[i],
y: point.y * this.weights[i],
z: point.z * this.weights[i],
w: this.weights[i]
}));
// B-spline evaluation with homogeneous coordinates
const tempCurve = new BSplineCurve(homogeneousPoints, this.degree, this.knotVector);
const homogeneousResult = tempCurve.evaluate(t);
// Perspective division
if (Math.abs(homogeneousResult.w) < 1e-10) {
throw new Error("Division by zero in NURBS evaluation");
}
return {
x: homogeneousResult.x / homogeneousResult.w,
y: homogeneousResult.y / homogeneousResult.w,
z: homogeneousResult.z / homogeneousResult.w
};
}
// Ağırlık değiştirme
setWeight(index, weight) {
if (index >= 0 && index < this.weights.length) {
this.weights[index] = weight;
}
}
// Rasyonel eğri özellikleri
isRational() {
return !this.weights.every(w => Math.abs(w - 1) < 1e-10);
}
// Perspektif projektif dönüşümler
applyProjectiveTransform(matrix4x4) {
// 4x4 homojen transformation matrix
const newPoints = [];
const newWeights = [];
for (let i = 0; i < this.controlPoints.length; i++) {
const p = this.controlPoints[i];
const w = this.weights[i];
// Homojen koordinatlara çevir
const homogeneous = [p.x * w, p.y * w, p.z * w, w];
// Matrix çarpımı
const transformed = [0, 0, 0, 0];
for (let row = 0; row < 4; row++) {
for (let col = 0; col < 4; col++) {
transformed[row] += matrix4x4[row][col] * homogeneous[col];
}
}
// Geri dönüştür
newWeights.push(transformed[3]);
if (Math.abs(transformed[3]) > 1e-10) {
newPoints.push({
x: transformed[0] / transformed[3],
y: transformed[1] / transformed[3],
z: transformed[2] / transformed[3]
});
} else {
newPoints.push({ x: 0, y: 0, z: 0 });
}
}
return new NURBSCurve(newPoints, this.degree, newWeights, this.knotVector);
}
}
// Örnek kullanım
const bsplinePoints = [
{ x: 0, y: 0, z: 0 },
{ x: 1, y: 2, z: 0 },
{ x: 3, y: 3, z: 1 },
{ x: 5, y: 1, z: 1 },
{ x: 6, y: 0, z: 0 }
];
// Kübik B-spline
const bspline = new BSplineCurve(bsplinePoints, 3);
console.log("B-spline t=0.5:", bspline.evaluate(0.5));
// NURBS eğri (ağırlıklı)
const weights = [1, 2, 1, 2, 1]; // Orta noktalar daha ağırlıklı
const nurbs = new NURBSCurve(bsplinePoints, 3, weights);
console.log("NURBS t=0.5:", nurbs.evaluate(0.5));
// Türev hesaplama
const derivative = bspline.derivative(1);
console.log("B-spline türev t=0.5:", derivative.evaluate(0.5));
| Özellik |
Bézier |
B-Spline |
NURBS |
| Kontrol türü |
Global |
Yerel |
Yerel + ağırlıklı |
| Interpolasyon |
Sadece uç noktalar |
Hiçbiri (genel) |
Hiçbiri (genel) |
| Geometrik dönüşümler |
Afin |
Afin |
Projektif |
| Konik kesitler |
Yaklaşık |
Yaklaşık |
Tam |
| Endüstriyel kullanım |
Grafik tasarım |
CAD/CAM |
Havacılık, otomotiv |
NURBS, çember, elips, hiperbol ve parabeller gibi konik kesitleri tam olarak temsil edebilen tek eğri türüdür.
Bu özellik, havacılık ve otomotiv endüstrilerinde kritik öneme sahiptir.
Knot Vector Stratejileri:
• Uniform: Eşit aralıklı knot'lar
• Non-uniform: Değişken aralıklı knot'lar
• Clamped: Uç noktalarda çokluk
• Periodic: Döngüsel eğriler için
• Adaptive: Eğrilik tabanlı knot yerleştirme
Performans İpucu: Gerçek zamanlı uygulamalarda knot span bulma işlemini optimize etmek için binary search yerine lookup table kullanabilirsiniz.
NURBS Dikkat: Ağırlık değerleri sıfıra yaklaştığında sayısal kararsızlık oluşabilir. Minimum ağırlık threshold'u belirleyin.
Geometrik Modelleme Yolculuğunuzun Başlangıcı
Bu kapsamlı rehberde uygulamalı geometrinin temel yapı taşlarını keşfettiniz.
Afin uzaylardan NURBS eğrilerine kadar uzanan bu yolculuk, modern bilgisayar grafiklerinin
ve CAD sistemlerinin matematiksel temellerini ortaya koymuştur.
| Yöntem |
Karmaşıklık |
Esneklik |
Uygulama Alanı |
| Lineer İnterpolasyon |
⭐ |
⭐ |
Basit animasyonlar |
| Polinom İnterpolasyon |
⭐⭐ |
⭐⭐ |
Bilimsel modelleme |
| Hermite Eğrileri |
⭐⭐⭐ |
⭐⭐⭐ |
Animasyon yolları |
| Spline Eğrileri |
⭐⭐⭐⭐ |
⭐⭐⭐⭐ |
CAD tasarım |
| Bézier Eğrileri |
⭐⭐⭐ |
⭐⭐⭐⭐ |
Grafik tasarım |
| NURBS |
⭐⭐⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
Endüstriyel tasarım |
Yüzey Modelleme: Bézier yüzeyleri, B-spline yüzeyleri, NURBS yüzeyleri
Solid Modelleme: Boolean işlemler, CSG, boundary representation
Mesh İşleme: Subdivision surfaces, mesh smoothing, remeshing
Diferansiyel Geometri: Eğrilik analizi, geodezikler, minimal yüzeyler
Hesaplamalı Geometri: Voronoi diyagramları, Delaunay triangulation
"Geometri = Sanat + Matematik + Mühendislik"
- Modern tasarımın evrensel dili