# modeling/src/maths/plane/fromNoisyPoints.js

``````const vec3 = require('../vec3')
const fromNormalAndPoint = require('./fromNormalAndPoint')

/**
* Create a best-fit plane from the given noisy vertices.
*
* NOTE: There are two possible orientations for every plane.
*       This function always produces positive orientations.
*
* See http://www.ilikebigbits.com for the original discussion
*
* @param {Plane} out - receiving plane
* @param {Array} vertices - list of vertices in any order or position
* @returns {Plane} out
* @alias module:modeling/maths/plane.fromNoisyPoints
*/
const fromNoisyPoints = (out, ...vertices) => {
out[0] = 0.0
out[1] = 0.0
out[2] = 0.0
out[3] = 0.0

// calculate the centroid of the vertices
// NOTE: out is the centriod
const n = vertices.length
vertices.forEach((v) => {
})
vec3.scale(out, out, 1.0 / n)

// Calculate full 3x3 covariance matrix, excluding symmetries
let xx = 0.0
let xy = 0.0
let xz = 0.0
let yy = 0.0
let yz = 0.0
let zz = 0.0

const vn = vec3.create()
vertices.forEach((v) => {
// NOTE: out is the centriod
vec3.subtract(vn, v, out)
xx += vn[0] * vn[0]
xy += vn[0] * vn[1]
xz += vn[0] * vn[2]
yy += vn[1] * vn[1]
yz += vn[1] * vn[2]
zz += vn[2] * vn[2]
})

xx /= n
xy /= n
xz /= n
yy /= n
yz /= n
zz /= n

// Calculate the smallest Eigenvector of the covariance matrix
// which becomes the plane normal

vn[0] = 0.0
vn[1] = 0.0
vn[2] = 0.0

// weighted directional vector
const wdv = vec3.create()

// X axis
let det = yy * zz - yz * yz
wdv[0] = det
wdv[1] = xz * yz - xy * zz
wdv[2] = xy * yz - xz * yy

let weight = det * det

// Y axis
det = xx * zz - xz * xz
wdv[0] = xz * yz - xy * zz
wdv[1] = det
wdv[2] = xy * xz - yz * xx

weight = det * det
if (vec3.dot(vn, wdv) < 0.0) {
weight = -weight
}

// Z axis
det = xx * yy - xy * xy
wdv[0] = xy * yz - xz * yy
wdv[1] = xy * xz - yz * xx
wdv[2] = det

weight = det * det
if (vec3.dot(vn, wdv) < 0.0) {
weight = -weight
}