Skip to content

Instantly share code, notes, and snippets.

@dribnet
Last active September 30, 2020 10:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dribnet/b0a6a211702c53ad9b371f820cac377b to your computer and use it in GitHub Desktop.
Save dribnet/b0a6a211702c53ad9b371f820cac377b to your computer and use it in GitHub Desktop.
new face mapping assignment prototype
license: mit
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// other variables can be in here too
// these control the colors used
//COLOURS
const white = [225, 225, 225];
const black = [0, 0, 0];
const lightBlack = [40, 40, 40];
//FACE COLOURS
const face1Main = "#ded1ca";
const face1Detail = "#c7b2a7";
const face2Main = "#c7ad9d";
const face2Detail = "#9c8373";
const face3Main = "#ab8a72";
const face3Detail = "#8a6d5b";
const face4Main = "#856a59";
const face4Detail = "#594336";
const face5Main = "#594844";
const face5Detail = "#4a342c";
//EAR COLOURS
const earGrey = "#abaaa9";
const earLightBlonde = "#eddfc7";
const earDarkBlonde = "#d1ab7d";
const earRed = "#963917";
const earLightBrown = "#9c785a";
const earDarkBrown = "#572e1a";
const earBlack = "#210c02";
//EYES
const eyeDBrown = "#38220a";
const eyeLBrown = "#b58c6e";
const eyeGreen = "#739c60";
const eyeBlue = "#6591b5";
function Face() {
// these are state variables for a face
// (your variables may be different)
this.tilt_value = 0; // range is -30 to 30
this.face_width = 0;
this.face_colour = 1; // range 1-5
this.hair_style = 1; // hair length in middle of ear
this.ear_colour = 1; // 1= grey, 2 = lightBlonde, 3 = darkBlonde, 4 = red, 5 = lightBrown, 6= darkBrown, 7 = black;
this.eye_colour = 1; // 1= dark brown, 2 = light brown, 3 = green, 4 = blue
this.blush_value = 1; // 1 = true, 2 = false;
/*
* Draw a face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
// SETUP
rectMode(CENTER);
ellipseMode(CENTER);
noStroke();
rotate(this.tilt_value);
//******** POSITIONS ********/
let left_eyebrow1 = positions.left_eyebrow[0];
let right_eyebrow5 = positions.right_eyebrow[4];
let left_eye = positions.left_eye[5];
let right_eye = positions.right_eye[5];
let bottom_lip = positions.bottom_lip[9];
let top_lip1 = positions.top_lip[0];
let top_lip2 = positions.top_lip[1];
let top_lip3 = positions.top_lip[2];
let top_lip4 = positions.top_lip[3];
let top_lip5 = positions.top_lip[4];
let top_lip6 = positions.top_lip[5];
let top_lip7 = positions.top_lip[6];
let top_lip8 = positions.top_lip[7];
let top_lip9 = positions.top_lip[8];
let top_lip10 = positions.top_lip[9];
let top_lip11 = positions.top_lip[10];
let top_lip12 = positions.top_lip[11];
let nose_bridge4 = positions.nose_bridge[3];
//***** HEAD ******/
//Colours
let faceColour = face1Main;
let detailColour = face1Detail;
let hairColour = earBlack;
//Facial Colouring
if(this.face_colour == 1){
faceColour = face1Main;
detailColour = face1Detail;
}
else if(this.face_colour == 2){
faceColour = face2Main;
detailColour = face2Detail;
}
else if(this.face_colour == 3){
faceColour = face3Main;
detailColour = face3Detail;
}
else if(this.face_colour == 4){
faceColour = face4Main;
detailColour = face4Detail;
}
else if(this.face_colour == 5){
faceColour = face5Main;
detailColour = face5Detail;
}
//Ear/Hair Colouring
if(this.ear_colour == 1){
hairColour = earGrey;
}
else if(this.ear_colour == 2){
hairColour = earLightBlonde;
}
else if(this.ear_colour == 3){
hairColour = earDarkBlonde;
}
else if(this.ear_colour == 4){
hairColour = earRed;
}
else if(this.ear_colour == 5){
hairColour = earLightBrown;
}
else if(this.ear_colour == 6){
hairColour = earDarkBrown;
}
else if(this.ear_colour == 7){
hairColour = earBlack;
}
//Ears
this.drawEars(detailColour, hairColour, left_eyebrow1[0], right_eyebrow5[0], left_eyebrow1[1], right_eyebrow5[1]);
//Hair in the Middle
this.drawHair(hairColour, this.hair_style);
//Face
fill(faceColour);
rect(0,0,this.face_width,4, 20);
//******** EYES - LEFT EYE, RIGHT EYE ******/
if(this.eye_colour == 1){
this.drawEyes(detailColour, eyeDBrown, left_eye[0], left_eye[1], right_eye[0], right_eye[1]);
}
else if(this.eye_colour == 2){
this.drawEyes(detailColour, eyeLBrown, left_eye[0], left_eye[1], right_eye[0], right_eye[1]);
}
else if(this.eye_colour == 3){
this.drawEyes(detailColour, eyeGreen, left_eye[0], left_eye[1], right_eye[0], right_eye[1]);
}
else if(this.eye_colour == 4){
this.drawEyes(detailColour, eyeBlue, left_eye[0], left_eye[1], right_eye[0], right_eye[1]);
}
//******** MOUTH - BOTTOM LIP, TOP LIP & NOSE - NOSE TIP, NOSE BRIDGE*********/
//OuterMouth
fill(detailColour);
ellipse(top_lip4[0], top_lip4[1]+0.2, 2.3, 2);
//BottomLip
fill("#ad8e8e");
beginShape();
curveVertex(top_lip2[0], top_lip2[1]);
curveVertex(top_lip4[0], top_lip4[1]);
curveVertex(top_lip6[0], top_lip6[1]);
curveVertex(bottom_lip[0] + 0.4, bottom_lip[1]);
curveVertex(bottom_lip[0], bottom_lip[1]);
curveVertex(bottom_lip[0] - 0.4, bottom_lip[1]);
endShape(CLOSE);
stroke(black);
strokeCap(SQUARE);
strokeWeight(0.08);
noFill();
beginShape();
curveVertex(top_lip2[0], top_lip2[1] + 0.05);
curveVertex(top_lip2[0], top_lip2[1]+ 0.05);
curveVertex(bottom_lip[0] - 0.4, bottom_lip[1]-0.05);
curveVertex(bottom_lip[0], bottom_lip[1]);
curveVertex(bottom_lip[0] + 0.4, bottom_lip[1]-0.05);
curveVertex(top_lip6[0], top_lip6[1]+0.05);
curveVertex(top_lip6[0], top_lip6[1]+0.05);
endShape();
noStroke();
//TopLip
fill(black);
beginShape();
curveVertex(top_lip1[0], top_lip1[1]);
curveVertex(top_lip2[0], top_lip2[1]);
curveVertex(top_lip3[0], top_lip3[1]);
curveVertex(top_lip4[0], top_lip4[1]);
curveVertex(top_lip5[0], top_lip5[1]);
curveVertex(top_lip6[0], top_lip6[1]);
curveVertex(top_lip7[0], top_lip7[1]);
curveVertex(top_lip8[0], top_lip8[1]);
curveVertex(top_lip9[0], top_lip9[1]);
curveVertex(top_lip10[0], top_lip10[1]);
curveVertex(top_lip11[0], top_lip11[1]);
curveVertex(top_lip12[0], top_lip12[1]);
curveVertex(top_lip1[0], top_lip1[1]);
curveVertex(top_lip2[0], top_lip2[1]);
endShape();
//Blush
if(this.blush_value == 1){
fill(255, 48, 93, 75);
ellipse(top_lip1[0]-0.25, top_lip1[1], 0.75);
ellipse(top_lip7[0] + 0.25, top_lip7[1], 0.75);
}
//Nose
stroke(black);
strokeWeight(0.15);
strokeCap(SQUARE);
noFill();
line(nose_bridge4[0], nose_bridge4[1], top_lip4[0], top_lip4[1]);
noStroke();
fill(black);
ellipse(nose_bridge4[0], nose_bridge4[1], 0.6, 0.4);
fill(30);
ellipse(nose_bridge4[0], nose_bridge4[1], 0.3, 0.2);
fill(175);
ellipse(nose_bridge4[0]+0.125, nose_bridge4[1]-0.1, 0.075, 0.05);
}
//****** OBJECTS FUNCTIONS FOR FACIAL FEATURES ****/
//Ears
this.drawEars = function(detail, hair, lx, rx, ly, ry){
fill(detail);
ellipse(lx+0.25, ly, 2, 2);
ellipse(rx-0.25, ry, 2, 2);
//left_ear floofs
beginShape();
vertex(lx, ly);
vertex(lx, ly-0.7);
vertex(lx-1, ly-0.6);
endShape(CLOSE);
beginShape();
vertex(lx, ry-0.3);
vertex(lx , ry-0.9);
vertex(lx-1, ry-0.9);
endShape(CLOSE);
//right_ear floofs
beginShape();
vertex(rx, ry);
vertex(rx, ry-0.7);
vertex(rx+1, ry-0.6);
endShape(CLOSE)
beginShape();
vertex(rx, ry-0.3);
vertex(rx , ry-0.95);
vertex(rx+0.75, ry-0.9);
endShape(CLOSE);
fill(hair);
ellipse(lx+0.25, ly, 1.5, 1.5);
ellipse(rx-0.25, ry, 1.5, 1.5);
}
//Eyes
this.drawEyes = function(detail, eye, lx, ly, rx, ry){
//EYE PATCHES
//LeftEyePatch
fill(detail);
beginShape();
curveVertex(lx + 0.65, ly);
curveVertex(lx + 0.65, ly + 0.3);
curveVertex(lx - 0.2, ly + 0.8);
curveVertex(lx - 0.7, ly + 0.3);
curveVertex(lx - 0.3, ly - 0.5);
curveVertex(lx + 0.5, ly - 0.5);
endShape(CLOSE);
//RightEyePatch
beginShape();
curveVertex(rx - 0.65, ry);
curveVertex(rx - 0.65, ry + 0.3);
curveVertex(rx + 0.2, ry + 0.8);
curveVertex(rx + 0.7, ry + 0.3);
curveVertex(rx + 0.3, ry - 0.5);
curveVertex(rx - 0.5, ry - 0.5);
endShape(CLOSE);
//EyeBalls
fill(eye);
ellipse(lx, ly, 0.55, 0.55);
ellipse(rx, ry, 0.55, 0.55);
fill(100);
ellipse(lx, ly, 0.48, 0.48);
ellipse(rx, ry, 0.48, 0.48);
fill(black);
ellipse(lx, ly, 0.4, 0.4);
ellipse(rx, ry, 0.4, 0.4);
fill(175);
ellipse(lx +0.075, ly-0.075, 0.08, 0.05);
ellipse(rx +0.075, ry-0.075, 0.08, 0.05);
}
//Hair
this.drawHair = function(hair, length){
fill(hair);
beginShape();
vertex(-0.25, -1.5);
vertex(0.25, -1.5);
vertex(0, -2*length);
endShape(CLOSE);
beginShape();
vertex(-0.22, -1.5);
vertex(0.22, -1.5);
vertex(-0.25 - (0.1*length), -1.85*length);
endShape(CLOSE);
beginShape();
vertex(-0.2, -1.5);
vertex(0.2, -1.5);
vertex(0.25 + (0.1*length), -1.8*length);
endShape(CLOSE);
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
//this.eye_value = int(map(settings[0], 0, 100, 2, 3));
//TiltValue
this.tilt_value = map(settings[0], 0, 100, -30, 30);
//FACE SHAPE
this.face_width = map(settings[1], 0, 100, 3.6, 4);
//FACE COLOUR
this.face_colour = int(map(settings[2], 0, 100, 1, 5));
//EARS
this.hair_style = map(settings[3], 0, 100, 1, 1.2);
//EAR COLOUR
this.ear_colour = int(map(settings[4], 0, 100, 1, 7));
//EYE COLOUR - brown, light brown, green, blue
this.eye_colour = int(map(settings[5], 0, 100, 1, 4));
// BLUSH
this.blush_value = int(map(settings[6], 0, 100, 1, 2));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(7);
settings[0] = map(this.tilt_value, -30, 30, 0, 100);
settings[1] = map(this.face_width, 3.6, 4, 0, 100);
settings[2] = map(this.face_colour, 1, 5, 0, 100);
settings[3] = map(this.hair_style, 1, 1.2, 0, 100);
settings[4] = map(this.ear_colour, 1, 7, 0, 100);
settings[5] = map(this.eye_colour, 1, 4, 0, 100);
settings[6] = map(this.blush_value, 1, 2, 0, 100);
return settings;
}
}
//given an array of [x,y] points, return the average
function average_point(list){
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for(var i = 0; i<list.length; i++){
sum_x += list[i][0];
sum_y += list[i][1];
num_points +- 1;
}
return [sum_x / num_points, sum_y /num_points];
}
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/seedrandom/2.4.3/seedrandom.min.js"></script>
<script src="https://d3js.org/d3-random.v1.min.js"></script>
<script src="z_clmtrackr.js"></script>
<script src="z_model_pca_20_svm.js"></script>
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="z_focused_random.js"></script>
<script language="javascript" type="text/javascript" src="z_face_system.js"></script>
<script language="javascript" type="text/javascript" src="z_kdTree.js"></script>
<script language="javascript" type="text/javascript" src="z_face-api.js"></script>
<script language="javascript" type="text/javascript" src="z_training_images.js"></script>
<script language="javascript" type="text/javascript" src="z_testing_images.js"></script>
<script language="javascript" type="text/javascript" src="face.js"></script>
<script language="javascript" type="text/javascript" src="system_runner.js"></script>
<style>
body { padding: 0; margin: 0; }
.inner { position: absolute; }
#controls {
font: 300 12px "Helvetica Neue";
padding: 5;
margin: 5;
background: #f0f0f0;
opacity: 0.0;
-webkit-transition: opacity 0.2s ease;
-moz-transition: opacity 0.2s ease;
-o-transition: opacity 0.2s ease;
-ms-transition: opacity 0.2s ease;
}
#controls:hover { opacity: 0.9; }
</style>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner" id="controls" height="500">
<table>
<tr>
<td>setting 1</td>
<td id="slider1Container"></td>
</tr>
<tr>
<td>setting 2</td>
<td id="slider2Container"></td>
</tr>
<tr>
<td>setting 3</td>
<td id="slider3Container"></td>
</tr>
<tr>
<td>setting 4</td>
<td id="slider4Container"></td>
</tr>
<tr>
<td>setting 5</td>
<td id="slider5Container"></td>
</tr>
<tr>
<td>setting 6</td>
<td id="slider6Container"></td>
</tr>
<tr>
<td>setting 7</td>
<td id="slider7Container"></td>
</tr>
<tr>
<td>setting 8</td>
<td id="slider8Container"></td>
</tr>
<tr>
<td>setting 9</td>
<td id="slider9Container"></td>
</tr>
<tr>
<td>setting 10</td>
<td id="slider10Container"></td>
</tr>
<tr>
<td>setting 11</td>
<td id="slider11Container"></td>
</tr>
<tr>
<td>setting 12</td>
<td id="slider12Container"></td>
</tr>
<tr>
</tr>
<tr>
<td>show target</td>
<td id="sliderTintContainer"></td>
</tr>
<tr>
<td>Draw function</td>
<td id="selector1Container"></td>
</tr>
<tr>
<td>Face Draw</td>
<td id="checkbox1Container"></td>
</tr>
<tr>
<td>Face Targets</td>
<td id="checkbox2Container"></td>
</tr>
<tr>
<td>Face Points</td>
<td id="checkbox3Container"></td>
</tr>
<tr>
<td></td>
<td id="button1Container"></td>
</tr>
<tr>
<td></td>
<td id="button2Container"></td>
</tr>
<tr>
<td></td>
<td id="button3Container"></td>
</tr>
<tr>
<td></td>
<td id="button4Container"></td>
</tr>
</table>
</div>
<div>
<div id="canvasContainer"></div>
<a href="face.js">face code</a><br>
<a href="sketch.html">sketches</a>
</div>
</div>
<pre>
<p id="output">
</p>
</pre>
</body>
[
"williams.jpg",
"oscar_selfie.jpg"
]
<head>
<style> body {padding: 0; margin: 0;} </style>
</head>
<body style="background-color:white">
<img src="same_pose.jpg" width="960" height="500"/><br>
Same Pose
<hr>
<img src="same_subject.jpg" width="960" height="500"/><br>
Same Subject
<p>
<a href="index.html">program</a>
</body>
// recent work from my @VicUniWgtn 3rd year media design students that combines @nulhom's dlib face library with @p5xjs
var canvasWidth = 960;
var canvasHeight = 500;
var button;
var curRandomSeed;
var mainFace;
var faceImages = [];
var curFaceIndex = 0;
var curTrainIndex = 0;
var curValidIndex = 0;
var main_canvas;
var video_buffer;
var faceSelector;
var drawFaceCheckbox;
var faceGuideCheckbox;
var facePointsCheckbox;
var sliders = [];
var NUM_SLIDERS = 12;
var sliderTint;
var trainDataKeys = []
var trainValues = {}
var validDataKeys = []
var faceMapping = null;
let model_loaded = false;
let faces_processing = false;
let faces_processed = false;
var sample_images;
var selfieData = []
var video_capture = null;
async function preload () {
sample_images = loadJSON('sample_images.json')
trainValues = loadJSON('training_values.json');
await faceapi.loadSsdMobilenetv1Model("./");
await faceapi.loadFaceLandmarkModel("./");
await faceapi.loadFaceRecognitionModel("./");
model_loaded = true;
}
var allEmbeddingsTree;
var allEmbeddings = [];
var embeddingDimensions;
var curNeighbors = [];
function squaredDistance(a, b) {
var sum = 0;
var length = 128;
for(var i=0; i<128; i++) {
var diff = a[i] - b[i];
sum += diff * diff;
}
// print(a.length,diff);
// print(sum, a==b);
return sum;
}
var haveStarted = false;
function setup () {
let keys = Object.keys(sample_images);
for (let i=0; i<keys.length; i++) {
let obj = {};
obj.url = sample_images[keys[i]];
selfieData.push(obj);
}
// create the drawing canvas, save the canvas element
main_canvas = createCanvas(canvasWidth, canvasHeight);
main_canvas.parent('canvasContainer');
curRandomSeed = int(focusedRandom(0, 100));
mainFace = new Face();
littleFace = new Face();
for(var i=0; i<selfieData.length; i++) {
var data = selfieData[i];
data.image = loadImage(data.url);
}
trainDataKeys = Object.keys(trainData);
for(var i=0; i<trainDataKeys.length; i++) {
var curKey = trainDataKeys[i];
var data = trainData[curKey];
var curEmbedding = data.embedding[0];
if(curEmbedding.length == 128) {
curEmbedding.push(curKey);
allEmbeddings.push(curEmbedding);
}
else {
print("rejected embedding ", curEmbedding.length, curEmbedding);
}
data.image = loadImage(data.url);
}
validDataKeys = Object.keys(validData);
for(var i=0; i<validDataKeys.length; i++) {
var curKey = validDataKeys[i];
var data = validData[curKey];
data.image = loadImage(data.url);
}
// print("Length: ", allEmbeddings.length);
// setup k-d tree
var N = allEmbeddings[0].length - 1;
embeddingDimensions = Array.apply(null, {length: N}).map(Number.call, Number);
// print(embeddingDimensions)
allEmbeddingsTree = new kdTree(allEmbeddings, squaredDistance, embeddingDimensions);
// print(allEmbeddingsTree)
faceSelector = createSelect();
faceSelector.option('Faces');
faceSelector.option('Train');
faceSelector.option('NearestNeighbors');
faceSelector.option('TrainingQuiz');
faceSelector.option('InterpolationQuiz');
faceSelector.option('Video');
faceSelector.value('Faces');
faceSelector.parent('selector1Container');
/* create the sliders */
for(i=1; i<=NUM_SLIDERS; i++) {
var slider = createSlider(0, 100, 50);
var parentStr = 'slider' + i + 'Container';
slider.parent(parentStr);
sliders.push(slider);
}
drawFaceCheckbox = createCheckbox('', true);
drawFaceCheckbox.parent('checkbox1Container');
faceGuideCheckbox = createCheckbox('', false);
faceGuideCheckbox.parent('checkbox2Container');
facePointsCheckbox = createCheckbox('', false);
facePointsCheckbox.parent('checkbox3Container');
sliderTint = createSlider(0, 100, 10);
sliderTint.parent("sliderTintContainer");
/* and the buttons */
var loadButton = createButton('load');
loadButton.mousePressed(loadCurrentSettings);
loadButton.parent('button1Container');
var interpButton = createButton('interpolate');
interpButton.mousePressed(interpolateCurrent);
interpButton.parent('button1Container');
var saveButton = createButton('save');
saveButton.mousePressed(saveCurrentSettings);
saveButton.parent('button2Container');
var getValuesButton = createButton('get values');
getValuesButton.mousePressed(getSingleJson);
getValuesButton.parent('button3Container');
var randButton = createButton('get all values');
randButton.mousePressed(getAllJson);
randButton.parent('button4Container');
updateSlidersForTraining();
// rotation in degrees
angleMode(DEGREES);
background(255);
fill(0);
textSize(50);
textAlign(CENTER);
text("(waiting for models to load...)", width/2, height/2);
haveStarted = true;
}
function saveCurrentSettings() {
var curKey = trainDataKeys[curTrainIndex];
obj = mainFace.getProperties();
trainValues[curKey] = obj;
// for(var i=0; i<obj.length; i++) {
// trainData[curKey][i] = obj[i];
// }
var text = select('#output');
text.html("Storing values for " + curKey);
// getAllJson();
}
function getSingleJson() {
obj = mainFace.getProperties();
var text = select('#output');
var json = JSON.stringify(obj, null, 2);
text.html(json)
}
function getAllJson() {
obj = trainValues;
var text = select('#output');
var json = JSON.stringify(obj, null, 2);
// alert(json);
text.html(json)
}
// global variables for colors
var bg_color1 = [50, 50, 50];
var lastSwapTime = 0;
var millisPerSwap = 5000;
function changeRandomSeed() {
curRandomSeed = curRandomSeed + 1;
lastSwapTime = millis();
}
function mouseClicked() {
// changeRandomSeed();
}
var quiz_done = true;
var guessed_answer = 0;
function num_dist(e1, e2) {
let dist = 0;
for(let i=0; i<e1.length; i++) {
print(i, e1[i], e2[i]);
dist = dist + Math.abs(e1[i] - e2[i]);
}
return dist;
}
var processing_vid_face = false;
var lastProcessedVidFace = null;
async function draw () {
if (!model_loaded) {
return;
}
if (!faces_processing) {
faces_processing = true;
background(255);
fill(0);
textSize(50);
textAlign(CENTER);
text("(processing faces...)", width/2, height/2);
for(var i=0; i<selfieData.length; i++) {
var data = selfieData[i];
let fullFaceDescriptions = await faceapi.detectAllFaces(data.image.canvas).withFaceLandmarks().withFaceDescriptors();
data.landmarks = get_landmarks(fullFaceDescriptions);
data.embedding = get_latents(fullFaceDescriptions);
}
// print("Some distances")
// var data = selfieData[0];
// for(var i=0; i<data.landmarks.length; i++) {
// for(var j=0; j<data.landmarks.length; j++) {
// print("dist ", i, "old to ", j, " new -> ", num_dist(data.embedding[i], data.latents[j]));
// }
// }
faces_processed = true;
return;
}
if(!faces_processed) {
return;
}
var mode = faceSelector.value();
if(millis() > lastSwapTime + millisPerSwap) {
lastSwapTime = millis();
// changeRandomSeed();
}
resetFocusedRandom(curRandomSeed);
noStroke();
var textDisplay = "unknown";
var params = [];
for(var i=0; i<NUM_SLIDERS; i++) {
params.push(sliders[i].value());
}
if (mode == 'Faces' || mode == 'FacePair' || mode == 'Train' || mode == 'Video') {
var do_train = (mode == 'Train');
var is_face = (mode == 'Faces');
var is_video = (mode == 'Video');
var show_face_guide = faceGuideCheckbox.checked();
var show_face_points = facePointsCheckbox.checked();
var do_draw_face = drawFaceCheckbox.checked();
if(do_train) {
// var keys = Object.keys(trainData);
var curKey = trainDataKeys[curTrainIndex];
var data = trainData[curKey];
}
else {
var data = selfieData[curFaceIndex];
}
const v_w = 640;
const v_h = 480;
const v_w_p = v_w / this._pixelDensity;
const v_h_p = v_h / this._pixelDensity;
// setup "video image" if in video mode
if (is_video) {
if (video_capture == null) {
video_capture = createCapture(VIDEO);
video_capture.size(canvasWidth, canvasHeight);
video_buffer = createGraphics(v_w, v_h);
return;
}
// print(processing_vid_face);
if(processing_vid_face == false) {
video_buffer.image(video_capture, 0, 0, v_w_p, v_h_p);
// print("grabbing video");
processing_vid_face = true;
lastProcessedVidFace = await faceapi.detectAllFaces(video_buffer.canvas).withFaceLandmarks().withFaceDescriptors();
processing_vid_face = false;
// print("grabbed video");
return;
}
if (lastProcessedVidFace == null) {
background(255);
fill(0);
textSize(50);
textAlign(CENTER);
text("(setting up camera...)", width/2, height/2);
return
}
data = {};
data["image"] = video_buffer;
data["landmarks"] = get_landmarks(lastProcessedVidFace);
data["embedding"] = get_latents(lastProcessedVidFace);
// print("Found faces: ", data.landmarks.length)
}
// we are not bailing, draw background
background(bg_color1);
// Displays the image at its actual size at point (0,0)
var img = data.image
if (is_face) {
x2 = 0;
y1 = 0;
x1 = 0;
var im_w = canvasWidth;
var im_h = canvasHeight;
var rect_w = canvasWidth;
var rect_h = canvasHeight;
image(img, x2, y1, im_w, im_h);
}
else if(is_video) {
// let vw = video_capture.elt.videoWidth;
// let vh = video_capture.elt.videoHeight;
// x2 = 0;
// y1 = 0;
// x1 = 0;
x1 = (canvasWidth - v_w) / 2.0;
x2 = x1;
y1 = (canvasHeight - v_h) / 2.0;
var im_w = v_w;
var im_h = v_h;
var rect_w = v_w;
var rect_h = v_h;
// print(im_w, im_h);
image(img, x2, y1, im_w, im_h, 0, 0, v_w_p, v_h_p);
}
else {
var x1 = (width/4-400/2);
var x2 = (3*width/4-400/2);
var y1 = (height/2-400/2);
var rect_w = 400;
var rect_h = 400;
var im_w = 400;
var im_h = 400;
image(img, x1, y1, 400, 400);
}
if(do_train) {
if (curKey in trainValues) {
fill(0, 200, 0);
}
else {
fill(200, 0, 0);
}
ellipse(x1+400/2, y1+400+15, 10, 10);
}
noStroke();
var curSliderTintValue = sliderTint.value();
var overlayAlpha = map(curSliderTintValue, 0, 100, 255, 0);
fill(bg_color1[0], bg_color1[1], bg_color1[2], overlayAlpha);
rect(x2, y1, rect_w, rect_h);
stroke(0);
fill(255);
for(var i=0; i<data.landmarks.length; i++) {
// get array of face marker positions [x, y] format
var positions = data.landmarks[i];
var shifted_positions = JSON.parse(JSON.stringify(positions))
var data_mean = [0.0, 0.0];
var data_scale = 1.0;
var data_angle = 0.0;
if ('transform' in positions) {
data_mean = positions.transform.center;
data_scale = positions.transform.scale;
data_angle = positions.transform.angle;
delete shifted_positions.transform
}
var scale_x = im_w / img.width;
var scale_y = im_h / img.height;
push();
translate(x1, y1)
translate(scale_x*data_mean[0], scale_y*data_mean[1]);
scale(scale_x*data_scale, scale_y*data_scale);
rotate(degrees(data_angle));
stroke(0);
fill(255);
strokeWeight(1/data_scale);
Object.keys(positions).forEach(function(key) {
if (key=='transform') {
return;
}
var curSection = positions[key];
var shiftedSection = shifted_positions[key];
for (var i=0; i<curSection.length; i++) {
var cur_x = curSection[i][0];
var cur_y = curSection[i][1];
if (show_face_points) {
ellipse(cur_x, cur_y, 5/data_scale, 5/data_scale);
}
// get ready for drawing the face
shiftedSection[i][0] = cur_x;
shiftedSection[i][1] = cur_y;
}
});
noFill();
if(show_face_guide) {
stroke(0, 0, 255);
ellipse(0, 0, 4, 4);
line(0, -2, 0, 2);
line(-2, 0, 2, 0);
}
// ellipse(x1+data_mean[0], y1+data_mean[1], 4*data_scale, 4*data_scale);
// line(x1+data_mean[0], y1+data_mean[1]-2*data_scale, x1+data_mean[0], y1+data_mean[1]+2*data_scale);
pop();
var settings = params;
if (Object.keys(trainValues).length > 0) {
// NOT NOW
if ((typeof data.embedding !== 'undefined') &&
(data.embedding != null) &&
(data.embedding.length > i) &&
(data.embedding[i] != null) &&
(typeof data.embedding[i].length !== 'undefined') &&
(data.embedding[i].length == 128)) {
// print("Using embedding ", i)
var curEmbedding = data.embedding[i];
results = getAverageSettingsFrom(curEmbedding);
settings = results[0];
}
}
push();
translate(x2, y1)
translate(scale_x*data_mean[0], scale_y*data_mean[1]);
scale(scale_x*data_scale, scale_y*data_scale);
rotate(degrees(data_angle));
strokeWeight(1/data_scale);
mainFace.setProperties(settings);
if (do_draw_face) {
mainFace.draw(shifted_positions);
}
pop();
}
if(do_train) {
textDisplay = "Train: " + curKey;
}
else {
textDisplay = "";
}
}
else if (mode == 'NearestNeighbors') {
background(bg_color1);
// var keys = Object.keys(trainData);
var curKey = trainDataKeys[curTrainIndex];
var data = trainData[curKey];
// Displays the image at its actual size at point (0,0)
var img = data.image
var x1 = (width/4-250/2);
var y1 = (height/3-250/2);
image(img, x1, y1, 250, 250);
if (curKey in trainValues) {
fill(0, 200, 0);
}
else {
fill(200, 0, 0);
}
ellipse(x1+250/2, y1+250+15, 10, 10);
var y2 = (3*height/4-80/2);
for(var i=0; i<4; i++) {
// var keys = Object.keys(trainData);
var curKey = curNeighbors[i];
var nearData = trainData[curKey];
// Displays the image at its actual size at point (0,0)
var img = nearData.image
var x2 = (width/4 - 200 + i*100);
image(img, x2, y2, 80, 80);
}
for(var i=0; i<1; i++) {
// get array of face marker positions [x, y] format
var positions = data.landmarks[i];
var shifted_positions = JSON.parse(JSON.stringify(positions))
var data_mean = [0.0, 0.0];
var data_scale = 1.0;
var data_angle = 0.0;
if ('transform' in positions) {
data_mean = positions.transform.center;
data_scale = positions.transform.scale;
data_angle = positions.transform.angle;
delete shifted_positions.transform
}
var scale_x = 400.0 / img.width;
var scale_y = 400.0 / img.height;
Object.keys(positions).forEach(function(key) {
if (key=='transform') {
return;
}
var curSection = positions[key];
var shiftedSection = shifted_positions[key];
for (var i=0; i<curSection.length; i++) {
var cur_x = curSection[i][0];
var cur_y = curSection[i][1];
// get ready for drawing the face
shiftedSection[i][0] = cur_x;
shiftedSection[i][1] = cur_y;
}
});
var scale_x = 250.0 / img.width;
var scale_y = 250.0 / img.height;
var x2 = (3*width/4-250/2);
push();
translate(x2, y1);
translate(scale_x*data_mean[0], scale_y*data_mean[1]);
scale(scale_x*data_scale, scale_y*data_scale);
rotate(degrees(data_angle));
strokeWeight(1/data_scale);
mainFace.setProperties(params);
mainFace.draw(shifted_positions);
pop();
var scale_x = 80.0 / img.width;
var scale_y = 80.0 / img.height;
for(var j=0; j<4; j++) {
// var keys = Object.keys(trainData);
var curKey = curNeighbors[j];
var x2 = (3*width/4 - 200 + j*100);
push();
translate(x2, y2);
if (curKey in trainValues) {
var settings = trainValues[curKey]
translate(scale_x*data_mean[0], scale_y*data_mean[1]);
scale(scale_x*data_scale, scale_y*data_scale);
rotate(degrees(data_angle));
strokeWeight(1/data_scale);
littleFace.setProperties(settings);
littleFace.draw(shifted_positions);
}
else {
noFill();
stroke(100);
rect(10, 10, 70, 70);
}
pop();
}
}
textDisplay = "Neighbors: " + trainDataKeys[curTrainIndex];
}
else if (mode == 'TrainingQuiz' || mode == 'InterpolationQuiz') {
background(bg_color1);
var curKey = trainDataKeys[curTrainIndex];
var data = trainData[curKey];
var valid_mode = false;
if (mode == 'InterpolationQuiz') {
valid_mode = true;
curKey = validDataKeys[curValidIndex];
data = validData[curKey];
}
// Displays the image at its actual size at point (0,0)
var img = data.image
var x1 = (width/2-200/2);
var y1 = (height/3-300/2);
image(img, x1, y1, 200, 200);
if(valid_mode) {
fill(0, 0, 200);
}
else if (curKey in trainValues) {
fill(0, 200, 0);
}
else {
fill(200, 0, 0);
}
ellipse(x1+200/2, y1+200+15, 10, 10);
var y2 = (3*height/5-80/2);
var y3 = (4*height/5-80/2);
/*
for(var i=0; i<4; i++) {
// var keys = Object.keys(trainData);
var curKey = curNeighbors[i];
var nearData = trainData[curKey];
// Displays the image at its actual size at point (0,0)
var img = nearData.image
var x2 = (width/4 - 200 + i*100);
image(img, x2, y2, 80, 80);
}
*/
for(var i=0; i<1; i++) {
// get array of face marker positions [x, y] format
var positions = data.landmarks[i];
var shifted_positions = JSON.parse(JSON.stringify(positions))
var data_mean = [0.0, 0.0];
var data_scale = 1.0;
var data_angle = 0.0;
if ('transform' in positions) {
data_mean = positions.transform.center;
data_scale = positions.transform.scale;
data_angle = positions.transform.angle;
delete shifted_positions.transform
}
var scale_x = 400.0 / img.width;
var scale_y = 400.0 / img.height;
Object.keys(positions).forEach(function(key) {
if (key=='transform') {
return;
}
var curSection = positions[key];
var shiftedSection = shifted_positions[key];
for (var i=0; i<curSection.length; i++) {
var cur_x = curSection[i][0];
var cur_y = curSection[i][1];
// get ready for drawing the face
shiftedSection[i][0] = cur_x;
shiftedSection[i][1] = cur_y;
}
});
/*
var scale_x = 250.0 / img.width;
var scale_y = 250.0 / img.height;
var x2 = (3*width/4-250/2);
push();
translate(x2, y1);
translate(scale_x*data_mean[0], scale_y*data_mean[1]);
scale(scale_x*data_scale, scale_y*data_scale);
rotate(degrees(data_angle));
strokeWeight(1/data_scale);
mainFace.setProperties(params);
mainFace.draw(shifted_positions);
pop();
*/
var scale_x = 80.0 / img.width;
var scale_y = 80.0 / img.height;
var otherKeys = Object.keys(trainValues);
var index = otherKeys.indexOf(trainDataKeys[curTrainIndex]);
if(index >= 0) {
otherKeys.splice(index, 1);
}
var answerSlot = int(focusedRandom(0, 4));
var answerKeys = Array(4);
for(var j=0; j<4; j++) {
if(j == answerSlot) {
curKey = trainDataKeys[curTrainIndex];
}
else {
var guess = int(focusedRandom(0, otherKeys.length));
// if(otherKeys.length > j+2) {
// while(answerKeys.indexOf(guess) == -1) {
// guess = int(focusedRandom(0, otherKeys.length));
// }
// }
curKey = otherKeys[guess];
}
answerKeys[j] = curKey;
// print("Answer", j, " is ", curKey);
var x2 = (width/2 - 200 + j*100);
var settings = params;
if (valid_mode && j == answerSlot) {
var curEmbedding = data.embedding[0];
results = getAverageSettingsFrom(curEmbedding);
settings = results[0];
var validTrainKeys = results[1];
}
else if (curKey in trainValues) {
settings = trainValues[curKey];
}
push();
translate(x2, y2);
translate(scale_x*data_mean[0], scale_y*data_mean[1]);
scale(scale_x*data_scale, scale_y*data_scale);
rotate(degrees(data_angle));
strokeWeight(1/data_scale);
if (typeof settings !== 'undefined') {
littleFace.setProperties(settings);
}
littleFace.draw(shifted_positions);
pop();
if(quiz_done && guessed_answer == (j+1)) {
push();
translate(x2, y2);
noFill();
strokeWeight(4);
if(guessed_answer == (answerSlot+1)) {
stroke(0, 100, 0);
}
else {
stroke(100, 0, 0);
}
rect(-10, -10, 100, 100);
pop();
}
}
if(quiz_done) {
for(var j=0; j<4; j++) {
if (valid_mode && (answerSlot+1) == (j+1)) {
for(var k=0; k<4; k++) {
var curKey = validTrainKeys[k];
var nearData = trainData[curKey];
// Displays the image at its actual size at point (0,0)
var img = nearData.image
var x2 = (width/2 - 200 + j*100 + (k%2)*40);
var y4 = y3 + (int(k/2))*40;
image(img, x2, y4, 40, 40);
}
}
else {
var curKey = answerKeys[j];
var nearData = trainData[curKey];
// Displays the image at its actual size at point (0,0)
if (typeof nearData !== 'undefined') {
var img = nearData.image
var x2 = (width/2 - 200 + j*100);
image(img, x2, y3, 80, 80);
}
}
}
}
}
if(valid_mode) {
if(quiz_done) {
textDisplay = "InterpolationQuiz: hit a number to continue";
}
else {
textDisplay = "InterpolationQuiz: hit 1, 2, 3, or 4 to guess";
}
}
else {
if(quiz_done) {
textDisplay = "TrainingQuiz: hit a number to continue";
}
else {
textDisplay = "TrainingQuiz: hit 1, 2, 3, or 4 to guess";
}
}
}
fill(255);
textSize(32);
textAlign(CENTER);
text(textDisplay, width/2, height-12);
}
async function keyTyped() {
if(!haveStarted) {
return;
}
var mode = faceSelector.value();
if (key == 'q' && mode != 'Faces') {
faceSelector.value('Faces');
}
else if (key == 'w' && mode != 'Train') {
faceSelector.value('Train');
}
else if (key == 'e' && mode != 'NearestNeighbors') {
faceSelector.value('NearestNeighbors');
}
else if (key == 'r' && mode != 'TrainingQuiz') {
faceSelector.value('TrainingQuiz');
}
else if (key == 't' && mode != 'InterpolationQuiz') {
faceSelector.value('InterpolationQuiz');
}
else if (key == 'y' && mode != 'Video') {
faceSelector.value('Video');
}
if (key >= '0' && key <= '9' &&
(mode == 'TrainingQuiz' || mode == 'InterpolationQuiz') && quiz_done) {
quiz_done = false;
if(mode == 'TrainingQuiz') {
curTrainIndex = (curTrainIndex + 1) % trainDataKeys.length;
}
else {
curValidIndex = (curValidIndex + 1) % validDataKeys.length;
}
changeRandomSeed();
}
else if ((mode == 'TrainingQuiz' || mode == 'InterpolationQuiz') && quiz_done == false) {
if(key >= '1' && key <= '4') {
guessed_answer = key - '0';
quiz_done = true;
}
}
if (key == 's') {
saveCurrentSettings();
}
else if (key == 'i') {
interpolateCurrent();
}
else if (key == 'l') {
loadCurrentSettings();
}
if (key == '!') {
saveBlocksImages();
}
else if (key == '@') {
saveBlocksImages(true);
}
/* THIS CODE IS USED TO UPDATE TRAINING_IMAGES.JS and TESTING_IMAGES.JS
if (key == '/') {
print("loading new train[0]");
for(let i=0; i<trainDataKeys.length; i++) {
var curKey = trainDataKeys[i];
var data = trainData[curKey];
let fullFaceDescriptions = await faceapi.detectAllFaces(data.image.canvas).withFaceLandmarks().withFaceDescriptors();
data.landmarks = get_landmarks(fullFaceDescriptions);
data.embedding = get_latents(fullFaceDescriptions);
}
print("loaded new trains");
return;
}
if (key == '?') {
print("running diagnostic on training");
let obj = {};
for(let i=0; i<trainDataKeys.length; i++) {
var curKey = trainDataKeys[i];
var data = trainData[curKey];
let fullFaceDescriptions = await faceapi.detectAllFaces(data.image.canvas).withFaceLandmarks().withFaceDescriptors();
let found_embed = get_latents(fullFaceDescriptions);
let found_landmarks = get_landmarks(fullFaceDescriptions);
// print(data.embedding[0], found_embed[0]);
// print("dist old to new -> ", num_dist(found_embed[0], data.embedding[0]));
let lst = [];
for(let i=0; i<128; i++) {
lst[i] = found_embed[0][i];
}
obj[curKey] = {"url": data.url, "embedding": [lst], "landmarks": found_landmarks};
}
// print(obj);
// obj = found_embed;
var text = select('#output');
var json = JSON.stringify(obj, null);
// alert(json);
text.html(json)
return;
}
if (key == ':') {
print("running diagnostic on validation");
let obj = {};
for(let i=0; i<validDataKeys.length; i++) {
var curKey = validDataKeys[i];
var data = validData[curKey];
let fullFaceDescriptions = await faceapi.detectAllFaces(data.image.canvas).withFaceLandmarks().withFaceDescriptors();
let found_embed = get_latents(fullFaceDescriptions);
let found_landmarks = get_landmarks(fullFaceDescriptions);
// print(data.embedding[0], found_embed[0]);
// print("dist old to new -> ", num_dist(found_embed[0], data.embedding[0]));
let lst = [];
for(let i=0; i<128; i++) {
lst[i] = found_embed[0][i];
}
obj[curKey] = {"url": data.url, "embedding": [lst], "landmarks": found_landmarks};
}
// print(obj);
// obj = found_embed;
var text = select('#output');
var json = JSON.stringify(obj, null);
// alert(json);
text.html(json)
return;
}
*/
}
function interpolateCurrent() {
var curNeighborSettings = [];
for(var i=0; i<4; i++) {
neighborKey = curNeighbors[i]
if(neighborKey in trainValues) {
curNeighborSettings.push(trainValues[neighborKey]);
}
}
for(var i=0; i<NUM_SLIDERS; i++) {
sliders[i].value(50);
}
if(curNeighborSettings.length > 0) {
settings = curNeighborSettings[0];
for(var i=0; i<settings.length; i++) {
var sum = 0;
for(j=0; j<curNeighborSettings.length; j++) {
sum += curNeighborSettings[j][i];
}
var avg = int(sum / curNeighborSettings.length)
sliders[i].value(avg);
}
}
}
function loadCurrentSettings() {
var curKey = trainDataKeys[curTrainIndex];
for(var i=0; i<NUM_SLIDERS; i++) {
sliders[i].value(50);
}
if (curKey in trainValues) {
var settings = trainValues[curKey]
for(var i=0; i<settings.length; i++) {
sliders[i].value(settings[i]);
}
}
}
function updateSlidersForTraining() {
var mode = faceSelector.value();
var curKey = trainDataKeys[curTrainIndex];
// first find the closest neighbors
var nearest = allEmbeddingsTree.nearest(trainData[curKey].embedding[0], 5);
curNeighbors = [];
curNeighborSettings = [];
for(var i=0; i<5; i++) {
if(nearest[i][0][128] != curKey) {
var neighborKey = nearest[i][0][128];
curNeighbors.push(neighborKey);
if(neighborKey in trainValues) {
curNeighborSettings.push(trainValues[neighborKey]);
}
}
}
loadCurrentSettings();
// if(mode == 'NearestNeighbors') {
// interpolateCurrent();
// }
// else {
// loadCurrentSettings();
// }
}
function getAverageSettingsFrom(e) {
// first find the closest neighbors
var nearest = allEmbeddingsTree.nearest(e, 4);
curNeighbors = [];
curNeighborSettings = [];
for(var i=0; i<4; i++) {
var neighborKey = nearest[i][0][128];
curNeighbors.push(neighborKey);
if(neighborKey in trainValues) {
curNeighborSettings.push(trainValues[neighborKey]);
}
}
for(var i=0; i<4; i++) {
neighborKey = curNeighbors[i]
if(neighborKey in trainValues) {
curNeighborSettings.push(trainValues[neighborKey]);
}
}
var trainValueKeys = Object.keys(trainValues);
var props = trainValues[trainValueKeys[0]];
if(curNeighborSettings.length > 0) {
settings = curNeighborSettings[0];
for(var i=0; i<settings.length; i++) {
var sum = 0;
for(j=0; j<curNeighborSettings.length; j++) {
sum += curNeighborSettings[j][i];
}
var avg = int(sum / curNeighborSettings.length)
props[i] = avg;
}
}
return [props, curNeighbors];
}
function keyPressed() {
if(!haveStarted) {
return;
}
var mode = faceSelector.value();
if (mode == 'Faces') {
if (keyCode == LEFT_ARROW || keyCode == UP_ARROW) {
curFaceIndex = (curFaceIndex + selfieData.length - 1) % selfieData.length;
} else if (keyCode === RIGHT_ARROW || keyCode == DOWN_ARROW) {
curFaceIndex = (curFaceIndex + 1) % selfieData.length;
}
}
else if (mode == 'Train' || mode == 'NearestNeighbors') {
if (keyCode == LEFT_ARROW || keyCode == UP_ARROW) {
curTrainIndex = (curTrainIndex + trainDataKeys.length - 1) % trainDataKeys.length;
updateSlidersForTraining();
} else if (keyCode == RIGHT_ARROW || keyCode == DOWN_ARROW) {
curTrainIndex = (curTrainIndex + 1) % trainDataKeys.length;
updateSlidersForTraining();
}
}
}
{
"000001": [
50,
24.00000000000003,
25,
100,
33.33333333333333,
0,
0
],
"000002": [
50,
49.99999999999994,
0,
100,
50,
0,
0
],
"000005": [
50,
42.00000000000005,
25,
36.000000000000036,
33.33333333333333,
100,
0
],
"000006": [
50,
42.00000000000005,
75,
100,
66.66666666666666,
0,
0
],
"000007": [
42,
53.00000000000006,
50,
16.000000000000018,
100,
0,
100
],
"000009": [
60,
14.000000000000016,
25,
100,
83.33333333333334,
0,
0
],
"000010": [
50,
10.000000000000012,
25,
100,
33.33333333333333,
100,
0
],
"000013": [
50,
82.99999999999999,
25,
45.00000000000005,
16.666666666666664,
100,
100
],
"000014": [
56.00000000000001,
4.000000000000004,
75,
42.00000000000005,
100,
0,
0
],
"000015": [
45,
57.99999999999995,
25,
46.00000000000005,
83.33333333333334,
100,
100
],
"000016": [
50,
29.000000000000032,
50,
43.00000000000005,
83.33333333333334,
0,
100
],
"000018": [
50,
39.00000000000004,
25,
100,
33.33333333333333,
100,
0
],
"000020": [
50,
61.99999999999996,
25,
90.99999999999999,
83.33333333333334,
0,
100
],
"000023": [
53,
55.00000000000006,
25,
41.00000000000005,
100,
100,
100
],
"000025": [
50,
55.99999999999995,
25,
18.000000000000018,
66.66666666666666,
0,
100
],
"000028": [
47,
42.00000000000005,
50,
100,
66.66666666666666,
0,
0
],
"000029": [
50,
25.00000000000003,
25,
100,
16.666666666666664,
100,
0
],
"000030": [
56.99999999999999,
37.000000000000036,
25,
52.99999999999995,
16.666666666666664,
0,
100
],
"000031": [
50,
30.000000000000032,
25,
67.99999999999996,
66.66666666666666,
100,
0
],
"000032": [
50,
37.000000000000036,
25,
43.00000000000005,
66.66666666666666,
0,
100
],
"000035": [
50,
44.00000000000005,
0,
100,
100,
0,
0
],
"000037": [
50,
55.99999999999995,
75,
26.00000000000003,
100,
0,
100
],
"000038": [
50,
43.00000000000005,
25,
50.00000000000006,
83.33333333333334,
100,
100
],
"000040": [
50,
39.00000000000004,
25,
100,
100,
0,
0
],
"000041": [
38,
49.99999999999994,
50,
63.99999999999996,
100,
0,
100
],
"000042": [
50,
28.000000000000032,
0,
77.99999999999999,
66.66666666666666,
100,
0
],
"000043": [
50,
49.99999999999994,
25,
100,
83.33333333333334,
0,
0
],
"000044": [
50,
35.000000000000036,
75,
93,
100,
0,
0
],
"000045": [
50,
23.000000000000025,
50,
83.99999999999999,
50,
0,
0
],
"000047": [
46,
49.99999999999994,
50,
100,
100,
0,
0
],
"000048": [
50,
49.99999999999994,
0,
31.000000000000032,
100,
66.66666666666666,
100
],
"000050": [
50,
34.000000000000036,
25,
27.00000000000003,
100,
0,
100
],
"000051": [
50,
49.99999999999994,
50,
0,
0,
0,
100
],
"000052": [
50,
23.000000000000025,
25,
20.000000000000025,
83.33333333333334,
0,
100
],
"000054": [
50,
31.000000000000032,
25,
100,
16.666666666666664,
100,
0
],
"000055": [
50,
49.99999999999994,
25,
22.000000000000025,
100,
0,
100
],
"000056": [
50,
36.000000000000036,
0,
62.99999999999996,
100,
100,
100
],
"000058": [
50,
39.00000000000004,
0,
100,
100,
100,
0
],
"000060": [
50,
49.99999999999994,
75,
20.000000000000025,
100,
0,
100
],
"000064": [
50,
32.000000000000036,
25,
29.000000000000032,
83.33333333333334,
100,
100
],
"000065": [
50,
37.000000000000036,
25,
39.00000000000004,
100,
0,
100
],
"000068": [
52,
31.000000000000032,
50,
58.99999999999995,
0,
33.33333333333333,
100
],
"000069": [
50,
43.00000000000005,
25,
13.000000000000014,
100,
0,
100
],
"000071": [
50,
28.000000000000032,
25,
68.99999999999996,
33.33333333333333,
33.33333333333333,
0
],
"000073": [
50,
35.000000000000036,
25,
100,
83.33333333333334,
0,
0
],
"000076": [
50,
29.000000000000032,
25,
80.99999999999999,
100,
0,
100
],
"000077": [
50,
37.000000000000036,
25,
97,
100,
0,
0
],
"000078": [
50,
49.99999999999994,
50,
100,
100,
0,
0
],
"000079": [
50,
12.000000000000014,
50,
0,
83.33333333333334,
0,
100
],
"000080": [
50,
36.000000000000036,
25,
29.000000000000032,
100,
0,
100
],
"000081": [
50,
35.000000000000036,
50,
16.000000000000018,
100,
0,
100
],
"000083": [
50,
49.99999999999994,
25,
68.99999999999996,
50,
66.66666666666666,
0
],
"000085": [
50,
32.000000000000036,
25,
94,
50,
66.66666666666666,
0
],
"000086": [
50,
34.000000000000036,
25,
73.99999999999997,
66.66666666666666,
33.33333333333333,
0
],
"000088": [
50,
49.99999999999994,
25,
100,
50,
0,
0
],
"000091": [
50,
68.99999999999996,
25,
27.00000000000003,
100,
0,
100
],
"000092": [
50,
40.00000000000005,
25,
71.99999999999996,
33.33333333333333,
66.66666666666666,
0
],
"000096": [
50,
58.99999999999995,
25,
100,
100,
0,
0
],
"000097": [
50,
39.00000000000004,
25,
100,
66.66666666666666,
100,
0
],
"000099": [
50,
42.00000000000005,
25,
100,
66.66666666666666,
100,
0
],
"000100": [
50,
49.99999999999994,
0,
29.000000000000032,
33.33333333333333,
0,
0
],
"000103": [
50,
49.99999999999994,
25,
84.99999999999999,
100,
66.66666666666666,
0
],
"000104": [
50,
49.99999999999994,
0,
38.00000000000004,
33.33333333333333,
100,
100
],
"000106": [
50,
31.000000000000032,
25,
70.99999999999996,
66.66666666666666,
0,
0
],
"000108": [
50,
49.99999999999994,
25,
56.000000000000064,
16.666666666666664,
100,
0
],
"000109": [
50,
19.00000000000002,
25,
26.00000000000003,
33.33333333333333,
100,
100
],
"000110": [
50,
49.99999999999994,
0,
59.99999999999995,
66.66666666666666,
100,
0
],
"000111": [
50,
49.99999999999994,
75,
30.000000000000032,
66.66666666666666,
0,
0
],
"000114": [
50,
41.00000000000005,
25,
36.000000000000036,
100,
0,
100
],
"000115": [
50,
49.99999999999994,
0,
0,
16.666666666666664,
66.66666666666666,
100
],
"000116": [
50,
49.99999999999994,
25,
58.99999999999995,
83.33333333333334,
0,
100
],
"000117": [
50,
24.00000000000003,
100,
83.99999999999999,
100,
0,
0
],
"000118": [
50,
18.000000000000018,
50,
24.00000000000003,
100,
0,
0
],
"000121": [
50,
49.99999999999994,
50,
100,
100,
0,
0
],
"000122": [
50,
32.000000000000036,
0,
0,
16.666666666666664,
0,
0
],
"000125": [
50,
26.00000000000003,
25,
0,
0,
100,
100
],
"000126": [
50,
49.99999999999994,
25,
100,
16.666666666666664,
100,
0
],
"000129": [
50,
18.000000000000018,
25,
32.000000000000036,
100,
100,
100
],
"000131": [
50,
43.00000000000005,
50,
100,
100,
0,
0
],
"000132": [
50,
51.00000000000006,
50,
100,
100,
0,
0
],
"000133": [
50,
49.99999999999994,
25,
24.00000000000003,
66.66666666666666,
100,
0
],
"000134": [
50,
49.99999999999994,
100,
0,
100,
0,
100
],
"000135": [
50,
23.000000000000025,
50,
12.000000000000014,
100,
0,
100
],
"000137": [
50,
71.99999999999996,
25,
32.000000000000036,
83.33333333333334,
100,
100
],
"000140": [
50,
35.000000000000036,
25,
100,
16.666666666666664,
100,
0
],
"000142": [
50,
16.000000000000018,
25,
100,
83.33333333333334,
100,
0
],
"000143": [
50,
33.000000000000036,
25,
22.000000000000025,
66.66666666666666,
100,
100
],
"000145": [
50,
49.99999999999994,
25,
100,
100,
0,
0
],
"000146": [
50,
49.99999999999994,
50,
100,
50,
0,
0
],
"000147": [
50,
38.00000000000004,
25,
100,
33.33333333333333,
100,
0
],
"000148": [
50,
38.00000000000004,
0,
97,
100,
100,
0
],
"000150": [
50,
19.00000000000002,
0,
52.00000000000006,
50,
100,
100
],
"000151": [
50,
31.000000000000032,
25,
100,
100,
0,
0
],
"000152": [
50,
49.99999999999994,
25,
23.000000000000025,
66.66666666666666,
66.66666666666666,
100
],
"000153": [
50,
23.000000000000025,
25,
20.000000000000025,
83.33333333333334,
33.33333333333333,
100
],
"000155": [
46,
22.000000000000025,
25,
100,
50,
0,
0
],
"000156": [
50,
30.000000000000032,
25,
10.000000000000012,
33.33333333333333,
100,
0
],
"000157": [
50,
32.000000000000036,
25,
100,
16.666666666666664,
100,
0
],
"000160": [
50,
36.000000000000036,
25,
24.00000000000003,
100,
0,
100
],
"000161": [
50,
27.00000000000003,
0,
100,
100,
100,
0
]
}
const bg_color = [225, 206, 187];
const fg_color = [151, 102, 52];
const stroke_color = [95, 52, 8];
function Face() {
// these are state variables for a face
// (your variables may be different)
/*
* Draw a face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
let eyeChange = this.eyesSHape;
//position for land marks
let rightePx = positions.right_eye[0][0]; //0.48
let rightePy = positions.right_eye[0][1]
let leftePx = positions.left_eye[3][0]; //0.48
let leftePy = positions.left_eye[3][1];
let skinco = this.skinC;
let Gender = this.Genders;
let smooth;
let sk1 = '#F2C6AE';
let sk2 = '#dbb58c';
let sk3 = '#F5E5C9';
let sk4 = '#c48d52';
let sk5 = '#36210d';
let teethP= this.teethPos;
let decoration = this.dec;
let eyecolor = this.ecolor;
let rightEyebrow = this.rightbrow;
let leftEyebrow = this.leftbrow;
fill(255 - this.mouth_value, 200)
beginShape();
if(skinco == 1){
fill(sk1);
}else if(skinco ==2){
fill(sk2)
}else if(skinco == 3){
fill(sk3)
}else if(skinco ==4){
fill(sk4)
}else if(skinco ==5){
fill(sk5)
}
//face
for(let i=0; i<positions.chin.length;i += Gender) {
vertex(positions.chin[i][0], positions.chin[i][1]);
}
for(let i=positions.right_eyebrow.length-2; i>=0;i-=2) {
vertex(positions.right_eyebrow[i][0], positions.right_eyebrow[i][1]-1.2);
}
for(let i=positions.left_eyebrow.length-2; i>=0;i-=2) {
vertex(positions.left_eyebrow[i][0], positions.left_eyebrow[i][1]-1.2);
}
endShape(CLOSE);
push();
fill(255);
beginShape();
noStroke()
for(let i = 0; i<positions.nose_tip.length; i++){
vertex(positions.nose_tip[i][0], positions.nose_tip[i][1]);
}
for(let i=14; i>1; i -= Gender) {
vertex(positions.chin[i][0], positions.chin[i][1]);
}
endShape(CLOSE);
pop();
//eye
push()
let eyeP = this.eyePos;
fill(100);
ellipse(leftePx-0.52, leftePy-0.3,1,2)
ellipse(rightePx+0.52, rightePy-0.3,1,2)
translate(0,eyeP)
if(eyeChange == 1){
push()
strokeWeight(0.04)
fill(255)
beginShape();
vertex(rightePx+1.12, -1.12);
bezierVertex(rightePx+1.04, -0.8, rightePx+0.92, -0.68, rightePx+0.76, -0.6)
bezierVertex(rightePx+0.4, -0.6, rightePx+0.24, -0.68, rightePx+0.08, -0.8)
vertex(rightePx, -1);
endShape(CLOSE);
beginShape();
vertex(leftePx-1.12, -1.12);
bezierVertex(leftePx-1.04, -0.8, leftePx-0.92, -0.68, leftePx-0.76, -0.6)
bezierVertex(leftePx-0.4, -0.6, leftePx-0.24, -0.68, leftePx-0.08, -0.8)
vertex(leftePx, -1);
endShape(CLOSE);
noStroke();
push();
colorMode(HSB);
fill(eyecolor,100,71)
ellipse(rightePx+0.52, -1.04, 0.6, 0.52)
ellipse(leftePx-0.52, -1.04, 0.6, 0.52)
pop();
fill(0);
ellipse(rightePx+0.52,-1.04, 0.4, 0.32)
ellipse(leftePx-0.52,-1.04, 0.4, 0.32)
pop();
push();
push();
strokeWeight(0)
fill('#FF9D85')
beginShape();
vertex(rightePx+1.2, -1.08);
vertex(rightePx+0.92, -1.4);
vertex(rightePx+0.32, -1.4);
vertex(rightePx, -1)
endShape();
beginShape();
vertex(leftePx-1.2, -1.08);
vertex(leftePx-0.92, -1.4);
vertex(leftePx-0.32, -1.4);
vertex(leftePx, -1)
endShape();
pop();
beginShape();
strokeWeight(0.08);
vertex(rightePx, -1);
bezierVertex(rightePx+0.24, -1.08, rightePx+1.12, -1.12, rightePx+1.2, -1.08);
endShape();
beginShape();
vertex(leftePx, -1);
bezierVertex(leftePx-0.24, -1.08, leftePx-1.12, -1.12, leftePx-1.2, -1.08);
endShape();
pop();
}else if(eyeChange ==2){
//rightePx = 0.48
//rightePy = 0.2
strokeWeight(0.04);
fill(255);
beginShape();
vertex(rightePx+1.12, rightePy-0.52);
bezierVertex(rightePx+1, rightePy, rightePx+0.72, rightePy, rightePx,rightePy);
bezierVertex(rightePx+0.28, rightePy-0.8, rightePx+0.44, rightePy - 0.64, rightePx +0.68, rightePy - 0.68);
endShape();
beginShape();
vertex(leftePx-1.12, leftePy-0.52);
bezierVertex(leftePx-1, leftePy, leftePx-0.72, leftePy, leftePx,leftePy);
bezierVertex(leftePx-0.28, leftePy-0.8, leftePx-0.44, leftePy - 0.64, leftePx -0.68, leftePy - 0.68);
endShape();
push();
colorMode(HSB);
fill(eyecolor,100,71)
ellipse(rightePx+0.52, rightePy-0.3, 0.6, 0.6)
pop();
fill(0);
ellipse(rightePx+0.52, rightePy-0.3, 0.3, 0.3)
beginShape();
vertex(rightePx,rightePy);
bezierVertex(rightePx+0.08, rightePy-0.72, rightePx + 0.44, rightePy-0.8, rightePx + 0.68, rightePy-0.78);
bezierVertex(rightePx + 0.92, rightePy-0.72, rightePx + 1.12, rightePy-0.52, rightePx + 1.2, rightePy-0.64);
bezierVertex(rightePx + 1.12, rightePy-0.52, rightePx + 0.92, rightePy-0.56, rightePx + 0.68, rightePy-0.68);
bezierVertex(rightePx + 0.44, rightePy-0.64, rightePx+0.28, rightePy-0.6, rightePx, rightePy-0.2);
endShape()
push();
colorMode(HSB);
fill(eyecolor,100,71)
ellipse(leftePx-0.52, leftePy-0.3, 0.6, 0.6)
pop();
fill(0);
ellipse(leftePx-0.52, leftePy-0.3, 0.3, 0.3)
beginShape();
vertex(leftePx,leftePy);
bezierVertex(leftePx-0.08, leftePy-0.72, leftePx - 0.44, leftePy-0.8, leftePx - 0.68, leftePy-0.78);
bezierVertex(leftePx - 0.92, leftePy-0.72, leftePx - 1.12, leftePy-0.52, leftePx - 1.2, leftePy-0.64);
bezierVertex(leftePx - 1.12, leftePy-0.52, leftePx - 0.92, leftePy-0.56, leftePx - 0.68, leftePy-0.68);
bezierVertex(leftePx - 0.44, leftePy-0.64, leftePx-0.28, leftePy-0.6, leftePx, leftePy-0.2);
endShape();
}else if(eyeChange == 3){
translate(0,-0.8)
// scale(0.4)
beginShape();//right eye inside
fill(250)
//rightePx = 0.48
vertex(rightePx, -0.216);
bezierVertex(rightePx+0.144, -0.364, rightePx+1.2, -0.676, rightePx+1.08,-0.24)
bezierVertex(rightePx+0.96, 0, rightePx+0.916, 0.048, rightePx + 0.72, 0.192);
bezierVertex(rightePx, 0.24, rightePx-0.12, 0.12, rightePx, -0.216)
endShape(CLOSE);
push();
colorMode(HSB);
fill(eyecolor,100,71);
ellipse(rightePx+0.432, -0.12, 0.648, 0.576);
pop();
fill(36, 73, 83)
ellipse(rightePx+0.432, -0.12, 0.24, 0.24)
push();
noFill();
beginShape();
fill(0)
vertex(rightePx, -0.216);
bezierVertex(rightePx+0.144, -0.368, rightePx+1.2, -0.676, rightePx+1.08, -0.24)
vertex(rightePx+1.2, -0.48);
bezierVertex(rightePx + 1.08, -0.6, rightePx+0.72, -0.6, rightePx, -0.24)
endShape(CLOSE);
pop();
beginShape();//left eye inside
fill(250)
vertex(leftePx, -0.216);
bezierVertex(leftePx-0.144, -0.364, leftePx-1.2, -0.676, leftePx-1.08,-0.24)
bezierVertex(leftePx-0.96, 0, leftePx-0.916, 0.048, leftePx - 0.72, 0.192);
bezierVertex(leftePx, 0.24, leftePx-0.12, 0.12, leftePx, -0.216)
endShape(CLOSE);
push();
colorMode(HSB);
fill(eyecolor,100,71);
ellipse(leftePx-0.432, -0.12, 0.648, 0.576);
pop();
fill(36, 73, 83)
ellipse(leftePx-0.432, -0.12, 0.24, 0.24)
beginShape();
fill(0)
vertex(leftePx, -0.216);
bezierVertex(leftePx-0.144, -0.368, leftePx-1.2, -0.676, leftePx-1.08, -0.24)
vertex(leftePx-1.2, -0.48);
bezierVertex(leftePx - 1.08, -0.6, leftePx-0.72, -0.6, leftePx, -0.24)
endShape(CLOSE);
}
pop()
push();
scale(0.4)
translate(0,-2.5)
if(decoration == 1){
//freckle
fill("#B57738")
noStroke()
ellipse(1,0,0.1,0.1);
ellipse(0.2,0.5,0.2,0.2)
ellipse(-1.1,0.5,0.2,0.15);
ellipse(1.4,0.8,0.15,0.15);
ellipse(-1.1,0.3,0.15,0.1);
ellipse(-1.4,1.3,0.15,0.15);
ellipse(-0.8,0.5,0.2,0.15);
ellipse(1.1,0.3,0.15,0.15);
ellipse(-1,0.9,0.15,0.2);
ellipse(-2,1,0.15,0.15);
ellipse(2,1,0.2,0.15);
ellipse(0, 1, 0.3, 0.15);
ellipse(1.5, 1.4, 0.25, 0.25);
ellipse(-1.8, 0.8, 0.2, 0.2);
ellipse(1.8, 0.8, 0.2, 0.2);
}else if(decoration==2){
}else if(decoration==3){
// translate(3,0)
fill('#EB4762');
noStroke();
ellipse(3,2,2,2);
ellipse(-3,2,2,2);
}else if(decoration==4){
//glass
noFill();
strokeWeight(0.2)
ellipse(2.5,0,3.5,2.5);
ellipse(-2.5,0,3.5,2.5);
beginShape();
vertex(0.8,0);
vertex(0,-0.5)
vertex(-0.8,0)
endShape();
}
pop();
push()
beginShape();// botom lip
noFill();
vertex(positions.bottom_lip[2][0],positions.bottom_lip[2][1]);
bezierVertex(positions.bottom_lip[2][0],positions.bottom_lip[2][1],positions.bottom_lip[3][0],positions.bottom_lip[3][1],positions.bottom_lip[4][0],positions.bottom_lip[4][1])
endShape();
pop();
beginShape();//mouth
noFill();
for(let i = 7; i <positions.top_lip.length; i ++){
vertex(positions.top_lip[i][0],positions.top_lip[i][1]);
}
endShape();
beginShape();
fill('#543B33');
vertex(positions.top_lip[7][0],positions.top_lip[7][1]);
vertex(positions.top_lip[8][0],positions.top_lip[8][1]+this.teethPos);
vertex(positions.top_lip[9][0],positions.top_lip[9][1]+this.teethPos);
vertex(positions.top_lip[10][0],positions.top_lip[10][1]+this.teethPos);
vertex(positions.top_lip[11][0],positions.top_lip[11][1]);
for(let i = 7; i <positions.bottom_lip.length; i ++){
vertex(positions.bottom_lip[i][0],positions.bottom_lip[i][1])
}
endShape();
beginShape();
noStroke();
fill('red');
vertex(positions.top_lip[0][0]-0.6,positions.top_lip[0][1]);
for(let i = 1; i <6; i ++){
vertex(positions.top_lip[i][0],positions.top_lip[i][1]);
}
vertex(positions.top_lip[6][0]+0.6,positions.top_lip[6][1]);
for(let i = 7; i <12; i ++){
vertex(positions.top_lip[i][0],positions.top_lip[i][1]);
}
endShape()
beginShape();
vertex(positions.top_lip[6][0]+0.6,positions.top_lip[6][1]);
for(let i = 1; i <6; i ++){
vertex(positions.bottom_lip[i][0],positions.bottom_lip[i][1])
}
vertex(positions.top_lip[0][0]-0.6,positions.top_lip[0][1]);
vertex(positions.bottom_lip[6][0],positions.bottom_lip[6][1]);
for(let i = 7; i <12; i ++){
vertex(positions.bottom_lip[i][0],positions.bottom_lip[i][1])
}
endShape();
beginShape()//teeth
fill(255)
vertex(positions.top_lip[7][0],positions.top_lip[7][1]);
vertex(positions.top_lip[8][0],positions.top_lip[8][1]+this.teethPos);
vertex(positions.top_lip[9][0],positions.top_lip[9][1]+this.teethPos);
vertex(positions.top_lip[10][0],positions.top_lip[10][1]+this.teethPos);
vertex(positions.top_lip[11][0],positions.top_lip[11][1]);
for(let i = 11; i >6 ; i --){
vertex(positions.top_lip[i][0],positions.top_lip[i][1]);
}
endShape();
push();
stroke(0);
fill('red');
ellipse(positions.nose_bridge[3][0], positions.nose_bridge[3][1],1,1)
pop();
push();
translate(0,-1)
scale(0.4);
noStroke();
fill(25);
beginShape();//right eye brow
vertex(0.72, -2.1+0.2*rightEyebrow);
bezierVertex(0.72, -2.16+0.2*rightEyebrow, 2.4, -3.3-0.15*rightEyebrow, 4.2, -2.4-0.15*rightEyebrow);
vertex(3.6, -2.46-0.15*rightEyebrow);
vertex(2.1, -2.4+0.01*rightEyebrow);
endShape(CLOSE);
beginShape();//Left eye brow
vertex(-0.72, -2.1+0.15*leftEyebrow);
bezierVertex(-0.72, -2.16+0.2*leftEyebrow, -2.4, -3.3-0.15*leftEyebrow, -4.2, -2.4-0.15*leftEyebrow);
vertex(-3.6, -2.46-0.15*leftEyebrow);
vertex(-2.1, -2.4+0.01*leftEyebrow);
endShape(CLOSE);
pop();
fill(20);
// for(let i = 0; i <positions.top_lip.length; i++){
// textSize(0.3);
// text(i, positions.top_lip[i][0], positions.top_lip[i][1]);
// } //11 10 9 8 7
// for(let i = 0; i <positions.bottom_lip.length; i++){
// textSize(0.2);
// text(i, positions.bottom_lip[i][0], positions.bottom_lip[i][1]);
// } //7 8 9 10 11
// // // for(let i = 0; i <positions.chin.length; i++){
// // // textSize(0.2);
// // // text(i, positions.chin[i][0], positions.chin[i][1]);
// // // }
// // for(let i = 0; i <positions.nose_tip.length; i++){
// // textSize(0.2);
// // text(i, positions.nose_tip[i][0], positions.nose_tip[i][1]);
// // }
// // for(let i = 0; i <positions.nose_bridge.length; i++){
// // textSize(0.2);
// // text(i, positions.nose_bridge[i][0], positions.nose_bridge[i][1]);
// // }
// fill(0);
// for(let i = 0; i <positions.left_eyebrow.length; i++){
// textSize(0.4);
// text(i, positions.left_eyebrow[i][0], positions.left_eyebrow[i][1]);
// }
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.eyesSHape = int(map(settings[0], 0, 100, 1,3));
this.skinC = int(map(settings[1], 0, 100, 1, 5));
this.Genders = int(map(settings[2], 0, 100, 1, 2));
this.teethPos = map(settings[3], 0, 100,0, 0.5);
this.dec = int(map(settings[4], 0, 100,1, 4));
this.ecolor = map(settings[5], 0, 100,0, 360);
this.rightbrow = map(settings[6], 0, 100,0, 3);
this.leftbrow = map(settings[7], 0, 100,0, 3);
this.eyePos = map(settings[8], 0, 100,-0.3,0.3)
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(9);
settings[0] = map(this.eyesSHape, 1, 3, 0, 100);
settings[1] = map(this.skinC, 1, 5, 0, 100);
settings[2] = map(this.Genders, 1, 2, 0, 100);
settings[3] = map(this.teethPos, 0, 0.5, 0, 100);
settings[4] = map(this.dec, 1, 4, 0, 100);
settings[5]= map(this.ecolor,0,360,0,100);
settings[6]= map(this.rightbrow,0,3,0,100);
settings[7]= map(this.leftbrow,0,3,0,100);
settings[8]= map(this.eyePos,-0.3,0.3,0,100);
return settings;
}
}
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for(var i=0; i<list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// other variables can be in here too
// these control the colors used
const bg_color = [225, 206, 187];
const fg_color = [151, 102, 52];
const stroke_color = [95, 52, 8];
function segment_average(segment) {
let sum_x = 0;
let sum_y = 0;
let s_len = segment.length;
for (let i=0; i<s_len; i++) {
sum_x = sum_x + segment[i][0];
sum_y = sum_y + segment[i][1];
}
return [sum_x / s_len , sum_y / s_len ];
}
function Face() {
// these are state variables for a face
// (your variables may be different)
this.eye_value = 2; // can be either 2 (eyes) or 3 (no eyes)
this.mouth_value = 1; // range is 0.5 to 8
this.tilt_value = 0; // range is -30 to 30
this.draw_segment = function(segment, do_loop) {
// print(segment);
for(let i=0; i<segment.length; i++) {
let px = segment[i][0];
let py = segment[i][1];
ellipse(px, py, 0.1);
if(i < segment.length - 1) {
let nx = segment[i+1][0];
let ny = segment[i+1][1];
line(px, py, nx, ny);
}
else if(do_loop) {
let nx = segment[0][0];
let ny = segment[0][1];
line(px, py, nx, ny);
}
}
};
/*
* Draw a face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
rotate(this.tilt_value);
// head
stroke(stroke_color);
fill(fg_color);
ellipse(0, 0, 3, 4);
noStroke();
// mouth
fill(bg_color);
ellipse(0, 0.64, 1.36, 0.25 * this.mouth_value);
// eyebrows
fill(0);
stroke(0);
strokeWeight(0.08);
this.draw_segment(positions.left_eyebrow);
this.draw_segment(positions.right_eyebrow);
fill(128);
stroke(128);
this.draw_segment(positions.chin);
fill(100, 0, 100);
stroke(100, 0, 100);
this.draw_segment(positions.nose_bridge);
this.draw_segment(positions.nose_tip);
strokeWeight(0.03);
fill(200, 0, 0);
stroke(200, 0, 0);
this.draw_segment(positions.top_lip);
this.draw_segment(positions.bottom_lip);
fill(255);
stroke(255);
// this.draw_segment(positions.left_eye, true);
// this.draw_segment(positions.right_eye, true);
// print(Object.keys(positions))
let left_eye_pos = segment_average(positions.left_eye);
let right_eye_pos = segment_average(positions.right_eye);
// eyes
noStroke();
fill(bg_color);
ellipse(left_eye_pos[0], left_eye_pos[1], 0.45, 0.27);
ellipse(right_eye_pos[0], right_eye_pos[1], 0.45, 0.27);
fill(fg_color);
ellipse(left_eye_pos[0] - 0.1, left_eye_pos[1], 0.18);
ellipse(right_eye_pos[0] - 0.1, right_eye_pos[1], 0.18);
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.eye_value = int(map(settings[0], 0, 100, 2, 3));
this.mouth_value = map(settings[1], 0, 100, 0.5, 8);
this.tilt_value = map(settings[2], 0, 100, -30, 30);
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(3);
settings[0] = map(this.eye_value, 2, 3, 0, 100);
settings[1] = map(this.mouth_value, 0.5, 8, 0, 100);
settings[2] = map(this.tilt_value, -30, 30, 0, 100);
return settings;
}
}
// draw the whole mask in function face()
function Face() {
this.draw = function(positions) {
let hair_setting = this.hair_setting;
let face_setting = this.face_setting;
let nose_setting = this.nose_setting;
let symbol_value = this.symbol_value;
let eye_setting = this.eye_setting;
let beard_setting = this.beard_setting;
let hair_colour = this.hair_colour;
//hair colour
let hc1 = "#000000";
let hc2 = "#e5ddcc";
let hc3 = "#d9a86c";
let hc4 = "#6a5b4d";
let hc5 = "#f2c46d";
let hc6 = "#8c3730";
let shift_face_x = positions.left_eyebrow[0][0];
let shift_face_y =positions.left_eyebrow[0][1];
angleMode(DEGREES);
push();
scale(0.33);
stroke(0);
strokeWeight(0.15);
//draw face shape
push()
strokeWeight(0.1);
scale(3.3);
if (face_setting == 0){
fill("#f2c1ae")
beginShape();
curveVertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1]);
curveVertex(positions.chin[0][0], positions.chin[0][1]);
curveVertex(positions.chin[3][0], positions.chin[3][1]);
curveVertex(positions.chin[5][0], positions.chin[5][1]);
curveVertex(positions.chin[6][0], positions.chin[6][1]);
curveVertex(positions.chin[7][0], positions.chin[7][1]);
curveVertex(positions.chin[8][0], positions.chin[8][1]);
curveVertex(positions.chin[9][0], positions.chin[9][1]);
curveVertex(positions.chin[10][0], positions.chin[10][1]);
curveVertex(positions.chin[11][0], positions.chin[11][1]);
curveVertex(positions.chin[12][0], positions.chin[12][1]);
curveVertex(positions.chin[14][0], positions.chin[14][1]);
curveVertex(positions.chin[16][0], positions.chin[16][1]);
curveVertex(positions.right_eyebrow[4][0], positions.right_eyebrow[4][1]);
curveVertex(positions.right_eyebrow[4][0], positions.right_eyebrow[4][1]);
endShape();
}else if (face_setting == 1){
fill("#fff3ec");
beginShape();
curveVertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1]);
curveVertex(positions.chin[0][0], positions.chin[0][1]);
curveVertex(positions.chin[0][0], positions.chin[0][1]);
curveVertex(positions.chin[3][0], positions.chin[3][1]);
curveVertex(positions.chin[5][0], positions.chin[5][1]);
curveVertex(positions.chin[6][0], positions.chin[6][1]);
curveVertex(positions.chin[7][0], positions.chin[7][1]);
curveVertex(positions.chin[8][0], positions.chin[8][1]);
curveVertex(positions.chin[9][0], positions.chin[9][1]);
curveVertex(positions.chin[10][0], positions.chin[10][1]);
curveVertex(positions.chin[11][0], positions.chin[11][1]);
curveVertex(positions.chin[12][0], positions.chin[12][1]);
curveVertex(positions.chin[14][0], positions.chin[14][1]);
curveVertex(positions.chin[16][0], positions.chin[16][1]);
curveVertex(positions.right_eyebrow[4][0], positions.right_eyebrow[4][1]);
curveVertex(positions.right_eyebrow[4][0], positions.right_eyebrow[4][1]);
endShape();
}else if (face_setting == 2){
beginShape();
fill("#ffdcbb");
curveVertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1]);
curveVertex(positions.chin[0][0], positions.chin[0][1]);
curveVertex(positions.chin[3][0], positions.chin[3][1]);
curveVertex(positions.chin[5][0], positions.chin[5][1]);
curveVertex(positions.chin[6][0], positions.chin[6][1]);
curveVertex(positions.chin[7][0], positions.chin[7][1]);
curveVertex(positions.chin[8][0], positions.chin[8][1]);
curveVertex(positions.chin[9][0], positions.chin[9][1]);
curveVertex(positions.chin[10][0], positions.chin[10][1]);
curveVertex(positions.chin[11][0], positions.chin[11][1]);
curveVertex(positions.chin[12][0], positions.chin[12][1]);
curveVertex(positions.chin[14][0], positions.chin[14][1]);
curveVertex(positions.chin[16][0], positions.chin[16][1]);
curveVertex(positions.right_eyebrow[4][0], positions.right_eyebrow[4][1]);
curveVertex(positions.right_eyebrow[4][0], positions.right_eyebrow[4][1]);
endShape(CLOSE);
}else {
fill("#bf8665");
beginShape();
curveVertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[0][0], positions.left_eyebrow[0][1]);
curveVertex(positions.chin[0][0], positions.chin[0][1]);
curveVertex(positions.chin[3][0], positions.chin[3][1]);
curveVertex(positions.chin[5][0], positions.chin[5][1]);
curveVertex(positions.chin[6][0], positions.chin[6][1]);
curveVertex(positions.chin[7][0], positions.chin[7][1]);
curveVertex(positions.chin[8][0], positions.chin[8][1]);
curveVertex(positions.chin[9][0], positions.chin[9][1]);
curveVertex(positions.chin[10][0], positions.chin[10][1]);
curveVertex(positions.chin[11][0], positions.chin[11][1]);
curveVertex(positions.chin[12][0], positions.chin[12][1]);
curveVertex(positions.chin[14][0], positions.chin[14][1]);
curveVertex(positions.chin[16][0], positions.chin[16][1]);
curveVertex(positions.right_eyebrow[4][0], positions.right_eyebrow[4][1]);
curveVertex(positions.right_eyebrow[4][0], positions.right_eyebrow[4][1]);
endShape();
}
pop();
//draw eye area(eye_mask and eye shapes)
push();
// right part
if(eye_setting == 0) {
beginShape();
fill("#c2c3c4")
vertex(1.2, -1);
bezierVertex( 3, -1, 5, -3,4.7,1)
bezierVertex( 3.6, 0, 3.5, 0.1, 1.5, -1);
bezierVertex(0.8, 0.6, 0.9, 0.3, 1.2, -0.8)
endShape(CLOSE);
beginShape();
fill(0)
vertex(1.2, -1);
bezierVertex( 1.6, -0.9, 4.2, -1.7, 3.7,-0.6)
bezierVertex( 3.6, 0, 3.5, 0.1, 3, 0.5);
bezierVertex(0.8, 0.6, 0.9, 0.3, 1.2, -0.8)
endShape(CLOSE);
fill(0)
ellipse(2.3, -0.3, 1.7, 1.5)
fill(50)
arc(2.3, -0.3,0.6,0.6,PI-QUARTER_PI,QUARTER_PI, PIE)
//left EYE area
beginShape();
fill("#c2c3c4")
vertex(-1.2, -1);
bezierVertex( -3, -1, -5, -3, -4.7,1)
bezierVertex( -3.6, 0, -3.5, 0.1, -1.5, -1);
bezierVertex(-0.8, 0.6, -0.9, 0.3, -1.2, -0.8)
endShape(CLOSE);
beginShape();
fill(0)
vertex(-1.2, -1);
bezierVertex( -1.6, -0.9, -4.2, -1.7, -3.7,-0.6)
bezierVertex( -3.6, 0, -3.5, 0.1, -3, 0.5);
bezierVertex(-0.8, 0.6, -0.9, 0.3, -1.2, -0.8)
endShape(CLOSE);
fill(0);
ellipse(-2.3, -0.3, -1.7, 1.5)
fill(50);
arc(-2.3, -0.3,0.6,0.6,PI-QUARTER_PI,QUARTER_PI, PIE)
}else if
(eye_setting == 1) {
beginShape();
fill("#f9a603")
stroke("#ffa600")
vertex(1.2, -1);
bezierVertex( 3, -1, 5, -4, 6.7,-1.6)
bezierVertex( 3.6, 0, 3.5, 0.1, 5, 1.5);
bezierVertex(0.8, 0.6, 0.9, 0.3, 1.2, -0.8)
endShape(CLOSE);
beginShape();
fill("#f7ebd5")
vertex(1.2, -1);
bezierVertex( 1.6, -0.9, 4.2, -1.7, 3.7,-0.6)
bezierVertex( 3.6, 0, 3.5, 0.1, 3, 0.5);
bezierVertex(0.8, 0.6, 0.9, 0.3, 1.2, -0.8)
endShape(CLOSE);
fill("#f7ebd5")
ellipse(2.3, -0.3, 1.6, 1.2)
fill("#f9a603")
arc(2.3, -0.3,0.6,0.3,0,360, PIE)
//left EYE area
beginShape();
fill("#f9a603")
stroke("#ffa600")
vertex(-1.2, -1);
bezierVertex( -3, -1, -5, -4, -6.7,-1.6)
bezierVertex( -3.6, 0, -3.5, 0.1, -5, 1.5);
bezierVertex(-0.8, 0.6, -0.9, 0.3, -1.2, -0.8)
endShape(CLOSE);
beginShape();
fill("#f7edb5")
vertex(-1.2, -1);
bezierVertex( -1.6, -0.9, -4.2, -1.7, -3.7,-0.6)
bezierVertex( -3.6, 0, -3.5, 0.1, -3, 0.5);
bezierVertex(-0.8, 0.6, -0.9, 0.3, -1.2, -0.8)
endShape(CLOSE);
fill("#f7ebd5");
ellipse(-2.3, -0.3, 1.6, 1.2)
fill("#f9a603");
arc(-2.3, -0.3,0.6,0.3,0,360, PIE)
}else if(eye_setting == 2) {
// right EYE area
beginShape();
fill("#F1FCFF");
vertex(1.2, -1);
bezierVertex( 1.6, -0.9, 4.2, -1.7, 3.7,-0.6)
bezierVertex( 3.6, 0, 3.5, 0.1, 3, 0.5);
bezierVertex(0.8, 0.6, 0.9, 0.3, 1.2, -0.8)
endShape(CLOSE);
fill("#b5bdbf")
strokeWeight(0.2)
stroke("#000000")
ellipse(2.3, -0.3, 1.5, 1.4)
fill("#3c3f40")
arc(2.3, -0.3,0.6,0.6,0,180, PIE)
//left EYE area
beginShape();
fill("f1fcff")
vertex(-1.2, -1);
bezierVertex( -1.6, -0.9, -4.2, -1.7, -3.7,-0.6)
bezierVertex( -3.6, 0, -3.5, 0.1, -3, 0.5);
bezierVertex(-0.8, 0.6, -0.9, 0.3, -1.2, -0.8)
endShape(CLOSE);
fill("#b5bdbf");
stroke("#000000")
strokeWeight(0.2)
ellipse(-2.3, -0.3, 1.5, 1.4)
fill("#3c3f40");
arc(-2.3, -0.3,0.6,0.6,0,180, PIE)
}else if (eye_setting == 3) {
//right EYE area
beginShape();
stroke("#730217")
fill("#f20530")
vertex(1.2, -1);
bezierVertex( 3, -1, 5, -3, 8.7,-4)
bezierVertex( 3.6, 0, 3.5, 0.1, 6, 3.5);
bezierVertex(0.8, 0.6, 0.9, 0.3, 1.2, -0.8)
endShape(CLOSE);
beginShape();
fill("#ffffff")
vertex(1.2, -1);
bezierVertex( 1.6, -0.9, 4.2, -1.7, 3.7,-0.6)
bezierVertex( 3.6, 0, 3.5, 0.1, 3, 0.5);
bezierVertex(0.8, 0.6, 0.9, 0.3, 1.2, -0.8)
endShape(CLOSE);
fill("#a7d5f2")
ellipse(2.3, -0.3, 1.5, 1.1)
fill("#0468bf")
arc(2.3, -0.3,0.3,0.6,0,360, PIE)
//left EYE area
beginShape();
stroke("#730217")
fill("#f20530")
vertex(-1.2, -1);
bezierVertex( -3, -1, -5, -3, -8.7,-4)
bezierVertex( -3.6, 0, -3.5, 0.1, -6, 3.5);
bezierVertex(-0.8, 0.6, -0.9, 0.3, -1.2, -0.8)
endShape(CLOSE);
beginShape();
fill("#ffffff")
vertex(-1.2, -1);
bezierVertex( -1.6, -0.9, -4.2, -1.7, -3.7,-0.6)
bezierVertex( -3.6, 0, -3.5, 0.1, -3, 0.5);
bezierVertex(-0.8, 0.6, -0.9, 0.3, -1.2, -0.8)
endShape(CLOSE);
fill("#a7d5f2");
ellipse(-2.3, -0.3, 1.5, 1.1)
fill("#0468bf");
arc(-2.3, -0.3,0.3,0.6,0,360, PIE)
}else {
// right EYE area
scale(3.3);
fill("#000000")
beginShape();
curveVertex(positions.chin[0][0],positions.chin[0][1])
curveVertex(positions.chin[0][0],positions.chin[0][1])
curveVertex(positions.chin[2][0],positions.chin[2][1])
curveVertex(positions.chin[14][0],positions.chin[14][1])
curveVertex(positions.chin[16][0],positions.chin[16][1])
curveVertex(positions.chin[16][0],positions.chin[16][1])
endShape(CLOSE);
scale(0.33)
fill("#84bfbf")
stroke("#000000")
ellipse(2.3, -0.5, 3.2, 2.1)
stroke("#155fbf")
fill("#155fbf")
arc(2.3, -0.5,1.1,0.8,210,150, PIE)
//left EYE area
fill("#84bfbf")
stroke("#000000")
ellipse(-2.3, -0.5, 3.2, 2.1)
stroke("#155fbf")
fill("#155fbf")
arc(-2.3, -0.5,1.1,0.8,30,330, PIE)
}
pop()
//draw Nose area
push();
stroke(0);
strokeJoin(ROUND);
fill(0);
if (nose_setting == 0){
translate(-shift_face_x*0.1, -shift_face_y*1.2);
triangle(positions.nose_bridge[1][0], positions.nose_bridge[1][1],positions.nose_tip[1][0],positions.nose_tip[1][1],positions.nose_tip[3][0],positions.nose_tip[3][1]);
}else if (nose_setting == 1){
translate(-shift_face_x*0.1, -shift_face_y*1.2);
triangle(positions.nose_bridge[0][0], positions.nose_bridge[0][1],positions.nose_tip[1][0],positions.nose_tip[1][1],positions.nose_tip[3][0],positions.nose_tip[3][1]);
}else{
translate(-shift_face_x*0.1, -shift_face_y*1.2);
ellipse(positions.nose_bridge[2][0],positions.nose_bridge[2][1],0.1,1);
}
pop();
//draw eyebrow
push()
if (eye_setting == 0){
translate(shift_face_x*0.7,shift_face_y*0.6);
fill("#000000");
beginShape();
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[2][0],positions.left_eyebrow[2][1]);
curveVertex(positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]);
curveVertex(positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]);
endShape();
beginShape();
curveVertex(positions.right_eyebrow[0][0]+2.5,positions.right_eyebrow[0][1]);
curveVertex(positions.right_eyebrow[0][0]+2.5,positions.right_eyebrow[0][1]);
curveVertex(positions.right_eyebrow[2][0]+2.5,positions.right_eyebrow[2][1]);
curveVertex(positions.right_eyebrow[4][0]+2.5,positions.right_eyebrow[4][1]);
curveVertex(positions.right_eyebrow[4][0]+2.5,positions.right_eyebrow[4][1]);
endShape();
}else if (eye_setting == 1){
translate(shift_face_x*0.7,shift_face_y*0.6);
noFill();
beginShape();
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[2][0],positions.left_eyebrow[2][1]);
curveVertex(positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]);
curveVertex(positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]);
endShape();
beginShape();
curveVertex(positions.right_eyebrow[0][0]+2.5,positions.right_eyebrow[0][1]);
curveVertex(positions.right_eyebrow[0][0]+2.5,positions.right_eyebrow[0][1]);
curveVertex(positions.right_eyebrow[2][0]+2.5,positions.right_eyebrow[2][1]);
curveVertex(positions.right_eyebrow[4][0]+2.5,positions.right_eyebrow[4][1]);
curveVertex(positions.right_eyebrow[4][0]+2.5,positions.right_eyebrow[4][1]);
endShape();
}else if (eye_setting == 2){
translate(shift_face_x*0.7,shift_face_y*0.6);
fill("#000000");
beginShape();
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[3][0],positions.left_eyebrow[3][1]);
curveVertex(positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]);
curveVertex(positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]);
endShape();
beginShape();
curveVertex(positions.right_eyebrow[0][0]+2.5,positions.right_eyebrow[0][1]);
curveVertex(positions.right_eyebrow[0][0]+2.5,positions.right_eyebrow[0][1]);
curveVertex(positions.right_eyebrow[3][0]+2.5,positions.right_eyebrow[3][1]);
curveVertex(positions.right_eyebrow[4][0]+2.5,positions.right_eyebrow[4][1]);
curveVertex(positions.right_eyebrow[4][0]+2.5,positions.right_eyebrow[4][1]);
endShape();
}else {
translate(shift_face_x*0.7,shift_face_y*0.6);
noFill();
beginShape();
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[2][0],positions.left_eyebrow[2][1]);
curveVertex(positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]);
curveVertex(positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]);
endShape();
beginShape();
curveVertex(positions.right_eyebrow[0][0]+2.5,positions.right_eyebrow[0][1]);
curveVertex(positions.right_eyebrow[0][0]+2.5,positions.right_eyebrow[0][1]);
curveVertex(positions.right_eyebrow[2][0]+2.5,positions.right_eyebrow[2][1]);
curveVertex(positions.right_eyebrow[4][0]+2.5,positions.right_eyebrow[4][1]);
curveVertex(positions.right_eyebrow[4][0]+2.5,positions.right_eyebrow[4][1]);
endShape();
}
pop();
//draw hair
push();
strokeWeight(1.2);
scale(3.3);
if (hair_setting == 0){
if (hair_colour == 0){
stroke(hc1);
}else if (hair_colour == 1){
stroke(hc2);
}else if (hair_colour ==2){
stroke(hc3)
}else{
stroke(hc1);
}
strokeWeight(0.7);
line(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1], positions.right_eyebrow[4][0],positions.right_eyebrow[4][1]);
}else if (hair_setting == 1){
if (hair_colour == 0){
fill(hc1);
}else if (hair_colour == 1){
fill(hc2);
}else if (hair_colour ==2){
fill(hc3)
}else if (hair_colour ==3){
fill(hc4);
}else if (hair_colour ==4){
fill(hc5);
}else{
fill(hc6);
}
strokeWeight(0.2)
strokeJoin(ROUND);
beginShape();
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[0][0]-0.4,positions.left_eyebrow[0][1]-0.6);
curveVertex(positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]-0.8);
curveVertex(positions.right_eyebrow[3][0]+0.4,positions.right_eyebrow[3][1]-0.6);
curveVertex(positions.right_eyebrow[4][0], positions.right_eyebrow[4][1]);
curveVertex(positions.right_eyebrow[4][0], positions.right_eyebrow[4][1]);
endShape(CLOSE);
}else if (hair_setting == 2){
if (hair_colour == 0){
fill(hc1);
}else if (hair_colour == 1){
fill(hc2);
}else if (hair_colour ==2){
fill(hc3)
}else if (hair_colour ==3){
fill(hc4);
}else if (hair_colour ==4){
fill(hc5);
}else{
fill(hc6);
}
strokeWeight(0.2)
strokeJoin(ROUND);
beginShape();
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[2][0]-0.8,positions.left_eyebrow[2][1]-1.2);
curveVertex(positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]-1.6);
curveVertex(positions.right_eyebrow[3][0]+0.8,positions.right_eyebrow[3][1]-0.6);
curveVertex(positions.right_eyebrow[4][0],positions.right_eyebrow[4][1]);
curveVertex(positions.right_eyebrow[4][0],positions.right_eyebrow[4][1]);
endShape(CLOSE);
}else if (hair_setting == 3){
if (hair_colour == 0){
fill(hc1);
}else if (hair_colour == 1){
fill(hc2);
}else if (hair_colour ==2){
fill(hc3)
}else if (hair_colour ==3){
fill(hc4);
}else if (hair_colour ==4){
fill(hc5);
}else{
fill(hc6);
}
strokeWeight(0.2)
strokeJoin(ROUND);
beginShape();
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[1][0]-0.3,positions.left_eyebrow[1][1]-0.8);
curveVertex(positions.left_eyebrow[2][0]+0.3,positions.left_eyebrow[2][1]-0.6);
curveVertex(positions.left_eyebrow[3][0]+0.4,positions.left_eyebrow[3][1]-0.5);
curveVertex(positions.left_eyebrow[4][0]+0.2,positions.left_eyebrow[4][1]-1.2);
curveVertex(positions.right_eyebrow[0][0]+0.6,positions.right_eyebrow[0][1]-0.6);
curveVertex(positions.right_eyebrow[1][0]+0.6,positions.right_eyebrow[1][1]-0.6);
curveVertex(positions.right_eyebrow[2][0]+0.4,positions.right_eyebrow[2][1]-0.8);
curveVertex(positions.right_eyebrow[3][0]+2, positions.right_eyebrow[3][1]+2);
curveVertex(positions.right_eyebrow[4][0]+2.5, positions.right_eyebrow[4][1]+1.2);
curveVertex(positions.right_eyebrow[4][0]+2, positions.right_eyebrow[4][1]+2);
curveVertex(positions.right_eyebrow[4][0],positions.right_eyebrow[4][1]);
curveVertex(positions.right_eyebrow[4][0],positions.right_eyebrow[4][1]);
endShape(CLOSE);
}else if (hair_setting == 4) {
if (hair_colour == 0){
fill(hc1);
}else if (hair_colour == 1){
fill(hc2);
}else if (hair_colour ==2){
fill(hc3)
}else if (hair_colour ==3){
fill(hc4);
}else if (hair_colour ==4){
fill(hc5);
}else{
fill(hc6);
}
strokeWeight(0.2)
strokeJoin(ROUND);
beginShape();
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[0][0],positions.left_eyebrow[0][1]);
curveVertex(positions.left_eyebrow[3][0]-0.2,positions.left_eyebrow[3][1]-0.4);
curveVertex(positions.left_eyebrow[3][0]-0.3,positions.left_eyebrow[3][1]-0.6);
curveVertex(positions.left_eyebrow[2][0]-0.4,positions.left_eyebrow[2][1]-0.8);
curveVertex(positions.left_eyebrow[4][0],positions.left_eyebrow[4][1]-1.8);
curveVertex(positions.right_eyebrow[0][0]+0.6,positions.right_eyebrow[0][1]-0.5);
curveVertex(positions.right_eyebrow[1][0]+0.4,positions.right_eyebrow[1][1]-0.5);
curveVertex(positions.right_eyebrow[2][0]+0.2,positions.right_eyebrow[2][1]-0.8);
curveVertex(positions.right_eyebrow[4][0],positions.right_eyebrow[4][1]);
curveVertex(positions.right_eyebrow[4][0],positions.right_eyebrow[4][1]);
endShape(CLOSE);
}else {
if (hair_colour == 0){
stroke(hc1);
}else if (hair_colour == 1){
stroke(hc2);
}else{
stroke(hc3);
}
noFill();
translate(0,shift_face_y*0.15);
arc(positions.left_eyebrow[2][0], positions.left_eyebrow[2][1],1.5,0.3,0,180,open);
arc(positions.right_eyebrow[2][0], positions.right_eyebrow[2][1],1.5,0.3,0,180,open);
}
pop();
//draw decorations (tatoo,headwear,etc)
push();
translate(shift_face_x*2.2, shift_face_y*2.6);
if (symbol_value == 0){
fill("#f20530")
stroke("#730217");
let radius = 10;
beginShape();
angleMode(RADIANS);
for(let i = 0; i<10; i++) {
var x = cos(radians(i * 18*2)) * radius*0.32;
var y = sin(radians(i * 18*2)) * radius*0.32;
vertex(x, y-2.2);
if (radius == 10) {
radius = 5;
}else{
radius = 10;
}
}
endShape(CLOSE);
}else if (symbol_value == 1){
fill("#4895d9");
stroke("#052da6");
let radius = 10;
beginShape();
angleMode(RADIANS);
for(let i = 0; i<10; i++) {
var x = cos(radians(i * 18*8)) * radius*0.32;
var y = sin(radians(i * 18*8)) * radius*0.32;
vertex(x, y-2.2);
if (radius == 10) {
radius = 5;
}else{
radius = 10;
}
}endShape(CLOSE);
}else if (symbol_value == 2){
fill("#f2f2f2");
stroke("#8c8984");
let radius = 10;
beginShape();
angleMode(RADIANS);
for(let i = 0; i<10; i++) {
var x = cos(radians(i * 18*9)) * radius*0.32;
var y = sin(radians(i * 18*9)) * radius*0.32;
vertex(x, y-2.2);
if (radius == 10) {
radius = 5;
}else{
radius = 10;
}
}
endShape(CLOSE);
}else if (symbol_value == 3){
translate(-shift_face_x*2.2, -shift_face_y*1.3);
fill("#000000");
noStroke();
ellipse(positions.nose_tip[4][0], positions.nose_bridge[0][1],0.6,3);
ellipse(positions.nose_tip[4][0], positions.nose_bridge[0][1],3,0.6);
}else if (symbol_value == 4){
translate(-shift_face_x*2.2, -shift_face_y*1.8);
fill("#000000");
noStroke();
ellipse(positions.nose_tip[3][0], positions.nose_bridge[0][1],0.6,3.1);
ellipse(positions.nose_tip[3][0], 2*positions.nose_bridge[0][1],1,0.5);
}else if (symbol_value == 5){
translate(-shift_face_x*2, -shift_face_y*1.8);
noFill()
stroke("#000000");
rectMode(CENTER);
rect(positions.nose_tip[4][0], positions.nose_bridge[0][1],1.5,2.5,1,1,1,1);
fill("#000000");
noStroke();
ellipse(positions.nose_tip[4][0], positions.nose_bridge[0][1],0.6,3.1);
ellipse(positions.nose_tip[4][0], 2*positions.nose_bridge[0][1],1,0.5);
}else{
translate(shift_face_x*0.4, -shift_face_y*0.2);
fill("#f29bb2")
stroke("#f24472")
angleMode(RADIANS);
strokeJoin(ROUND);
// triangle(positions.right_eyebrow[0][0],positions.right_eyebrow[0][1],positions.right_eyebrow[0][0]-3,positions.right_eyebrow[0][1]-2.5,positions.right_eyebrow[0][0]-3,positions.right_eyebrow[0][1]+2.5);
arc(positions.right_eyebrow[0][0],positions.right_eyebrow[0][1],8,4,PI-0.6*QUARTER_PI,PI+0.6*QUARTER_PI,PIE);
arc(positions.right_eyebrow[0][0],positions.right_eyebrow[0][1],8,4,0-0.6*QUARTER_PI,0+0.6*QUARTER_PI,PIE);
ellipse(positions.right_eyebrow[0][0],positions.right_eyebrow[0][1],2,1.6);
fill("#f24472");
ellipse(positions.right_eyebrow[0][0],positions.right_eyebrow[0][1],0.4,1.55);
}
pop();
angleMode(DEGREES);
//draw Mouth area
push();
fill("#000000")
stroke(0);
if (eye_setting == 0) {
translate(0,-shift_face_y*1.5);
noFill()
beginShape();
vertex(positions.top_lip[0][0],positions.top_lip[0][1]);
vertex(positions.top_lip[3][0],positions.top_lip[3][1]);
vertex(positions.top_lip[6][0],positions.top_lip[6][1]);
endShape();
}else if (eye_setting == 1){
translate(0,-shift_face_y*1.5);
fill("#f9a603")
beginShape();
curveVertex(positions.bottom_lip[0][0],positions.bottom_lip[0][1]);
curveVertex(positions.bottom_lip[0][0],positions.bottom_lip[0][1]);
curveVertex(positions.bottom_lip[3][0],positions.bottom_lip[3][1]);
curveVertex(positions.bottom_lip[6][0],positions.bottom_lip[6][1]);
curveVertex(positions.bottom_lip[6][0],positions.bottom_lip[6][1]);
endShape();
}else if(eye_setting == 2){
translate(0,-shift_face_y*1.5);
noFill()
beginShape();
vertex(positions.top_lip[0][0],positions.top_lip[0][1]);
vertex(positions.top_lip[3][0],positions.top_lip[3][1]);
vertex(positions.top_lip[6][0],positions.top_lip[6][1]);
endShape();
}else {
translate(0,-shift_face_y*1.5);
fill("#f20530");
beginShape();
curveVertex(positions.bottom_lip[0][0],positions.bottom_lip[0][1]);
curveVertex(positions.bottom_lip[0][0],positions.bottom_lip[0][1]);
curveVertex(positions.bottom_lip[3][0],positions.bottom_lip[3][1]);
curveVertex(positions.bottom_lip[6][0],positions.bottom_lip[6][1]);
curveVertex(positions.bottom_lip[6][0],positions.bottom_lip[6][1]);
endShape();
}
pop();
//draw beard area
push();
if (beard_setting == 0) {
} else if (beard_setting == 1) {
fill("#000000");
beginShape();
scale(3.3);
curveVertex(positions.chin[5][0],positions.chin[5][1]);
curveVertex(positions.chin[5][0],positions.chin[5][1]);
curveVertex(positions.chin[6][0],positions.chin[6][1]);
curveVertex(positions.chin[7][0],positions.chin[7][1]);
curveVertex(positions.chin[8][0],positions.chin[8][1]);
curveVertex(positions.chin[9][0],positions.chin[9][1]);
curveVertex(positions.chin[10][0],positions.chin[10][1]);
curveVertex(positions.chin[11][0],positions.chin[11][1]);
curveVertex(positions.chin[11][0],positions.chin[11][1]);
endShape();
} else if (beard_setting == 2) {
translate(0,-shift_face_y*2.5);
fill("#141a26");
strokeWeight(0.6)
stroke("#141a26");
arc(positions.top_lip[3][0],positions.top_lip[3][1],1.5,0.7,0,180,CHORD);
}
pop();
pop();
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.hair_setting = int(map(settings[0], 0, 100, 0, 5.1));
this.face_setting = int(map(settings[1], 0, 100, 0, 3.1));
this.nose_setting = int(map(settings[2], 0, 100, 0, 3));
this.symbol_value = int(map(settings[3], 0, 100, 0, 6.1));
this.eye_setting = int(map(settings[4], 0, 100, 0, 4.1));
this.beard_setting = int(map(settings[5], 0, 100, 0, 2.1));
this.hair_colour = int(map(settings[6],0, 100, 0,5.1));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(7);
settings[0] = int(map(this.hair_setting , 0, 5.1, 0, 100) + 50/5.1);
settings[1] = int(map(this.face_setting , 0, 3.1, 0, 100) + 50/3.1);
settings[2] = int(map(this.nose_setting , 0, 3, 0, 100) + 50/3);
settings[3] = int(map(this.symbol_value , 0, 6.1, 0, 100) + 50/6.1);
settings[4] = int(map(this.eye_setting , 0, 4.1,0,100) + 50/4.1);
settings[5] = int(map(this.beard_setting , 0, 2.1,0,100) + 50/2.1);
settings[6] = int(map(this.hair_colour , 0, 5.1,0,100) + 50/5.1);
return settings;
}
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// other variables can be in here too
// these control the colors used
const stroke_color = [95, 52, 8];
function Face() {
// state variables for a face
this.cheek_size = 0;
this.cheek_colour = 0;
this.face_colour = 0;
this.lip_colour = 0;
this.eyelid_colour = 0;
//-----------------------------------
this.cheek_colour = ["#ffd1d1", "#ffb5b5", "#ffc1a6", "#fcb6e9", "#ffe6f2"];
this.face_colour = ["#ffe9de", "#ffe3c2", "#fcd7c7", "#eba386", "#b37156"];
this.lip_colour = ["#ff5c5c", "#fc8686", "#ffb3b3", "#ffc2e5", "#fa98d0", "#bf3459"];
this.eyelid_colour =["#ff9696", "#ff7070", "#f5abff", "#945f9c", "#fca2cd", "#ffd9eb", "#ad6a89"];
/*
* Draw a face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function (positions) {
//----------------------------
// FACE SHAPE
//----------------------------
stroke(0);
strokeWeight(0.07)
fill(this.face_colour[this.skin_tone]);
beginShape();
for(let i = 0; i < positions.chin.length; i++) {
curveVertex(positions.chin[i][0], positions.chin[i][1]);
curveVertex(positions.chin[i][0], positions.chin[i][1]);
}
for(let i = 4; i >= 0; i--) {
curveVertex(positions.right_eyebrow[i][0], positions.right_eyebrow[i][1]);
}
for(let i = 4; i >= 0; i--) {
curveVertex(positions.left_eyebrow[i][0], positions.left_eyebrow[i][1]);
}
curveVertex(positions.chin[1][0], positions.chin[0][1]);
curveVertex(positions.chin[0][0], positions.chin[0][1]);
curveVertex(positions.chin[0][0], positions.chin[0][1]);
endShape();
//------------------------------
// CHEEKS
//------------------------------
noStroke();
fill(this.cheek_colour[this.blush]);
// LEFT CHEEK
let left_cheek = average_point(positions.left_eye);
let right_cheek = average_point(positions.right_eye);
let cheek_sizes = [left_cheek[0]*0.75, left_cheek[0], left_cheek[0]*1.3];
if(this.cheek_size == 0) {
ellipse(left_cheek[0], left_cheek[1] + 0.8, cheek_sizes[this.cheek_size],
cheek_sizes[this.cheek_size]);
ellipse(right_cheek[0], right_cheek[1] + 0.8, cheek_sizes[this.cheek_size],
cheek_sizes[this.cheek_size]);
}
else if(this.cheek_size == 1) {
ellipse(left_cheek[0], left_cheek[1] + 0.8, cheek_sizes[this.cheek_size],
cheek_sizes[this.cheek_size]);
ellipse(right_cheek[0], right_cheek[1] + 0.8, cheek_sizes[this.cheek_size],
cheek_sizes[this.cheek_size]);
}
else if(this.cheek_size == 2) {
ellipse(left_cheek[0], left_cheek[1] + 0.8, cheek_sizes[this.cheek_size],
cheek_sizes[this.cheek_size]);
ellipse(right_cheek[0], right_cheek[1] + 0.8, cheek_sizes[this.cheek_size],
cheek_sizes[this.cheek_size]);
}
//------------------------------
// EYEBROWS
//------------------------------
fill(0);
stroke(0);
strokeWeight(0.07);
// LEFT EYEBROW
beginShape();
for(let i = 1; i < positions.left_eyebrow.length; i++) {
curveVertex(positions.left_eyebrow[i][0], positions.left_eyebrow[i][1]);
curveVertex(positions.left_eyebrow[i][0], positions.left_eyebrow[i][1]);
}
endShape();
// RIGHT EYEBROW
beginShape();
for(let i = 0; i < 4; i++) {
curveVertex(positions.right_eyebrow[i][0], positions.right_eyebrow[i][1]);
curveVertex(positions.right_eyebrow[i][0], positions.right_eyebrow[i][1]);
}
endShape();
//----------------------------
// EYELIDS
//----------------------------
let left_eyelid = average_point(positions.left_eye);
let right_eyelid = average_point(positions.right_eye);
noStroke();
fill(this.eyelid_colour[this.eyeshadow]);
arc(left_eyelid[0] + 0.03, left_eyelid[1] + 0.03, 0.6, 0.6, 180, 360);
arc(right_eyelid[0] + 0.03, right_eyelid[1] + 0.03, 0.6, 0.6, 180, 360);
//----------------------------
// EYE SHAPE
//----------------------------
fill(255);
stroke(0);
strokeWeight(0.05);
// LEFT EYE
beginShape();
for(let i = 0; i < positions.left_eye.length; i++) {
curveVertex(positions.left_eye[i][0], positions.left_eye[i][1]);
curveVertex(positions.left_eye[i][0], positions.left_eye[i][1]);
}
curveVertex(positions.left_eye[0][0], positions.left_eye[0][1]);
curveVertex(positions.left_eye[0][0], positions.left_eye[0][1]);
endShape();
//------------------
// RIGHT EYE
beginShape();
for(let i = 0; i < positions.left_eye.length; i++) {
curveVertex(positions.right_eye[i][0], positions.right_eye[i][1]);
curveVertex(positions.right_eye[i][0], positions.right_eye[i][1]);
}
curveVertex(positions.right_eye[0][0], positions.right_eye[0][1]);
curveVertex(positions.right_eye[0][0], positions.right_eye[0][1]);
endShape();
//----------------------------
// IRIS
//----------------------------
let left_eye = average_point(positions.left_eye);
let right_eye = average_point(positions.right_eye);
noStroke();
fill(0);
ellipse(left_eye[0], left_eye[1], 0.2, 0.15);
ellipse(right_eye[0], right_eye[1], 0.2, 0.15);
//----------------------------
// TEETH
//----------------------------
fill(255);
noStroke();
beginShape();
for(let i = 0; i < 7; i++) {
curveVertex(positions.top_lip[i][0], positions.top_lip[i][1]);
curveVertex(positions.top_lip[i][0], positions.top_lip[i][1]);
}
for(let i = 0; i < 7; i++) {
curveVertex(positions.bottom_lip[i][0], positions.bottom_lip[i][1]);
curveVertex(positions.bottom_lip[i][0], positions.bottom_lip[i][1]);
}
endShape();
//----------------------------
// TOP LIP
//----------------------------
fill(this.lip_colour[this.lipstick]);
noStroke();
beginShape();
for(let i = 0; i < positions.top_lip.length; i++) {
curveVertex(positions.top_lip[i][0], positions.top_lip[i][1]);
curveVertex(positions.top_lip[i][0], positions.top_lip[i][1]);
}
curveVertex(positions.top_lip[0][0], positions.top_lip[0][1]);
curveVertex(positions.top_lip[0][0], positions.top_lip[0][1]);
endShape();
//-------------------------------
// BOTTOM LIP
//-------------------------------
beginShape();
for (let i = 0; i < positions.bottom_lip.length; i++) {
curveVertex(positions.bottom_lip[i][0], positions.bottom_lip[i][1]);
curveVertex(positions.bottom_lip[i][0], positions.bottom_lip[i][1]);
}
curveVertex(positions.bottom_lip[0][0], positions.bottom_lip[0][1]);
curveVertex(positions.bottom_lip[0][0], positions.bottom_lip[0][1]);
endShape();
//-------------------------------
// NOSE BRIDGE
//-------------------------------
noFill();
stroke(0);
strokeWeight(0.08);
beginShape();
curveVertex(positions.nose_bridge[0][0], positions.nose_bridge[0][0]);
curveVertex(positions.nose_bridge[0][0], positions.nose_bridge[0][1]);
curveVertex(positions.nose_bridge[1][0], positions.nose_bridge[1][1]);
curveVertex(positions.nose_bridge[2][0], positions.nose_bridge[2][1]);
curveVertex(positions.nose_bridge[3][0], positions.nose_bridge[3][1]);
endShape();
//-------------------------------
// NOSE TIP
//-------------------------------
stroke(0);
strokeWeight(0.08);
beginShape();
curveVertex(positions.nose_tip[0][0], positions.nose_tip[0][1] -0.1);
curveVertex(positions.nose_tip[1][0], positions.nose_tip[1][1] -0.1);
curveVertex(positions.nose_tip[2][0], positions.nose_tip[2][1] -0.1);
curveVertex(positions.nose_tip[3][0], positions.nose_tip[3][1] -0.1);
curveVertex(positions.nose_tip[4][0], positions.nose_tip[4][1] -0.1);
endShape();
}
//------------------------------------
/* set internal properties based on list numbers 0-100 */
this.setProperties = function (settings) {
this.cheek_size = int(map(settings[0], 0, 100, 0, 2));
this.blush = int(map(settings[1], 0, 100, 0, 4));
this.skin_tone = int(map(settings[2], 0, 100, 0, 4));
this.lipstick = int(map(settings[3], 0, 100, 0, 5));
this.eyeshadow = int(map(settings[4], 0, 100, 0, 6));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function () {
let settings = new Array(5);
settings[0] = map(this.cheek_size, 0, 2, 0, 100);
settings[1] = map(this.blush, 0, 4, 0, 100);
settings[2] = map(this.skin_tone, 0, 4, 0, 100);
settings[3] = map(this.lipstick, 0, 5, 0, 100);
settings[4] = map(this.eyeshadow, 0, 6, 0, 100);
return settings;
}
}
// given an array of [x,y] points, return the average
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for (var i = 0; i < list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
/*
* FaceMap class - holds all informaiton about one mapped
* face and is able to draw itself.
*/
// other variables can be in here too
// these control the colors used
const bg_color = [225, 206, 187];
const fg_color = [151, 102, 52];
const stroke_color = [95, 52, 8];
// skin colors
let outLine1 = '#F2C7A9';
let skin1 = '#FDF0E7'; // linen
let skinLt1 = 'FEF9F6' // snow
let outLine2 = '#CC7A51';
let skin2 = '#FBBB9B'; // peach-orange
let skinLt2 = '#FDDDCD'; // unbleached silk
let outLine3 = '#9C531D';
let skin3 = '#F58D3F'; // tyger's eye
let skinLt3 = '#FBD1B2'; // apricot
let outLine4 = '#723502';
let skin4 = '#B25303'; // windsor tan
let skinLt4 = '#DCB08C'; // tumbleweed
let outLine5 = '#451405';
let skin5 = '#6C1E07'; // kenyan copper
let skinLt5 = '#D6C1BB'; // pale silver
let outLine;
let skinColor;
let skinLt;
// mouth colors
let mouthColor = '#BA2E2E';
function Face() {
// these are state variables for a face
// variables change from 0 - 1
this.skin = 2;
this.eyeOpenL = 0.5;
this.eyeOpenR = 0.5;
this.earL = 0.5;
this.earR = 0.5;
this.gender = 1;
this.blush = 1;
this.freckles = 1;
this.mouthOpen = 0;
/*
* Draw a face with position lists that include:
* chin, right_eye, left_eye, right_eyebrow, left_eyebrow
* bottom_lip, top_lip, nose_tip, nose_bridge,
*/
this.draw = function(positions) {
// vars
// eyes positon
let eyePosL = average_point(positions.left_eye);
let eyePosR = average_point(positions.right_eye);
// chin position
let chinLs = [positions.chin[7], positions.chin[8], positions.chin[9]];
let chinBt = average_point(chinLs);
// nose position
let nose = average_point(positions.nose_tip);
// mouth position
let mouthUp = average_point(positions.top_lip);
let mouthDw = average_point(positions.bottom_lip);
// overall face width
let faceWidth = abs(positions.chin[0][0] - positions.chin[16][0]);
let faceScaleX = map(faceWidth, 3, 4.5, 0.8, 1.1);
// center point of the face
let centerX = (eyePosL[0] + eyePosR[0]) / 2;
let centerY = (eyePosL[1] + eyePosR[1]) / 1.0;
angleMode(DEGREES);
strokeWeight(0.1);
// set up skin colours
if(this.skin == 1){
outLine = outLine1;
skinColor = skin1;
skinLt = skinLt1;
}else if(this.skin == 2){
outLine = outLine2;
skinColor = skin2;
skinLt = skinLt2;
}else if(this.skin == 3){
outLine = outLine3;
skinColor = skin3;
skinLt = skinLt3;
}else if(this.skin == 4){
outLine = outLine4;
skinColor = skin4;
skinLt = skinLt4;
}else{
outLine = outLine5;
skinColor = skin5;
skinLt = skinLt5;
}
push();
// ears
stroke(outLine);
fill(skinColor);
let earOffsetX = map(faceWidth, 3, 4.5, -0.2, 0.1);
// left ear
push();
let earRotL = map(this.earL, 0, 1, -10, 10);
translate(centerX - (1 + earOffsetX), centerY );
rotate(earRotL);
bezier(-0.7, 0.3, -0.9, -2, 0.1, -4, 0.9, 0.3);
translate(0.05, 0);
scale(0.7, 0.6);
fill(skinLt);
noStroke();
bezier(-0.7, 0.3, -0.9, -2, 0.1, -4, 0.9, 0.3);
pop();
// right ear
push();
let earRotR = map(this.earR, 0, 1, 10, -10);
translate(centerX + (1 + earOffsetX), centerY );
rotate(earRotR);
bezier(-0.9, 0.3, -0.1, -4, 0.9, -2, 0.7, 0.3);
translate(-0.05, 0);
scale(0.7, 0.6);
fill(skinLt);
noStroke();
bezier(-0.9, 0.3, -0.1, -4, 0.9, -2, 0.7, 0.3);
pop();
// face (color)
push(); //push for whole face change
translate(0, -0.1);
scale(faceScaleX, 0.9);
push();
noStroke();
fill(skinColor);
arc(0, -1.45, 3.7, 3.5, 200, 340, OPEN);
beginShape();
vertex(-1.71, - 2.11);
vertex( 1.71, - 2.11);
vertex( 2.01, chinBt[1] - 1.49);
vertex(-2.01, chinBt[1] - 1.49);
endShape();
bezier(-1.7, -2.1, -1.9, -1.9, -2.25, -0.1, -2, chinBt[1] - 1.5);
bezier( 1.7, -2.1, 1.9, -1.9, 2.25, -0.1, 2, chinBt[1] - 1.5);
bezier(-2, chinBt[1] - 1.5, -1.8, chinBt[1], 1.8, chinBt[1], 2, chinBt[1] - 1.5);
// light-color parts
fill(skinLt);
bezier(-1.6, chinBt[1] - 1.59, -1.0, -0.8, 1.0, -0.8, 1.6, chinBt[1] - 1.59);
bezier(-1.6, chinBt[1] - 1.6, -2.2, chinBt[1], 2.2, chinBt[1], 1.6, chinBt[1] - 1.6);
pop();
// face (stroke)
push();
stroke(outLine);
noFill();
arc(0, -1.45, 3.7, 3.5, 240, 250, OPEN);
arc(0, -1.45, 3.7, 3.5, 280, 295, OPEN);
arc(0, -1.45, 3.7, 3.5, 210, 215, OPEN);
arc(0, -1.45, 3.7, 3.5, 325, 330, OPEN);
bezier(-1.8, -1.8, -1.93, -1.6, -2.02, -1.3, -2.0, -1.1);
bezier(-2.0, -1.1, -2.1, -0.9, -2.15, -0.4, -2.05, -0.2);
bezier( 1.8, -1.8, 1.93, -1.6, 2.02, -1.3, 2.0, -1.1);
bezier( 2.0, -1.1, 2.1, -0.9, 2.15, -0.4, 2.05, -0.2);
bezier(-2, chinBt[1] - 1.5, -1.8, chinBt[1], 1.8, chinBt[1], 2, chinBt[1] - 1.5);
pop();
// fur
fill(skinColor);
//left cheek fur
push();
translate(-2.05, -0.08);
rotate(-90);
noStroke();
arc(0, 0, 0.2, 0.15, 180, 360, OPEN);
stroke(outLine);
arc(0, 0, 0.2, 0.15, 280, 360, OPEN);
pop();
push();
translate(-2.0, 0.25);
rotate(-95);
noStroke();
arc(0, 0, 0.35, 0.35, 180, 360, OPEN);
stroke(outLine);
arc(0, 0, 0.35, 0.35, 250, 360, OPEN);
pop();
push();
translate(-2.0, 0.45);
rotate(-95);
noStroke();
arc(0, 0, 0.15, 0.1, 180, 360, OPEN);
stroke(outLine);
arc(0, 0, 0.15, 0.1, 270, 360, OPEN);
pop();
//right cheek fur
push();
translate( 2.05, -0.08);
rotate( 90);
noStroke();
arc(0, 0, 0.2, 0.15, 180, 360, OPEN);
stroke(outLine);
arc(0, 0, 0.2, 0.15, 180, 280, OPEN);
pop();
push();
translate( 2.0, 0.25);
rotate( 95);
noStroke();
arc(0, 0, 0.35, 0.35, 180, 360, OPEN);
stroke(outLine);
arc(0, 0, 0.35, 0.35, 180, 300, OPEN);
pop();
push();
translate( 2.0, 0.45);
rotate( 95);
noStroke();
arc(0, 0, 0.15, 0.1, 180, 360, OPEN);
stroke(outLine);
arc(0, 0, 0.15, 0.1, 180, 260, OPEN);
pop();
// left ear fur
push();
translate( -1.65, -2.1);
rotate( 100);
noStroke();
arc(0, 0, 0.45, 0.4, 0, 180, OPEN);
stroke(outLine);
arc(0, 0, 0.45, 0.5, 80, 180, OPEN);
pop();
push();
translate( -1.75, -1.95);
rotate(80);
noStroke();
arc(0, 0, 0.2, 0.15, 0, 180, OPEN);
stroke(outLine);
arc(0, 0, 0.2, 0.15, 90, 180, OPEN);
pop();
// right ear fur
push();
translate( 1.65, -2.1);
rotate(80);
noStroke();
arc(0, 0, 0.45, 0.4, 180, 0, OPEN);
stroke(outLine);
arc(0, 0, 0.45, 0.5, 180, 260, OPEN);
pop();
push();
translate( 1.75, -1.95);
rotate( 100);
noStroke();
arc(0, 0, 0.2, 0.15, 180, 0, OPEN);
stroke(outLine);
arc(0, 0, 0.2, 0.15, 180, 270, OPEN);
pop();
// head-top fur
push();
translate(-0.45, -3.15);
rotate(-9);
noStroke();
arc(0, 0, 0.2, 0.15, 175, 5, OPEN);
stroke(outLine);
noFill();
arc(0, 0, 0.2, 0.15, 180, 270, OPEN);
pop();
push();
translate(-0.15, -3.18);
noStroke();
arc(0, 0, 0.4, 0.35, 175, 5, OPEN);
stroke(outLine);
noFill();
arc(0, 0, 0.4, 0.35, 190, 280, OPEN);
pop();
push();
translate(0.15, -3.15);
rotate(5);
noStroke();
arc(0, 0, 0.25, 0.2, 175, 5, OPEN);
stroke(outLine);
noFill();
arc(0, 0, 0.25, 0.2, 200, 280, OPEN);
pop();
// left up fur
push();
translate(-0.96, -2.94);
rotate(-30);
noStroke();
arc(0, 0, 0.15, 0.1, 175, 5, OPEN);
stroke(outLine);
noFill();
arc(0, 0, 0.15, 0.1, 320, 360, OPEN);
pop();
push();
translate(-1.2, -2.79);
rotate(-40);
noStroke();
arc(0, 0, 0.4, 0.35, 175, 5, OPEN);
stroke(outLine);
noFill();
arc(0, 0, 0.4, 0.35, 285, 360, OPEN);
pop();
push();
translate(-1.36, -2.62);
rotate(-45);
noStroke();
arc(0, 0, 0.28, 0.25, 175, 5, OPEN);
stroke(outLine);
noFill();
arc(0, 0, 0.28, 0.25, 300, 360, OPEN);
pop();
// right up fur
push();
translate(0.9, -2.98);
rotate(30);
noStroke();
arc(0, 0, 0.25, 0.2, 175, 5, OPEN);
stroke(outLine);
noFill();
arc(0, 0, 0.25, 0.2, 180, 280, OPEN);
pop();
push();
translate(1.2, -2.79);
rotate(40);
noStroke();
arc(0, 0, 0.4, 0.35, 175, 5, OPEN);
stroke(outLine);
noFill();
arc(0, 0, 0.4, 0.35, 185, 280, OPEN);
pop();
push();
translate(1.36, -2.62);
rotate(45);
noStroke();
arc(0, 0, 0.25, 0.2, 175, 5, OPEN);
stroke(outLine);
noFill();
arc(0, 0, 0.25, 0.2, 240, 280, OPEN);
pop();
pop(); // pop for whole face change
// eye-borws
push();
stroke(skinLt);
strokeWeight(0.15);
noFill();
translate(0, 0.1);
beginShape();
curveVertex(positions.left_eyebrow[1][0], positions.left_eyebrow[1][1]);
curveVertex(positions.left_eyebrow[2][0] + 0.08, positions.left_eyebrow[2][1]);
curveVertex(positions.left_eyebrow[3][0] - 0.08, positions.left_eyebrow[3][1]);
curveVertex(positions.left_eyebrow[4][0], positions.left_eyebrow[4][1]);
endShape();
beginShape();
curveVertex(positions.right_eyebrow[3][0], positions.right_eyebrow[3][1]);
curveVertex(positions.right_eyebrow[2][0] - 0.08, positions.right_eyebrow[2][1]);
curveVertex(positions.right_eyebrow[1][0] + 0.08, positions.right_eyebrow[1][1]);
curveVertex(positions.right_eyebrow[0][0], positions.right_eyebrow[0][1]);
endShape();
pop();
push();
noFill();
beginShape();
curveVertex(positions.left_eyebrow[1][0], positions.left_eyebrow[1][1]);
curveVertex(positions.left_eyebrow[2][0], positions.left_eyebrow[2][1]);
curveVertex(positions.left_eyebrow[3][0], positions.left_eyebrow[3][1]);
curveVertex(positions.left_eyebrow[4][0], positions.left_eyebrow[4][1]);
endShape();
beginShape();
curveVertex(positions.right_eyebrow[3][0], positions.right_eyebrow[3][1]);
curveVertex(positions.right_eyebrow[2][0], positions.right_eyebrow[2][1]);
curveVertex(positions.right_eyebrow[1][0], positions.right_eyebrow[1][1]);
curveVertex(positions.right_eyebrow[0][0], positions.right_eyebrow[0][1]);
endShape();
pop();
// left eye
push();
translate(eyePosL[0] - 0.05, eyePosL[1] + 0.1);
noStroke();
let eyeLipL = map (this.eyeOpenL, 0, 1, -0.09, 0.12);
// eye base
let fixerL = map(this.eyeOpenL, 0, 1, - 0.5, - 0.3);
noStroke();
fill(skinLt);
arc(0, 0, 0.6, 0.5, 0, 180);
bezier(- 0.3, 0, -0.32, fixerL, 0.32, fixerL, 0.3, 0);
// pupil
fill(10);
ellipse(0, 0, 0.5);
// eye-lip
push();
stroke(10);
strokeWeight(0.08);
noFill();
rotate(-5);
arc(0, -0.15 + eyeLipL, 0.6, 0.4, 200, 340);
// eye-lash
if(this.gender == 0){
// female, eye-lashes
arc(-0.04, -0.4 + eyeLipL, 0.5, 0.5, 148, 165);
}else{
// male, nothing
}
pop();
// fixer
noStroke();
let fixL1 = map (this.eyeOpenL, 0, 1, 180, 269);
let fixL2 = map (this.eyeOpenL, 0, 1, 360, 270);
pop();
// right eye
push();
translate(eyePosR[0] + 0.05, eyePosR[1] + 0.1);
noStroke();
let eyeLipR = map (this.eyeOpenR, 0, 1, -0.09, 0.12);
// eye base
let fixerR = map(this.eyeOpenR, 0, 1, - 0.5, - 0.3);
noStroke();
fill(skinLt);
arc(0, 0, 0.6, 0.5, 0, 180);
bezier(- 0.3, 0, -0.32, fixerR, 0.32, fixerR, 0.3, 0);
// pupil
fill(10);
ellipse(0, 0, 0.5);
// eye-lip
push();
stroke(10);
strokeWeight(0.08);
noFill();
rotate(5);
arc(0, -0.15 + eyeLipR, 0.6, 0.4, 200, 340);
// eye-lash
if(this.gender == 0){
// female, eye-lashes
arc( 0.04, -0.4 + eyeLipR, 0.5, 0.5, 10, 27);
}else{
// male, nothing
}
pop();
pop();
// nose
push();
noStroke();
strokeJoin(ROUND);
fill(10);
push();
translate(nose[0] - 0.05, nose[1]);
rotate(-45);
arc(0, 0, 0.25, 0.4, 180, 360, OPEN);
pop();
push();
translate(nose[0] + 0.05, nose[1]);
rotate( 45);
arc(0, 0, 0.25, 0.4, 180, 360, OPEN);
pop();
push();
translate(nose[0], nose[1] + 0.04);
arc(0, 0, 0.31, 0.2, 0, 180, OPEN);
pop();
quad(nose[0] - 0.15, nose[1] - 0.15, nose[0] + 0.15, nose[1] - 0.15, nose[0] + 0.1, nose[1] + 0.05, nose[0] - 0.1, nose[1] + 0.05);
pop();
// mouth
let mouthDis = abs(mouthUp[1] - mouthDw[1]);
push();
translate(mouthUp[0], mouthUp[1]);
noStroke();
fill(mouthColor);
arc(0, 0.01, 0.6, mouthDis * 2, 10, 170, OPEN);
fill(skinLt);
stroke(10);
strokeWeight(0.08);
arc(-0.2, 0, 0.4, 0.3, 0, 170);
arc( 0.2, 0, 0.4, 0.3, 10, 180);
pop();
// gender
if(this.gender == 0){
// female
push();
translate(-1.35, -2.55);
rotate(10);
noStroke();
fill('#5fa55a');
for (let i = 0; i < 3; i ++) {
ellipse(0, 0, 0.45, 0.22);
rotate(60);
}
fill(255);
ellipse(0, 0, 0.1);
pop();
push();
translate(-1, -2.78);
noStroke();
fill('#f6d51f');
for (let i = 0; i < 3; i ++) {
ellipse(0, 0, 0.7, 0.35);
rotate(60);
}
fill(255);
ellipse(0, 0, 0.15);
pop();
push();
translate(-0.6, -2.9);
rotate(20);
noStroke();
fill('#fa8925');
for (let i = 0; i < 3; i ++) {
ellipse(0, 0, 0.45, 0.22);
rotate(60);
}
fill(255);
ellipse(0, 0, 0.1);
pop();
push();
translate( 1.2, -2.65);
rotate(20);
noStroke();
fill('#01b4bc');
for (let i = 0; i < 3; i ++) {
ellipse(0, 0, 0.45, 0.22);
rotate(60);
}
fill(255);
ellipse(0, 0, 0.1);
pop();
push();
translate( 0.8, -2.85);
rotate(15);
noStroke();
fill('#fa5457');
for (let i = 0; i < 3; i ++) {
ellipse(0, 0, 0.7, 0.35);
rotate(60);
}
fill(255);
ellipse(0, 0, 0.15);
pop();
}else{
// male
fill(50);
stroke(0);
rectMode(CENTER);
push();
translate(chinBt[0] - 0.45, chinBt[1] - 0.52);
rotate(-15);
rect(0, 0.2, 0.6, 0.28, 0.1);
rotate(20);
rect(0, 0, 0.6, 0.38, 0.1);
line(0.1, 0, 0.2, 0);
pop();
push();
translate(chinBt[0] + 0.45, chinBt[1] - 0.52);
rotate(15);
rect(0, 0.2, 0.6, 0.28, 0.1);
rotate(-20);
rect(0, 0, 0.6, 0.38, 0.1);
line(- 0.1, 0, - 0.2, 0);
pop();
rect(chinBt[0], chinBt[1] - 0.47, 0.4, 0.5, 0.1);
}
// blush
if(this.blush == 0){
push();
stroke('#EC6054');
strokeWeight(0.18);
line(nose[0] - 0.6, nose[1] - 0.35, nose[0] - 0.8, nose[1] - 0.15);
line(nose[0] - 0.9, nose[1] - 0.35, nose[0] - 1.1, nose[1] - 0.15);
line(nose[0] + 0.8, nose[1] - 0.35, nose[0] + 0.6, nose[1] - 0.15);
line(nose[0] + 1.1, nose[1] - 0.35, nose[0] + 0.9, nose[1] - 0.15);
pop();
}else{
// do not do anything
}
// freckles
if(this.freckles == 0){
push();
fill(outLine);
noStroke();
ellipse(nose[0] - 0.4, nose[1] - 0.4, 0.08);
ellipse(nose[0] - 0.6, nose[1] - 0.15, 0.08);
ellipse(nose[0] - 0.8, nose[1] - 0.35, 0.08);
ellipse(nose[0] - 1.1, nose[1] - 0.2, 0.08);
ellipse(nose[0] + 0.4, nose[1] - 0.4, 0.08);
ellipse(nose[0] + 0.6, nose[1] - 0.15, 0.08);
ellipse(nose[0] + 0.8, nose[1] - 0.35, 0.08);
ellipse(nose[0] + 1.1, nose[1] - 0.2, 0.08);
pop();
}else{
// do not do anything
}
pop();
}
/* set internal properties based on list numbers 0-100 */
this.setProperties = function(settings) {
this.skin = int(map(settings[0], 0, 100, 1, 6));
this.eyeOpenL = map(settings[1], 0, 100, 0, 1);
this.eyeOpenR = map(settings[2], 0, 100, 0, 1);
this.earL = map(settings[3], 0, 100, 0, 1);
this.earR = map(settings[4], 0, 100, 0, 1);
this.gender = int(map(settings[5], 0, 100, 0, 2));
this.blush = int(map(settings[6], 0, 100, 0, 2));
this.freckles = int(map(settings[7], 0, 100, 0, 2));
}
/* get internal properties as list of numbers 0-100 */
this.getProperties = function() {
let settings = new Array(3);
settings[0] = map(this.skin, 1, 6, 0, 100);
settings[1] = map(this.eyeOpenL, 0, 1, 0, 100);
settings[2] = map(this.eyeOpenR, 0, 1, 0, 100);
settings[3] = map(this.earL, 0, 1, 0, 100);
settings[4] = map(this.earR, 0, 1, 0, 100);
settings[5] = map(this.gender, 0, 2, 0, 100);
settings[6] = map(this.blush, 0, 2, 0, 100);
settings[7] = map(this.freckles, 0, 2, 0, 100);
return settings;
}
}
// given an array of [x,y] points, return the average
function average_point(list) {
var sum_x = 0;
var sum_y = 0;
var num_points = 0;
for(var i=0; i<list.length; i++) {
sum_x += list[i][0];
sum_y += list[i][1];
num_points += 1;
}
return [sum_x / num_points, sum_y / num_points];
}
This file has been truncated, but you can view the full file.
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.clm = factory());
}(this, (function () { 'use strict';
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var numeric1_2_6 = createCommonjsModule(function (module, exports) {
"use strict";
var numeric = exports;
if(typeof commonjsGlobal !== "undefined") { commonjsGlobal.numeric = numeric; }
numeric.version = "1.2.6";
// 1. Utility functions
numeric.bench = function bench (f,interval) {
var t1,t2,n,i;
if(typeof interval === "undefined") { interval = 15; }
n = 0.5;
t1 = new Date();
while(1) {
n*=2;
for(i=n;i>3;i-=4) { f(); f(); f(); f(); }
while(i>0) { f(); i--; }
t2 = new Date();
if(t2-t1 > interval) break;
}
for(i=n;i>3;i-=4) { f(); f(); f(); f(); }
while(i>0) { f(); i--; }
t2 = new Date();
return 1000*(3*n-1)/(t2-t1);
};
numeric._myIndexOf = (function _myIndexOf(w) {
var n = this.length,k;
for(k=0;k<n;++k) if(this[k]===w) return k;
return -1;
});
numeric.myIndexOf = (Array.prototype.indexOf)?Array.prototype.indexOf:numeric._myIndexOf;
numeric.Function = Function;
numeric.precision = 4;
numeric.largeArray = 50;
numeric.prettyPrint = function prettyPrint(x) {
function fmtnum(x) {
if(x === 0) { return '0'; }
if(isNaN(x)) { return 'NaN'; }
if(x<0) { return '-'+fmtnum(-x); }
if(isFinite(x)) {
var scale = Math.floor(Math.log(x) / Math.log(10));
var normalized = x / Math.pow(10,scale);
var basic = normalized.toPrecision(numeric.precision);
if(parseFloat(basic) === 10) { scale++; normalized = 1; basic = normalized.toPrecision(numeric.precision); }
return parseFloat(basic).toString()+'e'+scale.toString();
}
return 'Infinity';
}
var ret = [];
function foo(x) {
var k;
if(typeof x === "undefined") { ret.push(Array(numeric.precision+8).join(' ')); return false; }
if(typeof x === "string") { ret.push('"'+x+'"'); return false; }
if(typeof x === "boolean") { ret.push(x.toString()); return false; }
if(typeof x === "number") {
var a = fmtnum(x);
var b = x.toPrecision(numeric.precision);
var c = parseFloat(x.toString()).toString();
var d = [a,b,c,parseFloat(b).toString(),parseFloat(c).toString()];
for(k=1;k<d.length;k++) { if(d[k].length < a.length) a = d[k]; }
ret.push(Array(numeric.precision+8-a.length).join(' ')+a);
return false;
}
if(x === null) { ret.push("null"); return false; }
if(typeof x === "function") {
ret.push(x.toString());
var flag = false;
for(k in x) { if(x.hasOwnProperty(k)) {
if(flag) ret.push(',\n');
else ret.push('\n{');
flag = true;
ret.push(k);
ret.push(': \n');
foo(x[k]);
} }
if(flag) ret.push('}\n');
return true;
}
if(x instanceof Array) {
if(x.length > numeric.largeArray) { ret.push('...Large Array...'); return true; }
var flag = false;
ret.push('[');
for(k=0;k<x.length;k++) { if(k>0) { ret.push(','); if(flag) ret.push('\n '); } flag = foo(x[k]); }
ret.push(']');
return true;
}
ret.push('{');
var flag = false;
for(k in x) { if(x.hasOwnProperty(k)) { if(flag) ret.push(',\n'); flag = true; ret.push(k); ret.push(': \n'); foo(x[k]); } }
ret.push('}');
return true;
}
foo(x);
return ret.join('');
};
numeric.parseDate = function parseDate(d) {
function foo(d) {
if(typeof d === 'string') { return Date.parse(d.replace(/-/g,'/')); }
if(!(d instanceof Array)) { throw new Error("parseDate: parameter must be arrays of strings"); }
var ret = [],k;
for(k=0;k<d.length;k++) { ret[k] = foo(d[k]); }
return ret;
}
return foo(d);
};
numeric.parseFloat = function parseFloat_(d) {
function foo(d) {
if(typeof d === 'string') { return parseFloat(d); }
if(!(d instanceof Array)) { throw new Error("parseFloat: parameter must be arrays of strings"); }
var ret = [],k;
for(k=0;k<d.length;k++) { ret[k] = foo(d[k]); }
return ret;
}
return foo(d);
};
numeric.parseCSV = function parseCSV(t) {
var foo = t.split('\n');
var j,k;
var ret = [];
var pat = /(([^'",]*)|('[^']*')|("[^"]*")),/g;
var patnum = /^\s*(([+-]?[0-9]+(\.[0-9]*)?(e[+-]?[0-9]+)?)|([+-]?[0-9]*(\.[0-9]+)?(e[+-]?[0-9]+)?))\s*$/;
var stripper = function(n) { return n.substr(0,n.length-1); };
var count = 0;
for(k=0;k<foo.length;k++) {
var bar = (foo[k]+",").match(pat),baz;
if(bar.length>0) {
ret[count] = [];
for(j=0;j<bar.length;j++) {
baz = stripper(bar[j]);
if(patnum.test(baz)) { ret[count][j] = parseFloat(baz); }
else ret[count][j] = baz;
}
count++;
}
}
return ret;
};
numeric.toCSV = function toCSV(A) {
var s = numeric.dim(A);
var i,j,m,n,row,ret;
m = s[0];
n = s[1];
ret = [];
for(i=0;i<m;i++) {
row = [];
for(j=0;j<m;j++) { row[j] = A[i][j].toString(); }
ret[i] = row.join(', ');
}
return ret.join('\n')+'\n';
};
numeric.getURL = function getURL(url) {
var client = new XMLHttpRequest();
client.open("GET",url,false);
client.send();
return client;
};
numeric.imageURL = function imageURL(img) {
function base64(A) {
var n = A.length, i,x,y,z,p,q,r,s;
var key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var ret = "";
for(i=0;i<n;i+=3) {
x = A[i];
y = A[i+1];
z = A[i+2];
p = x >> 2;
q = ((x & 3) << 4) + (y >> 4);
r = ((y & 15) << 2) + (z >> 6);
s = z & 63;
if(i+1>=n) { r = s = 64; }
else if(i+2>=n) { s = 64; }
ret += key.charAt(p) + key.charAt(q) + key.charAt(r) + key.charAt(s);
}
return ret;
}
function crc32Array (a,from,to) {
if(typeof from === "undefined") { from = 0; }
if(typeof to === "undefined") { to = a.length; }
var table = [0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D];
var crc = -1, y = 0, n = a.length,i;
for (i = from; i < to; i++) {
y = (crc ^ a[i]) & 0xFF;
crc = (crc >>> 8) ^ table[y];
}
return crc ^ (-1);
}
var h = img[0].length, w = img[0][0].length, s1, s2, next,k,length,a,b,i,j,adler32,crc32;
var stream = [
137, 80, 78, 71, 13, 10, 26, 10, // 0: PNG signature
0,0,0,13, // 8: IHDR Chunk length
73, 72, 68, 82, // 12: "IHDR"
(w >> 24) & 255, (w >> 16) & 255, (w >> 8) & 255, w&255, // 16: Width
(h >> 24) & 255, (h >> 16) & 255, (h >> 8) & 255, h&255, // 20: Height
8, // 24: bit depth
2, // 25: RGB
0, // 26: deflate
0, // 27: no filter
0, // 28: no interlace
-1,-2,-3,-4, // 29: CRC
-5,-6,-7,-8, // 33: IDAT Chunk length
73, 68, 65, 84, // 37: "IDAT"
// RFC 1950 header starts here
8, // 41: RFC1950 CMF
29 // 42: RFC1950 FLG
];
crc32 = crc32Array(stream,12,29);
stream[29] = (crc32>>24)&255;
stream[30] = (crc32>>16)&255;
stream[31] = (crc32>>8)&255;
stream[32] = (crc32)&255;
s1 = 1;
s2 = 0;
for(i=0;i<h;i++) {
if(i<h-1) { stream.push(0); }
else { stream.push(1); }
a = (3*w+1+(i===0))&255; b = ((3*w+1+(i===0))>>8)&255;
stream.push(a); stream.push(b);
stream.push((~a)&255); stream.push((~b)&255);
if(i===0) stream.push(0);
for(j=0;j<w;j++) {
for(k=0;k<3;k++) {
a = img[k][i][j];
if(a>255) a = 255;
else if(a<0) a=0;
else a = Math.round(a);
s1 = (s1 + a )%65521;
s2 = (s2 + s1)%65521;
stream.push(a);
}
}
stream.push(0);
}
adler32 = (s2<<16)+s1;
stream.push((adler32>>24)&255);
stream.push((adler32>>16)&255);
stream.push((adler32>>8)&255);
stream.push((adler32)&255);
length = stream.length - 41;
stream[33] = (length>>24)&255;
stream[34] = (length>>16)&255;
stream[35] = (length>>8)&255;
stream[36] = (length)&255;
crc32 = crc32Array(stream,37);
stream.push((crc32>>24)&255);
stream.push((crc32>>16)&255);
stream.push((crc32>>8)&255);
stream.push((crc32)&255);
stream.push(0);
stream.push(0);
stream.push(0);
stream.push(0);
// a = stream.length;
stream.push(73); // I
stream.push(69); // E
stream.push(78); // N
stream.push(68); // D
stream.push(174); // CRC1
stream.push(66); // CRC2
stream.push(96); // CRC3
stream.push(130); // CRC4
return 'data:image/png;base64,'+base64(stream);
};
// 2. Linear algebra with Arrays.
numeric._dim = function _dim(x) {
var ret = [];
while(typeof x === "object") { ret.push(x.length); x = x[0]; }
return ret;
};
numeric.dim = function dim(x) {
var y,z;
if(typeof x === "object") {
y = x[0];
if(typeof y === "object") {
z = y[0];
if(typeof z === "object") {
return numeric._dim(x);
}
return [x.length,y.length];
}
return [x.length];
}
return [];
};
numeric.mapreduce = function mapreduce(body,init) {
return Function('x','accum','_s','_k',
'if(typeof accum === "undefined") accum = '+init+';\n'+
'if(typeof x === "number") { var xi = x; '+body+'; return accum; }\n'+
'if(typeof _s === "undefined") _s = numeric.dim(x);\n'+
'if(typeof _k === "undefined") _k = 0;\n'+
'var _n = _s[_k];\n'+
'var i,xi;\n'+
'if(_k < _s.length-1) {\n'+
' for(i=_n-1;i>=0;i--) {\n'+
' accum = arguments.callee(x[i],accum,_s,_k+1);\n'+
' }'+
' return accum;\n'+
'}\n'+
'for(i=_n-1;i>=1;i-=2) { \n'+
' xi = x[i];\n'+
' '+body+';\n'+
' xi = x[i-1];\n'+
' '+body+';\n'+
'}\n'+
'if(i === 0) {\n'+
' xi = x[i];\n'+
' '+body+'\n'+
'}\n'+
'return accum;'
);
};
numeric.mapreduce2 = function mapreduce2(body,setup) {
return Function('x',
'var n = x.length;\n'+
'var i,xi;\n'+setup+';\n'+
'for(i=n-1;i!==-1;--i) { \n'+
' xi = x[i];\n'+
' '+body+';\n'+
'}\n'+
'return accum;'
);
};
numeric.same = function same(x,y) {
var i,n;
if(!(x instanceof Array) || !(y instanceof Array)) { return false; }
n = x.length;
if(n !== y.length) { return false; }
for(i=0;i<n;i++) {
if(x[i] === y[i]) { continue; }
if(typeof x[i] === "object") { if(!same(x[i],y[i])) return false; }
else { return false; }
}
return true;
};
numeric.rep = function rep(s,v,k) {
if(typeof k === "undefined") { k=0; }
var n = s[k], ret = Array(n), i;
if(k === s.length-1) {
for(i=n-2;i>=0;i-=2) { ret[i+1] = v; ret[i] = v; }
if(i===-1) { ret[0] = v; }
return ret;
}
for(i=n-1;i>=0;i--) { ret[i] = numeric.rep(s,v,k+1); }
return ret;
};
numeric.dotMMsmall = function dotMMsmall(x,y) {
var i,j,k,p,q,r,ret,foo,bar,woo,i0,k0,p0,r0;
p = x.length; q = y.length; r = y[0].length;
ret = Array(p);
for(i=p-1;i>=0;i--) {
foo = Array(r);
bar = x[i];
for(k=r-1;k>=0;k--) {
woo = bar[q-1]*y[q-1][k];
for(j=q-2;j>=1;j-=2) {
i0 = j-1;
woo += bar[j]*y[j][k] + bar[i0]*y[i0][k];
}
if(j===0) { woo += bar[0]*y[0][k]; }
foo[k] = woo;
}
ret[i] = foo;
}
return ret;
};
numeric._getCol = function _getCol(A,j,x) {
var n = A.length, i;
for(i=n-1;i>0;--i) {
x[i] = A[i][j];
--i;
x[i] = A[i][j];
}
if(i===0) x[0] = A[0][j];
};
numeric.dotMMbig = function dotMMbig(x,y){
var gc = numeric._getCol, p = y.length, v = Array(p);
var m = x.length, n = y[0].length, A = new Array(m), xj;
var VV = numeric.dotVV;
var i,j,k,z;
--p;
--m;
for(i=m;i!==-1;--i) A[i] = Array(n);
--n;
for(i=n;i!==-1;--i) {
gc(y,i,v);
for(j=m;j!==-1;--j) {
z=0;
xj = x[j];
A[j][i] = VV(xj,v);
}
}
return A;
};
numeric.dotMV = function dotMV(x,y) {
var p = x.length, q = y.length,i;
var ret = Array(p), dotVV = numeric.dotVV;
for(i=p-1;i>=0;i--) { ret[i] = dotVV(x[i],y); }
return ret;
};
numeric.dotVM = function dotVM(x,y) {
var i,j,k,p,q,r,ret,foo,bar,woo,i0,k0,p0,r0,s1,s2,s3,baz,accum;
p = x.length; q = y[0].length;
ret = Array(q);
for(k=q-1;k>=0;k--) {
woo = x[p-1]*y[p-1][k];
for(j=p-2;j>=1;j-=2) {
i0 = j-1;
woo += x[j]*y[j][k] + x[i0]*y[i0][k];
}
if(j===0) { woo += x[0]*y[0][k]; }
ret[k] = woo;
}
return ret;
};
numeric.dotVV = function dotVV(x,y) {
var i,n=x.length,i1,ret = x[n-1]*y[n-1];
for(i=n-2;i>=1;i-=2) {
i1 = i-1;
ret += x[i]*y[i] + x[i1]*y[i1];
}
if(i===0) { ret += x[0]*y[0]; }
return ret;
};
numeric.dot = function dot(x,y) {
var d = numeric.dim;
switch(d(x).length*1000+d(y).length) {
case 2002:
if(y.length < 10) return numeric.dotMMsmall(x,y);
else return numeric.dotMMbig(x,y);
case 2001: return numeric.dotMV(x,y);
case 1002: return numeric.dotVM(x,y);
case 1001: return numeric.dotVV(x,y);
case 1000: return numeric.mulVS(x,y);
case 1: return numeric.mulSV(x,y);
case 0: return x*y;
default: throw new Error('numeric.dot only works on vectors and matrices');
}
};
numeric.diag = function diag(d) {
var i,i1,j,n = d.length, A = Array(n), Ai;
for(i=n-1;i>=0;i--) {
Ai = Array(n);
i1 = i+2;
for(j=n-1;j>=i1;j-=2) {
Ai[j] = 0;
Ai[j-1] = 0;
}
if(j>i) { Ai[j] = 0; }
Ai[i] = d[i];
for(j=i-1;j>=1;j-=2) {
Ai[j] = 0;
Ai[j-1] = 0;
}
if(j===0) { Ai[0] = 0; }
A[i] = Ai;
}
return A;
};
numeric.getDiag = function(A) {
var n = Math.min(A.length,A[0].length),i,ret = Array(n);
for(i=n-1;i>=1;--i) {
ret[i] = A[i][i];
--i;
ret[i] = A[i][i];
}
if(i===0) {
ret[0] = A[0][0];
}
return ret;
};
numeric.identity = function identity(n) { return numeric.diag(numeric.rep([n],1)); };
numeric.pointwise = function pointwise(params,body,setup) {
if(typeof setup === "undefined") { setup = ""; }
var fun = [];
var k;
var avec = /\[i\]$/,p,thevec = '';
var haveret = false;
for(k=0;k<params.length;k++) {
if(avec.test(params[k])) {
p = params[k].substring(0,params[k].length-3);
thevec = p;
} else { p = params[k]; }
if(p==='ret') haveret = true;
fun.push(p);
}
fun[params.length] = '_s';
fun[params.length+1] = '_k';
fun[params.length+2] = (
'if(typeof _s === "undefined") _s = numeric.dim('+thevec+');\n'+
'if(typeof _k === "undefined") _k = 0;\n'+
'var _n = _s[_k];\n'+
'var i'+(haveret?'':', ret = Array(_n)')+';\n'+
'if(_k < _s.length-1) {\n'+
' for(i=_n-1;i>=0;i--) ret[i] = arguments.callee('+params.join(',')+',_s,_k+1);\n'+
' return ret;\n'+
'}\n'+
setup+'\n'+
'for(i=_n-1;i!==-1;--i) {\n'+
' '+body+'\n'+
'}\n'+
'return ret;'
);
return Function.apply(null,fun);
};
numeric.pointwise2 = function pointwise2(params,body,setup) {
if(typeof setup === "undefined") { setup = ""; }
var fun = [];
var k;
var avec = /\[i\]$/,p,thevec = '';
var haveret = false;
for(k=0;k<params.length;k++) {
if(avec.test(params[k])) {
p = params[k].substring(0,params[k].length-3);
thevec = p;
} else { p = params[k]; }
if(p==='ret') haveret = true;
fun.push(p);
}
fun[params.length] = (
'var _n = '+thevec+'.length;\n'+
'var i'+(haveret?'':', ret = Array(_n)')+';\n'+
setup+'\n'+
'for(i=_n-1;i!==-1;--i) {\n'+
body+'\n'+
'}\n'+
'return ret;'
);
return Function.apply(null,fun);
};
numeric._biforeach = (function _biforeach(x,y,s,k,f) {
if(k === s.length-1) { f(x,y); return; }
var i,n=s[k];
for(i=n-1;i>=0;i--) { _biforeach(typeof x==="object"?x[i]:x,typeof y==="object"?y[i]:y,s,k+1,f); }
});
numeric._biforeach2 = (function _biforeach2(x,y,s,k,f) {
if(k === s.length-1) { return f(x,y); }
var i,n=s[k],ret = Array(n);
for(i=n-1;i>=0;--i) { ret[i] = _biforeach2(typeof x==="object"?x[i]:x,typeof y==="object"?y[i]:y,s,k+1,f); }
return ret;
});
numeric._foreach = (function _foreach(x,s,k,f) {
if(k === s.length-1) { f(x); return; }
var i,n=s[k];
for(i=n-1;i>=0;i--) { _foreach(x[i],s,k+1,f); }
});
numeric._foreach2 = (function _foreach2(x,s,k,f) {
if(k === s.length-1) { return f(x); }
var i,n=s[k], ret = Array(n);
for(i=n-1;i>=0;i--) { ret[i] = _foreach2(x[i],s,k+1,f); }
return ret;
});
/*numeric.anyV = numeric.mapreduce('if(xi) return true;','false');
numeric.allV = numeric.mapreduce('if(!xi) return false;','true');
numeric.any = function(x) { if(typeof x.length === "undefined") return x; return numeric.anyV(x); }
numeric.all = function(x) { if(typeof x.length === "undefined") return x; return numeric.allV(x); }*/
numeric.ops2 = {
add: '+',
sub: '-',
mul: '*',
div: '/',
mod: '%',
and: '&&',
or: '||',
eq: '===',
neq: '!==',
lt: '<',
gt: '>',
leq: '<=',
geq: '>=',
band: '&',
bor: '|',
bxor: '^',
lshift: '<<',
rshift: '>>',
rrshift: '>>>'
};
numeric.opseq = {
addeq: '+=',
subeq: '-=',
muleq: '*=',
diveq: '/=',
modeq: '%=',
lshifteq: '<<=',
rshifteq: '>>=',
rrshifteq: '>>>=',
bandeq: '&=',
boreq: '|=',
bxoreq: '^='
};
numeric.mathfuns = ['abs','acos','asin','atan','ceil','cos',
'exp','floor','log','round','sin','sqrt','tan',
'isNaN','isFinite'];
numeric.mathfuns2 = ['atan2','pow','max','min'];
numeric.ops1 = {
neg: '-',
not: '!',
bnot: '~',
clone: ''
};
numeric.mapreducers = {
any: ['if(xi) return true;','var accum = false;'],
all: ['if(!xi) return false;','var accum = true;'],
sum: ['accum += xi;','var accum = 0;'],
prod: ['accum *= xi;','var accum = 1;'],
norm2Squared: ['accum += xi*xi;','var accum = 0;'],
norminf: ['accum = max(accum,abs(xi));','var accum = 0, max = Math.max, abs = Math.abs;'],
norm1: ['accum += abs(xi)','var accum = 0, abs = Math.abs;'],
sup: ['accum = max(accum,xi);','var accum = -Infinity, max = Math.max;'],
inf: ['accum = min(accum,xi);','var accum = Infinity, min = Math.min;']
};
(function () {
var i,o;
for(i=0;i<numeric.mathfuns2.length;++i) {
o = numeric.mathfuns2[i];
numeric.ops2[o] = o;
}
for(i in numeric.ops2) {
if(numeric.ops2.hasOwnProperty(i)) {
o = numeric.ops2[i];
var code, codeeq, setup = '';
if(numeric.myIndexOf.call(numeric.mathfuns2,i)!==-1) {
setup = 'var '+o+' = Math.'+o+';\n';
code = function(r,x,y) { return r+' = '+o+'('+x+','+y+')'; };
codeeq = function(x,y) { return x+' = '+o+'('+x+','+y+')'; };
} else {
code = function(r,x,y) { return r+' = '+x+' '+o+' '+y; };
if(numeric.opseq.hasOwnProperty(i+'eq')) {
codeeq = function(x,y) { return x+' '+o+'= '+y; };
} else {
codeeq = function(x,y) { return x+' = '+x+' '+o+' '+y; };
}
}
numeric[i+'VV'] = numeric.pointwise2(['x[i]','y[i]'],code('ret[i]','x[i]','y[i]'),setup);
numeric[i+'SV'] = numeric.pointwise2(['x','y[i]'],code('ret[i]','x','y[i]'),setup);
numeric[i+'VS'] = numeric.pointwise2(['x[i]','y'],code('ret[i]','x[i]','y'),setup);
numeric[i] = Function(
'var n = arguments.length, i, x = arguments[0], y;\n'+
'var VV = numeric.'+i+'VV, VS = numeric.'+i+'VS, SV = numeric.'+i+'SV;\n'+
'var dim = numeric.dim;\n'+
'for(i=1;i!==n;++i) { \n'+
' y = arguments[i];\n'+
' if(typeof x === "object") {\n'+
' if(typeof y === "object") x = numeric._biforeach2(x,y,dim(x),0,VV);\n'+
' else x = numeric._biforeach2(x,y,dim(x),0,VS);\n'+
' } else if(typeof y === "object") x = numeric._biforeach2(x,y,dim(y),0,SV);\n'+
' else '+codeeq('x','y')+'\n'+
'}\nreturn x;\n');
numeric[o] = numeric[i];
numeric[i+'eqV'] = numeric.pointwise2(['ret[i]','x[i]'], codeeq('ret[i]','x[i]'),setup);
numeric[i+'eqS'] = numeric.pointwise2(['ret[i]','x'], codeeq('ret[i]','x'),setup);
numeric[i+'eq'] = Function(
'var n = arguments.length, i, x = arguments[0], y;\n'+
'var V = numeric.'+i+'eqV, S = numeric.'+i+'eqS\n'+
'var s = numeric.dim(x);\n'+
'for(i=1;i!==n;++i) { \n'+
' y = arguments[i];\n'+
' if(typeof y === "object") numeric._biforeach(x,y,s,0,V);\n'+
' else numeric._biforeach(x,y,s,0,S);\n'+
'}\nreturn x;\n');
}
}
for(i=0;i<numeric.mathfuns2.length;++i) {
o = numeric.mathfuns2[i];
delete numeric.ops2[o];
}
for(i=0;i<numeric.mathfuns.length;++i) {
o = numeric.mathfuns[i];
numeric.ops1[o] = o;
}
for(i in numeric.ops1) {
if(numeric.ops1.hasOwnProperty(i)) {
setup = '';
o = numeric.ops1[i];
if(numeric.myIndexOf.call(numeric.mathfuns,i)!==-1) {
if(Math.hasOwnProperty(o)) setup = 'var '+o+' = Math.'+o+';\n';
}
numeric[i+'eqV'] = numeric.pointwise2(['ret[i]'],'ret[i] = '+o+'(ret[i]);',setup);
numeric[i+'eq'] = Function('x',
'if(typeof x !== "object") return '+o+'x\n'+
'var i;\n'+
'var V = numeric.'+i+'eqV;\n'+
'var s = numeric.dim(x);\n'+
'numeric._foreach(x,s,0,V);\n'+
'return x;\n');
numeric[i+'V'] = numeric.pointwise2(['x[i]'],'ret[i] = '+o+'(x[i]);',setup);
numeric[i] = Function('x',
'if(typeof x !== "object") return '+o+'(x)\n'+
'var i;\n'+
'var V = numeric.'+i+'V;\n'+
'var s = numeric.dim(x);\n'+
'return numeric._foreach2(x,s,0,V);\n');
}
}
for(i=0;i<numeric.mathfuns.length;++i) {
o = numeric.mathfuns[i];
delete numeric.ops1[o];
}
for(i in numeric.mapreducers) {
if(numeric.mapreducers.hasOwnProperty(i)) {
o = numeric.mapreducers[i];
numeric[i+'V'] = numeric.mapreduce2(o[0],o[1]);
numeric[i] = Function('x','s','k',
o[1]+
'if(typeof x !== "object") {'+
' xi = x;\n'+
o[0]+';\n'+
' return accum;\n'+
'}'+
'if(typeof s === "undefined") s = numeric.dim(x);\n'+
'if(typeof k === "undefined") k = 0;\n'+
'if(k === s.length-1) return numeric.'+i+'V(x);\n'+
'var xi;\n'+
'var n = x.length, i;\n'+
'for(i=n-1;i!==-1;--i) {\n'+
' xi = arguments.callee(x[i]);\n'+
o[0]+';\n'+
'}\n'+
'return accum;\n');
}
}
}());
numeric.truncVV = numeric.pointwise(['x[i]','y[i]'],'ret[i] = round(x[i]/y[i])*y[i];','var round = Math.round;');
numeric.truncVS = numeric.pointwise(['x[i]','y'],'ret[i] = round(x[i]/y)*y;','var round = Math.round;');
numeric.truncSV = numeric.pointwise(['x','y[i]'],'ret[i] = round(x/y[i])*y[i];','var round = Math.round;');
numeric.trunc = function trunc(x,y) {
if(typeof x === "object") {
if(typeof y === "object") return numeric.truncVV(x,y);
return numeric.truncVS(x,y);
}
if (typeof y === "object") return numeric.truncSV(x,y);
return Math.round(x/y)*y;
};
numeric.inv = function inv(x) {
var s = numeric.dim(x), abs = Math.abs, m = s[0], n = s[1];
var A = numeric.clone(x), Ai, Aj;
var I = numeric.identity(m), Ii, Ij;
var i,j,k,x;
for(j=0;j<n;++j) {
var i0 = -1;
var v0 = -1;
for(i=j;i!==m;++i) { k = abs(A[i][j]); if(k>v0) { i0 = i; v0 = k; } }
Aj = A[i0]; A[i0] = A[j]; A[j] = Aj;
Ij = I[i0]; I[i0] = I[j]; I[j] = Ij;
x = Aj[j];
for(k=j;k!==n;++k) Aj[k] /= x;
for(k=n-1;k!==-1;--k) Ij[k] /= x;
for(i=m-1;i!==-1;--i) {
if(i!==j) {
Ai = A[i];
Ii = I[i];
x = Ai[j];
for(k=j+1;k!==n;++k) Ai[k] -= Aj[k]*x;
for(k=n-1;k>0;--k) { Ii[k] -= Ij[k]*x; --k; Ii[k] -= Ij[k]*x; }
if(k===0) Ii[0] -= Ij[0]*x;
}
}
}
return I;
};
numeric.det = function det(x) {
var s = numeric.dim(x);
if(s.length !== 2 || s[0] !== s[1]) { throw new Error('numeric: det() only works on square matrices'); }
var n = s[0], ret = 1,i,j,k,A = numeric.clone(x),Aj,Ai,alpha,temp,k1,k2,k3;
for(j=0;j<n-1;j++) {
k=j;
for(i=j+1;i<n;i++) { if(Math.abs(A[i][j]) > Math.abs(A[k][j])) { k = i; } }
if(k !== j) {
temp = A[k]; A[k] = A[j]; A[j] = temp;
ret *= -1;
}
Aj = A[j];
for(i=j+1;i<n;i++) {
Ai = A[i];
alpha = Ai[j]/Aj[j];
for(k=j+1;k<n-1;k+=2) {
k1 = k+1;
Ai[k] -= Aj[k]*alpha;
Ai[k1] -= Aj[k1]*alpha;
}
if(k!==n) { Ai[k] -= Aj[k]*alpha; }
}
if(Aj[j] === 0) { return 0; }
ret *= Aj[j];
}
return ret*A[j][j];
};
numeric.transpose = function transpose(x) {
var i,j,m = x.length,n = x[0].length, ret=Array(n),A0,A1,Bj;
for(j=0;j<n;j++) ret[j] = Array(m);
for(i=m-1;i>=1;i-=2) {
A1 = x[i];
A0 = x[i-1];
for(j=n-1;j>=1;--j) {
Bj = ret[j]; Bj[i] = A1[j]; Bj[i-1] = A0[j];
--j;
Bj = ret[j]; Bj[i] = A1[j]; Bj[i-1] = A0[j];
}
if(j===0) {
Bj = ret[0]; Bj[i] = A1[0]; Bj[i-1] = A0[0];
}
}
if(i===0) {
A0 = x[0];
for(j=n-1;j>=1;--j) {
ret[j][0] = A0[j];
--j;
ret[j][0] = A0[j];
}
if(j===0) { ret[0][0] = A0[0]; }
}
return ret;
};
numeric.negtranspose = function negtranspose(x) {
var i,j,m = x.length,n = x[0].length, ret=Array(n),A0,A1,Bj;
for(j=0;j<n;j++) ret[j] = Array(m);
for(i=m-1;i>=1;i-=2) {
A1 = x[i];
A0 = x[i-1];
for(j=n-1;j>=1;--j) {
Bj = ret[j]; Bj[i] = -A1[j]; Bj[i-1] = -A0[j];
--j;
Bj = ret[j]; Bj[i] = -A1[j]; Bj[i-1] = -A0[j];
}
if(j===0) {
Bj = ret[0]; Bj[i] = -A1[0]; Bj[i-1] = -A0[0];
}
}
if(i===0) {
A0 = x[0];
for(j=n-1;j>=1;--j) {
ret[j][0] = -A0[j];
--j;
ret[j][0] = -A0[j];
}
if(j===0) { ret[0][0] = -A0[0]; }
}
return ret;
};
numeric._random = function _random(s,k) {
var i,n=s[k],ret=Array(n), rnd;
if(k === s.length-1) {
rnd = Math.random;
for(i=n-1;i>=1;i-=2) {
ret[i] = rnd();
ret[i-1] = rnd();
}
if(i===0) { ret[0] = rnd(); }
return ret;
}
for(i=n-1;i>=0;i--) ret[i] = _random(s,k+1);
return ret;
};
numeric.random = function random(s) { return numeric._random(s,0); };
numeric.norm2 = function norm2(x) { return Math.sqrt(numeric.norm2Squared(x)); };
numeric.linspace = function linspace(a,b,n) {
if(typeof n === "undefined") n = Math.max(Math.round(b-a)+1,1);
if(n<2) { return n===1?[a]:[]; }
var i,ret = Array(n);
n--;
for(i=n;i>=0;i--) { ret[i] = (i*b+(n-i)*a)/n; }
return ret;
};
numeric.getBlock = function getBlock(x,from,to) {
var s = numeric.dim(x);
function foo(x,k) {
var i,a = from[k], n = to[k]-a, ret = Array(n);
if(k === s.length-1) {
for(i=n;i>=0;i--) { ret[i] = x[i+a]; }
return ret;
}
for(i=n;i>=0;i--) { ret[i] = foo(x[i+a],k+1); }
return ret;
}
return foo(x,0);
};
numeric.setBlock = function setBlock(x,from,to,B) {
var s = numeric.dim(x);
function foo(x,y,k) {
var i,a = from[k], n = to[k]-a;
if(k === s.length-1) { for(i=n;i>=0;i--) { x[i+a] = y[i]; } }
for(i=n;i>=0;i--) { foo(x[i+a],y[i],k+1); }
}
foo(x,B,0);
return x;
};
numeric.getRange = function getRange(A,I,J) {
var m = I.length, n = J.length;
var i,j;
var B = Array(m), Bi, AI;
for(i=m-1;i!==-1;--i) {
B[i] = Array(n);
Bi = B[i];
AI = A[I[i]];
for(j=n-1;j!==-1;--j) Bi[j] = AI[J[j]];
}
return B;
};
numeric.blockMatrix = function blockMatrix(X) {
var s = numeric.dim(X);
if(s.length<4) return numeric.blockMatrix([X]);
var m=s[0],n=s[1],M,N,i,j,Xij;
M = 0; N = 0;
for(i=0;i<m;++i) M+=X[i][0].length;
for(j=0;j<n;++j) N+=X[0][j][0].length;
var Z = Array(M);
for(i=0;i<M;++i) Z[i] = Array(N);
var I=0,J,ZI,k,l,Xijk;
for(i=0;i<m;++i) {
J=N;
for(j=n-1;j!==-1;--j) {
Xij = X[i][j];
J -= Xij[0].length;
for(k=Xij.length-1;k!==-1;--k) {
Xijk = Xij[k];
ZI = Z[I+k];
for(l = Xijk.length-1;l!==-1;--l) ZI[J+l] = Xijk[l];
}
}
I += X[i][0].length;
}
return Z;
};
numeric.tensor = function tensor(x,y) {
if(typeof x === "number" || typeof y === "number") return numeric.mul(x,y);
var s1 = numeric.dim(x), s2 = numeric.dim(y);
if(s1.length !== 1 || s2.length !== 1) {
throw new Error('numeric: tensor product is only defined for vectors');
}
var m = s1[0], n = s2[0], A = Array(m), Ai, i,j,xi;
for(i=m-1;i>=0;i--) {
Ai = Array(n);
xi = x[i];
for(j=n-1;j>=3;--j) {
Ai[j] = xi * y[j];
--j;
Ai[j] = xi * y[j];
--j;
Ai[j] = xi * y[j];
--j;
Ai[j] = xi * y[j];
}
while(j>=0) { Ai[j] = xi * y[j]; --j; }
A[i] = Ai;
}
return A;
};
// 3. The Tensor type T
numeric.T = function T(x,y) { this.x = x; this.y = y; };
numeric.t = function t(x,y) { return new numeric.T(x,y); };
numeric.Tbinop = function Tbinop(rr,rc,cr,cc,setup) {
var io = numeric.indexOf;
if(typeof setup !== "string") {
var k;
setup = '';
for(k in numeric) {
if(numeric.hasOwnProperty(k) && (rr.indexOf(k)>=0 || rc.indexOf(k)>=0 || cr.indexOf(k)>=0 || cc.indexOf(k)>=0) && k.length>1) {
setup += 'var '+k+' = numeric.'+k+';\n';
}
}
}
return Function(['y'],
'var x = this;\n'+
'if(!(y instanceof numeric.T)) { y = new numeric.T(y); }\n'+
setup+'\n'+
'if(x.y) {'+
' if(y.y) {'+
' return new numeric.T('+cc+');\n'+
' }\n'+
' return new numeric.T('+cr+');\n'+
'}\n'+
'if(y.y) {\n'+
' return new numeric.T('+rc+');\n'+
'}\n'+
'return new numeric.T('+rr+');\n'
);
};
numeric.T.prototype.add = numeric.Tbinop(
'add(x.x,y.x)',
'add(x.x,y.x),y.y',
'add(x.x,y.x),x.y',
'add(x.x,y.x),add(x.y,y.y)');
numeric.T.prototype.sub = numeric.Tbinop(
'sub(x.x,y.x)',
'sub(x.x,y.x),neg(y.y)',
'sub(x.x,y.x),x.y',
'sub(x.x,y.x),sub(x.y,y.y)');
numeric.T.prototype.mul = numeric.Tbinop(
'mul(x.x,y.x)',
'mul(x.x,y.x),mul(x.x,y.y)',
'mul(x.x,y.x),mul(x.y,y.x)',
'sub(mul(x.x,y.x),mul(x.y,y.y)),add(mul(x.x,y.y),mul(x.y,y.x))');
numeric.T.prototype.reciprocal = function reciprocal() {
var mul = numeric.mul, div = numeric.div;
if(this.y) {
var d = numeric.add(mul(this.x,this.x),mul(this.y,this.y));
return new numeric.T(div(this.x,d),div(numeric.neg(this.y),d));
}
return new T(div(1,this.x));
};
numeric.T.prototype.div = function div(y) {
if(!(y instanceof numeric.T)) y = new numeric.T(y);
if(y.y) { return this.mul(y.reciprocal()); }
var div = numeric.div;
if(this.y) { return new numeric.T(div(this.x,y.x),div(this.y,y.x)); }
return new numeric.T(div(this.x,y.x));
};
numeric.T.prototype.dot = numeric.Tbinop(
'dot(x.x,y.x)',
'dot(x.x,y.x),dot(x.x,y.y)',
'dot(x.x,y.x),dot(x.y,y.x)',
'sub(dot(x.x,y.x),dot(x.y,y.y)),add(dot(x.x,y.y),dot(x.y,y.x))'
);
numeric.T.prototype.transpose = function transpose() {
var t = numeric.transpose, x = this.x, y = this.y;
if(y) { return new numeric.T(t(x),t(y)); }
return new numeric.T(t(x));
};
numeric.T.prototype.transjugate = function transjugate() {
var t = numeric.transpose, x = this.x, y = this.y;
if(y) { return new numeric.T(t(x),numeric.negtranspose(y)); }
return new numeric.T(t(x));
};
numeric.Tunop = function Tunop(r,c,s) {
if(typeof s !== "string") { s = ''; }
return Function(
'var x = this;\n'+
s+'\n'+
'if(x.y) {'+
' '+c+';\n'+
'}\n'+
r+';\n'
);
};
numeric.T.prototype.exp = numeric.Tunop(
'return new numeric.T(ex)',
'return new numeric.T(mul(cos(x.y),ex),mul(sin(x.y),ex))',
'var ex = numeric.exp(x.x), cos = numeric.cos, sin = numeric.sin, mul = numeric.mul;');
numeric.T.prototype.conj = numeric.Tunop(
'return new numeric.T(x.x);',
'return new numeric.T(x.x,numeric.neg(x.y));');
numeric.T.prototype.neg = numeric.Tunop(
'return new numeric.T(neg(x.x));',
'return new numeric.T(neg(x.x),neg(x.y));',
'var neg = numeric.neg;');
numeric.T.prototype.sin = numeric.Tunop(
'return new numeric.T(numeric.sin(x.x))',
'return x.exp().sub(x.neg().exp()).div(new numeric.T(0,2));');
numeric.T.prototype.cos = numeric.Tunop(
'return new numeric.T(numeric.cos(x.x))',
'return x.exp().add(x.neg().exp()).div(2);');
numeric.T.prototype.abs = numeric.Tunop(
'return new numeric.T(numeric.abs(x.x));',
'return new numeric.T(numeric.sqrt(numeric.add(mul(x.x,x.x),mul(x.y,x.y))));',
'var mul = numeric.mul;');
numeric.T.prototype.log = numeric.Tunop(
'return new numeric.T(numeric.log(x.x));',
'var theta = new numeric.T(numeric.atan2(x.y,x.x)), r = x.abs();\n'+
'return new numeric.T(numeric.log(r.x),theta.x);');
numeric.T.prototype.norm2 = numeric.Tunop(
'return numeric.norm2(x.x);',
'var f = numeric.norm2Squared;\n'+
'return Math.sqrt(f(x.x)+f(x.y));');
numeric.T.prototype.inv = function inv() {
var A = this;
if(typeof A.y === "undefined") { return new numeric.T(numeric.inv(A.x)); }
var n = A.x.length, i, j, k;
var Rx = numeric.identity(n),Ry = numeric.rep([n,n],0);
var Ax = numeric.clone(A.x), Ay = numeric.clone(A.y);
var Aix, Aiy, Ajx, Ajy, Rix, Riy, Rjx, Rjy;
var i,j,k,d,d1,ax,ay,bx,by,temp;
for(i=0;i<n;i++) {
ax = Ax[i][i]; ay = Ay[i][i];
d = ax*ax+ay*ay;
k = i;
for(j=i+1;j<n;j++) {
ax = Ax[j][i]; ay = Ay[j][i];
d1 = ax*ax+ay*ay;
if(d1 > d) { k=j; d = d1; }
}
if(k!==i) {
temp = Ax[i]; Ax[i] = Ax[k]; Ax[k] = temp;
temp = Ay[i]; Ay[i] = Ay[k]; Ay[k] = temp;
temp = Rx[i]; Rx[i] = Rx[k]; Rx[k] = temp;
temp = Ry[i]; Ry[i] = Ry[k]; Ry[k] = temp;
}
Aix = Ax[i]; Aiy = Ay[i];
Rix = Rx[i]; Riy = Ry[i];
ax = Aix[i]; ay = Aiy[i];
for(j=i+1;j<n;j++) {
bx = Aix[j]; by = Aiy[j];
Aix[j] = (bx*ax+by*ay)/d;
Aiy[j] = (by*ax-bx*ay)/d;
}
for(j=0;j<n;j++) {
bx = Rix[j]; by = Riy[j];
Rix[j] = (bx*ax+by*ay)/d;
Riy[j] = (by*ax-bx*ay)/d;
}
for(j=i+1;j<n;j++) {
Ajx = Ax[j]; Ajy = Ay[j];
Rjx = Rx[j]; Rjy = Ry[j];
ax = Ajx[i]; ay = Ajy[i];
for(k=i+1;k<n;k++) {
bx = Aix[k]; by = Aiy[k];
Ajx[k] -= bx*ax-by*ay;
Ajy[k] -= by*ax+bx*ay;
}
for(k=0;k<n;k++) {
bx = Rix[k]; by = Riy[k];
Rjx[k] -= bx*ax-by*ay;
Rjy[k] -= by*ax+bx*ay;
}
}
}
for(i=n-1;i>0;i--) {
Rix = Rx[i]; Riy = Ry[i];
for(j=i-1;j>=0;j--) {
Rjx = Rx[j]; Rjy = Ry[j];
ax = Ax[j][i]; ay = Ay[j][i];
for(k=n-1;k>=0;k--) {
bx = Rix[k]; by = Riy[k];
Rjx[k] -= ax*bx - ay*by;
Rjy[k] -= ax*by + ay*bx;
}
}
}
return new numeric.T(Rx,Ry);
};
numeric.T.prototype.get = function get(i) {
var x = this.x, y = this.y, k = 0, ik, n = i.length;
if(y) {
while(k<n) {
ik = i[k];
x = x[ik];
y = y[ik];
k++;
}
return new numeric.T(x,y);
}
while(k<n) {
ik = i[k];
x = x[ik];
k++;
}
return new numeric.T(x);
};
numeric.T.prototype.set = function set(i,v) {
var x = this.x, y = this.y, k = 0, ik, n = i.length, vx = v.x, vy = v.y;
if(n===0) {
if(vy) { this.y = vy; }
else if(y) { this.y = undefined; }
this.x = x;
return this;
}
if(vy) {
if(y) { /* ok */ }
else {
y = numeric.rep(numeric.dim(x),0);
this.y = y;
}
while(k<n-1) {
ik = i[k];
x = x[ik];
y = y[ik];
k++;
}
ik = i[k];
x[ik] = vx;
y[ik] = vy;
return this;
}
if(y) {
while(k<n-1) {
ik = i[k];
x = x[ik];
y = y[ik];
k++;
}
ik = i[k];
x[ik] = vx;
if(vx instanceof Array) y[ik] = numeric.rep(numeric.dim(vx),0);
else y[ik] = 0;
return this;
}
while(k<n-1) {
ik = i[k];
x = x[ik];
k++;
}
ik = i[k];
x[ik] = vx;
return this;
};
numeric.T.prototype.getRows = function getRows(i0,i1) {
var n = i1-i0+1, j;
var rx = Array(n), ry, x = this.x, y = this.y;
for(j=i0;j<=i1;j++) { rx[j-i0] = x[j]; }
if(y) {
ry = Array(n);
for(j=i0;j<=i1;j++) { ry[j-i0] = y[j]; }
return new numeric.T(rx,ry);
}
return new numeric.T(rx);
};
numeric.T.prototype.setRows = function setRows(i0,i1,A) {
var j;
var rx = this.x, ry = this.y, x = A.x, y = A.y;
for(j=i0;j<=i1;j++) { rx[j] = x[j-i0]; }
if(y) {
if(!ry) { ry = numeric.rep(numeric.dim(rx),0); this.y = ry; }
for(j=i0;j<=i1;j++) { ry[j] = y[j-i0]; }
} else if(ry) {
for(j=i0;j<=i1;j++) { ry[j] = numeric.rep([x[j-i0].length],0); }
}
return this;
};
numeric.T.prototype.getRow = function getRow(k) {
var x = this.x, y = this.y;
if(y) { return new numeric.T(x[k],y[k]); }
return new numeric.T(x[k]);
};
numeric.T.prototype.setRow = function setRow(i,v) {
var rx = this.x, ry = this.y, x = v.x, y = v.y;
rx[i] = x;
if(y) {
if(!ry) { ry = numeric.rep(numeric.dim(rx),0); this.y = ry; }
ry[i] = y;
} else if(ry) {
ry = numeric.rep([x.length],0);
}
return this;
};
numeric.T.prototype.getBlock = function getBlock(from,to) {
var x = this.x, y = this.y, b = numeric.getBlock;
if(y) { return new numeric.T(b(x,from,to),b(y,from,to)); }
return new numeric.T(b(x,from,to));
};
numeric.T.prototype.setBlock = function setBlock(from,to,A) {
if(!(A instanceof numeric.T)) A = new numeric.T(A);
var x = this.x, y = this.y, b = numeric.setBlock, Ax = A.x, Ay = A.y;
if(Ay) {
if(!y) { this.y = numeric.rep(numeric.dim(this),0); y = this.y; }
b(x,from,to,Ax);
b(y,from,to,Ay);
return this;
}
b(x,from,to,Ax);
if(y) b(y,from,to,numeric.rep(numeric.dim(Ax),0));
};
numeric.T.rep = function rep(s,v) {
var T = numeric.T;
if(!(v instanceof T)) v = new T(v);
var x = v.x, y = v.y, r = numeric.rep;
if(y) return new T(r(s,x),r(s,y));
return new T(r(s,x));
};
numeric.T.diag = function diag(d) {
if(!(d instanceof numeric.T)) d = new numeric.T(d);
var x = d.x, y = d.y, diag = numeric.diag;
if(y) return new numeric.T(diag(x),diag(y));
return new numeric.T(diag(x));
};
numeric.T.eig = function eig() {
if(this.y) { throw new Error('eig: not implemented for complex matrices.'); }
return numeric.eig(this.x);
};
numeric.T.identity = function identity(n) { return new numeric.T(numeric.identity(n)); };
numeric.T.prototype.getDiag = function getDiag() {
var n = numeric;
var x = this.x, y = this.y;
if(y) { return new n.T(n.getDiag(x),n.getDiag(y)); }
return new n.T(n.getDiag(x));
};
// 4. Eigenvalues of real matrices
numeric.house = function house(x) {
var v = numeric.clone(x);
var s = x[0] >= 0 ? 1 : -1;
var alpha = s*numeric.norm2(x);
v[0] += alpha;
var foo = numeric.norm2(v);
if(foo === 0) { /* this should not happen */ throw new Error('eig: internal error'); }
return numeric.div(v,foo);
};
numeric.toUpperHessenberg = function toUpperHessenberg(me) {
var s = numeric.dim(me);
if(s.length !== 2 || s[0] !== s[1]) { throw new Error('numeric: toUpperHessenberg() only works on square matrices'); }
var m = s[0], i,j,k,x,v,A = numeric.clone(me),B,C,Ai,Ci,Q = numeric.identity(m),Qi;
for(j=0;j<m-2;j++) {
x = Array(m-j-1);
for(i=j+1;i<m;i++) { x[i-j-1] = A[i][j]; }
if(numeric.norm2(x)>0) {
v = numeric.house(x);
B = numeric.getBlock(A,[j+1,j],[m-1,m-1]);
C = numeric.tensor(v,numeric.dot(v,B));
for(i=j+1;i<m;i++) { Ai = A[i]; Ci = C[i-j-1]; for(k=j;k<m;k++) Ai[k] -= 2*Ci[k-j]; }
B = numeric.getBlock(A,[0,j+1],[m-1,m-1]);
C = numeric.tensor(numeric.dot(B,v),v);
for(i=0;i<m;i++) { Ai = A[i]; Ci = C[i]; for(k=j+1;k<m;k++) Ai[k] -= 2*Ci[k-j-1]; }
B = Array(m-j-1);
for(i=j+1;i<m;i++) B[i-j-1] = Q[i];
C = numeric.tensor(v,numeric.dot(v,B));
for(i=j+1;i<m;i++) { Qi = Q[i]; Ci = C[i-j-1]; for(k=0;k<m;k++) Qi[k] -= 2*Ci[k]; }
}
}
return {H:A, Q:Q};
};
numeric.epsilon = 2.220446049250313e-16;
numeric.QRFrancis = function(H,maxiter) {
if(typeof maxiter === "undefined") { maxiter = 10000; }
H = numeric.clone(H);
var H0 = numeric.clone(H);
var s = numeric.dim(H),m=s[0],x,v,a,b,c,d,det,tr, Hloc, Q = numeric.identity(m), Qi, Hi, B, C, Ci,i,j,k,iter;
if(m<3) { return {Q:Q, B:[ [0,m-1] ]}; }
var epsilon = numeric.epsilon;
for(iter=0;iter<maxiter;iter++) {
for(j=0;j<m-1;j++) {
if(Math.abs(H[j+1][j]) < epsilon*(Math.abs(H[j][j])+Math.abs(H[j+1][j+1]))) {
var QH1 = numeric.QRFrancis(numeric.getBlock(H,[0,0],[j,j]),maxiter);
var QH2 = numeric.QRFrancis(numeric.getBlock(H,[j+1,j+1],[m-1,m-1]),maxiter);
B = Array(j+1);
for(i=0;i<=j;i++) { B[i] = Q[i]; }
C = numeric.dot(QH1.Q,B);
for(i=0;i<=j;i++) { Q[i] = C[i]; }
B = Array(m-j-1);
for(i=j+1;i<m;i++) { B[i-j-1] = Q[i]; }
C = numeric.dot(QH2.Q,B);
for(i=j+1;i<m;i++) { Q[i] = C[i-j-1]; }
return {Q:Q,B:QH1.B.concat(numeric.add(QH2.B,j+1))};
}
}
a = H[m-2][m-2]; b = H[m-2][m-1];
c = H[m-1][m-2]; d = H[m-1][m-1];
tr = a+d;
det = (a*d-b*c);
Hloc = numeric.getBlock(H, [0,0], [2,2]);
if(tr*tr>=4*det) {
var s1,s2;
s1 = 0.5*(tr+Math.sqrt(tr*tr-4*det));
View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment