javascript: Getting object is not defined - javascript

when trying to reference an object created in a different function I get 'object is not defined' error. This sounds like a scope problem except this has worked in a different program before..
Error I get is 'uncaught reference error: man is not defined'..
Part of my code is listed below: Please see where the man object is created in the buildMap() function and where I try to reference it in the playGame() function..
var canvas = document.querySelector("canvas");
var drawingSurface = canvas.getContext("2d");
var man;
// Map code
var EMPTY = 0;
var TREE_BOTTOM = 1;
var TREE_TOP = 2;
var SKY = 3;
var CLOUD = 4;
var CLOUD_LEFT = 5;
var CLOUD_RIGHT = 6;
var PLATFORM = 7;
var EGG = 8;
var CAVE = 9;
var MEAT = 10;
var MAN = 11;
var DINO = 12;
var GUARD = 13;
var GROUND = 14;
// Map array
var map = [
[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],
[3,3,3,3,3,3,3,3,5,6,3,3,3,3,3,3,3,3,3,3,5,6,3,3],
[3,3,5,6,3,3,4,3,3,3,3,3,3,3,5,6,3,3,3,3,3,3,3,3],
[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,9,3,3,3],
[3,7,7,3,3,3,3,3,3,3,3,3,3,3,3,3,7,7,7,7,7,7,3,3],
[3,3,3,3,3,3,3,3,3,7,3,3,3,3,3,3,3,3,3,3,3,3,3,3],
[3,3,3,7,7,7,3,3,3,3,3,3,7,7,3,3,3,3,3,3,3,4,3,3],
[3,3,3,3,3,3,3,3,5,6,3,3,3,3,3,3,3,3,3,3,3,3,3,3],
[3,3,4,3,3,3,3,3,3,3,3,3,4,3,3,7,7,7,7,7,3,3,3,3],
[3,3,3,3,3,7,7,7,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],
[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3,3],
[3,3,3,3,3,3,3,3,3,3,3,7,7,7,7,3,3,3,3,3,3,3,3,3],
[3,3,2,3,3,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,2,3,3,3],
[14,14,1,14,14,14,14,14,14,14,1,14,14,14,14,14,1,14,14,14,1,14,14,14]
];
var gameObjects = [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,12,0,0,0,0,0,0,0,8,12,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,8,0,0,0,0],
[0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
];
// Cell size
var SIZE = 32;
// The number of rows and columns
var ROWS = map.length;
var COLS = map[0].length;
// Sprite object
var spriteObject =
{
sourceX: 0,
sourceY: 0,
sourceWidth: 32,
sourceHeight: 32,
width: 32,
height: 32,
x: 0,
y: 0,
vx: 0,
vy: 0,
visible: true,
//Getters
centerX: function()
{
return this.x + (this.width / 2);
},
centerY: function()
{
return this.y + (this.height / 2);
},
halfWidth: function()
{
return this.width / 2;
},
halfHeight: function()
{
return this.height / 2;
},
};
//arrays to store game objects
var sprites = [];
var eggs = [];
var dinos = [];
var platforms = [];
var assetsToLoad = [];
var assetsLoaded = 0;
//load the tilesheet
var image = new Image();
image.addEventListener("load", loadHandler, false);
image.src = "../images/spritesheet.png";
assetsToLoad.push(image);
//Game states
var LOADING = 0;
var BUILD_MAP = 1;
var PLAYING = 2;
var OVER = 3;
var gameState = LOADING;
// key codes
var LEFT = 37;
var RIGHT = 39;
var SPACE = 32;
// Directions
var moveLeft = false;
var moveRight = false;
window.addEventListener("keydown", function(event) {
switch(event.keyCode)
{
case LEFT:
moveLeft = true;
break;
case RIGHT:
moveRight = true;
break;
}}, false);
window.addEventListener("keyup", function(event) {
switch(event.keyCode)
{
case LEFT:
moveLeft = false;
break;
case RIGHT:
moveRight = false;
break;
}}, false);
update();
function update() {
requestAnimationFrame(update, canvas);
switch (gameState) {
case LOADING:
console.log("loading...");
break;
case BUILD_MAP:
buildMap(map);
buildMap(gameObjects);
gameState = PLAYING;
break;
case PLAYING:
playGame();
break;
case OVER:
endGame();
break;
}
render();
}
function loadHandler() {
assetsLoaded++;
if (assetsLoaded === assetsToLoad.length) {
image.removeEventListener("load", loadHandler, false);
gameState = BUILD_MAP;
}
}
function buildMap(map) {
for (var row=0; row < ROWS; row++) {
for (var col=0; col < COLS; col++) {
var currentTile = map[row] [col];
if (currentTile !== EMPTY) {
switch (currentTile) {
case GROUND:
var ground = Object.create(spriteObject);
ground.sourceX = 0;
ground.sourceY = 0;
ground.x = col * SIZE;
ground.y = row * SIZE;
sprites.push(ground);
break;
case TREE_BOTTOM:
var treeBottom = Object.create(spriteObject);
treeBottom.sourceX = 0;
treeBottom.sourceY = 32;
treeBottom.x = col * SIZE;
treeBottom.y = row * SIZE;
sprites.push(treeBottom);
break;
case TREE_TOP:
var treeTop = Object.create(spriteObject);
treeTop.sourceX = 0;
treeTop.sourceY = 64;
treeTop.x = col * SIZE;
treeTop.y = row * SIZE;
sprites.push(treeTop);
break;
case SKY:
var sky = Object.create(spriteObject);
sky.sourceX = 0;
sky.sourceY = 96;
sky.x = col * SIZE;
sky.y = row * SIZE;
sprites.push(sky);
break;
case CLOUD:
var cloud = Object.create(spriteObject);
cloud.sourceX = 0;
cloud.sourceY = 128;
cloud.x = col * SIZE;
cloud.y = row * SIZE;
sprites.push(cloud);
break;
case CLOUD_LEFT:
var cloudLeft = Object.create(spriteObject);
cloudLeft.sourceX = 0;
cloudLeft.sourceY = 160;
cloudLeft.x = col * SIZE;
cloudLeft.y = row * SIZE;
sprites.push(cloudLeft);
break;
case CLOUD_RIGHT:
var cloudRight = Object.create(spriteObject);
cloudRight.sourceX = 0;
cloudRight.sourceY = 192;
cloudRight.x = col * SIZE;
cloudRight.y = row * SIZE;
sprites.push(cloudRight);
break;
case PLATFORM:
var platform = Object.create(spriteObject);
platform.sourceX = 0;
platform.sourceY = 224;
platform.x = col * SIZE;
platform.y = row * SIZE;
sprites.push(platform);
platforms.push(platform);
break;
case CAVE:
var cave = Object.create(spriteObject);
cave.sourceX = 0;
cave.sourceY = 288;
cave.x = col * SIZE;
cave.y = row * SIZE;
sprites.push(cave);
break;
case EGG:
var egg = Object.create(spriteObject);
egg.sourceX = 0;
egg.sourceY = 256;
egg.x = col * SIZE;
egg.y = row * SIZE;
sprites.push(egg);
eggs.push(egg);
break;
case MEAT:
var meat = Object.create(spriteObject);
meat.sourceX = 0;
meat.sourceY = 320;
meat.x = col * SIZE;
meat.y = row * SIZE;
meat.visible = false;
sprites.push(meat);
break;
case DINO:
var dino = Object.create(spriteObject);
dino.sourceX = 0;
dino.sourceY = 416;
dino.x = col * SIZE;
dino.y = row * SIZE;
sprites.push(dino);
dinos.push(dino);
break;
case GUARD:
var guard = Object.create(spriteObject);
guard.sourceX = 0;
guard.sourceY = 480;
guard.x = col * SIZE;
guard.y = row * SIZE;
sprites.push(guard);
break;
case MAN:
var man = Object.create(spriteObject);
man.sourceX = 0;
man.sourceY = 352;
man.x = col * SIZE;
man.y = row * SIZE;
sprites.push(man);
break;
}
}
}
}
}
function playGame() {
if (moveLeft && !moveRight) {
man.vx = -3;
}
if (moveRight && !moveLeft) {
man.vx = 3;
}
if (!moveLeft && !moveRight) {
man.vx = 0;
}
man.x += man.vx;
}
function endGame() {
}
function render() {
drawingSurface.clearRect(0, 0, canvas.width, canvas.height);
if (sprites.length !== 0) {
for (i=0; i < sprites.length; i++) {
var sprite = sprites[i];
if (sprite.visible) {
drawingSurface.drawImage (
image,
sprite.sourceX, sprite.sourceY,
sprite.sourceWidth, sprite.sourceHeight,
Math.floor(sprite.x), Math.floor(sprite.y),
sprite.width, sprite.height
);
}
}
}
}

That's because man is in a local scope. Therefore, the playGame function can't "see" it.
To fix this, just declare the variable (put "var man;") outside of the buildMap function (right before it, preferrably).

what i think looking at your code is .... you have declared the variable "man" which is local to function "buildMap"
and you are trying to access it in another function ie. "playGame"..
may be this is the problem ...
you can solve it by making it global... at the topmost line of the script
hope it works.

Related

How to take the data?

I am learning to use neural networks, and have encountered a problem.
I can not figure out how to convert data for a neural network.
As I understand it, I need to normalize the data, after normalization and learning, the answer is always averaged.
https://jsfiddle.net/eoy7krzj/
<html>
<head>
<script src="https://cdn.rawgit.com/BrainJS/brain.js/5797b875/browser.js"></script>
</head>
<body>
<div>
<button onclick="train()">train</button><button onclick="Generate.next(); Generate.draw();">generate</button><button onclick="calculate()">calculate</button>
</div>
<canvas id="generate" style="border: 1px solid #000"></canvas>
</body>
<script type="text/javascript">
var trainData = [];
function randomInteger(min, max) {
var rand = min - 0.5 + Math.random() * (max - min + 1)
//rand = Math.round(rand);
return rand;
}
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
var Generate = new function(){
var canvas = document.getElementById('generate');
var ctx = canvas.getContext('2d');
var elem = {
input: [],
output: []
}
var size = {
width: 240,
height: 140
}
canvas.width = 500;
canvas.height = 250;
this.next = function(){
this.build();
trainData.push({
input: elem.input,
output: elem.output
});
}
this.clear = function(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
this.draw = function(){
this.clear();
this.item(elem.input, function(item){
ctx.strokeStyle = "green";
ctx.strokeRect(item[0], item[1], item[2], item[3]);
})
this.item(elem.output, function(item){
ctx.strokeStyle = "blue";
ctx.strokeRect(item[0], item[1], item[2], item[3]);
})
}
this.item = function(where, call){
for (var i = 0; i < where.length; i+=4) {
var input = [
where[i],
where[i+1],
where[i+2],
where[i+3],
];
this.denormalize(input);
call(input)
}
}
this.normalize = function(input){
input[0] = input[0] / 500;
input[1] = input[1] / 250;
input[2] = input[2] / 500;
input[3] = input[3] / 250;
}
this.denormalize = function(input){
input[0] = input[0] * 500;
input[1] = input[1] * 250;
input[2] = input[2] * 500;
input[3] = input[3] * 250;
}
this.empty = function(add){
var data = [];
for (var i = 0; i < add; i++) {
data = data.concat([0,0,0,0]);
}
return data;
}
this.build = function(){
var output = [];
var input = [];
size.width = randomInteger(100,500);
size.height = randomInteger(50,250);
var lines = 1;//Math.round(size.height / 100);
var line_size = 0;
var line_offset = 0;
for(var i = 0; i < lines; i++){
line_size = randomInteger(30,Math.round(size.height / lines));
var columns = Math.round(randomInteger(1,3));
var columns_width = 0;
var columns_offset = 0;
for(var c = 0; c < columns; c++){
columns_width = randomInteger(30,Math.round(size.width / columns));
var item = [
columns_offset + 10,
line_offset + 10,
columns_width - 20,
line_size - 20
];
this.normalize(item);
input = input.concat(item);
columns_offset += columns_width;
}
var box = [
0,
line_offset,
columns_offset,
line_size
]
this.normalize(box);
output = output.concat(box);
line_offset += line_size + 10;
}
elem.input = input.concat(this.empty(5 - Math.round(input.length / 4)));
elem.output = output.concat(this.empty(2 - Math.round(output.length / 4)));
}
this.get = function(){
return elem.input;
}
this.calculate = function(result, stat){
console.log('brain:',result);
this.item(result, function(item){
ctx.strokeStyle = "red";
ctx.strokeRect(item[0], item[1], item[2], item[3]);
})
}
this.train = function(){
for(var i = 0; i < 40; i++){
this.next();
}
}
}
Generate.train();
Generate.log = true;
var net,stat;
function train(){
net = new brain.NeuralNetwork({ hiddenLayers: [8,4]});
stat = net.train(trainData,{log: true, iterations: 250,learningRate: 0.01,errorThresh:0.05});
console.log('stat:',stat)
}
function calculate(){
Generate.calculate(net.run(Generate.get()))
}
</script>
</html>
My goal is to train the network to find the elements and show their sizes.
Procedure:
Click to train
Click generate
Click to calculate
As a result, the network shows average results and red indicates that the network has found.
Maybe not so I transfer the data, can on another it is necessary?

Make other nodes follow when dragging a node in Cytoscape.js

I'm new to cytoscape.js, I just want to make other nodes follow when dragging one node.
Appreciate your help
Write a listener, and update the other node positions appropriately in your callback:
eles.on()
node.position()
Here is how I did it. Note you have to save off the original positions at the grab event, and then update during the drag event.
function add_drag_listeners()
{
var all = cy.elements("node");
for (j = 0; j < all.length; j++)
{
cynode = all[j];
cynode.on("grab",handle_grab);
cynode.on("drag",handle_drag);
}
}
var grab_x = 0;
var grab_y = 0;
var drag_subgraph = [];
function handle_grab(evt)
{
grab_x = this.position().x ;
grab_y = this.position().y ;
var succ = this.successors();
drag_subgraph = [];
var succstr = "";
for (i = 0; i < succ.length; i++)
{
if (succ[i].isNode())
{
var old_x = succ[i].position().x;
var old_y = succ[i].position().y;
succstr += " " + succ[i].data("id");
drag_subgraph.push({old_x:old_x, old_y:old_y, obj:succ[i]});
}
}
}
function handle_drag(evt)
{
var new_x = this.position().x;
var new_y = this.position().y;
var delta_x = new_x - grab_x;
var delta_y = new_y - grab_y;
for (i = 0; i < drag_subgraph.length; i++)
{
var obj = drag_subgraph[i].obj;
var old_x = drag_subgraph[i].old_x;
var old_y = drag_subgraph[i].old_y;
var new_x = old_x + delta_x;
var new_y = old_y + delta_y;
obj.position({x:new_x, y:new_y});
}
}

How to use pixi.js onmouseout event to scale the object from 1.x back to 1

As mentioned in the title, I want onmouseover event of an object to scale it to 1.2 of its size, and then on onmouseout event I want it to scale back to its original size (1). But the onmouseout event does not return to its original size. Related code is as follows:
var renderer = PIXI.autoDetectRenderer(800, 500, { backgroundColor: 0x1099bb });
$("#container").append(renderer.view);
var stage = new PIXI.Container();
var container = new PIXI.Container();
stage.addChild(container);
var bunnyArray = new Array();
for (var i = 0; i < 5; i++)
{
bunnyArray[i] = new Array();
}
for (var i = 0; i < 5; i++) {
for (var j = 0; j < 5; j++) {
var rect = new PIXI.Graphics();
var width = 70;
rect.lineStyle(1, randomColor());
rect.interactive = true;
rect.hitArea = new PIXI.Rectangle(width*i,width*j, width + width * rect.scale.x, width + width * rect.scale.y);
//rect.position.x =10;
//rect.position.y = 10;
rect.position.set(width * i, width * j);
rect.zIndex = 2;
rect.drawRect(0, 0, width, width);
bunnyArray[i][j] = rect;
container.addChild(bunnyArray[i][j]);
}
}
for (var i = 0; i < bunnyArray.length; i++)
{
for (var j = 0; j < bunnyArray[i].length; j++)
{
bunnyArray[i][j].on("click", onClick);
bunnyArray[i][j].on("mouseover", onMouseover);
bunnyArray[i][j].on("mouseout", onMouseout);
}
}
container.x = 200;
container.y = 60;
renderImage();
function renderImage()
{
requestAnimationFrame(renderImage);
//renderer.render(container);
renderer.render(container);
//renderer.render(stage);
}
function animate() {
requestAnimationFrame(animate);
var bunny1 = thisPointer;
bunny1.rotation += 0.03;
cancelAnimationFrame(request);
}
function Scale(pointer) {
pointer.scale.x += 0.2;
pointer.scale.y += 0.2;
pointer.zIndex = 4;
return pointer;
}
function ScaleDel(requestPointer) {
//pointer.scale.x -= 0.2;
//pointer.scale.y -= 0.2;
if (requestPointer != undefined || requestPointer != null)
{
requestPointer.mouseover = null;
}
}
var thisPointer;
var request;
function onClick(eventData)
{
thisPointer = calcuatePos(eventData);
request = requestAnimationFrame(animate);
thisPointer.rotation = 0;
}
var requestPointer;
function onMouseover(eventData)
{
var thisPointer = calcuatePos(eventData);
//request = requestAnimationFrame(Scale);
requestPointer= Scale(thisPointer);
}
function onMouseout(eventData)
{
ScaleDel(requestPointer);
}
//生成随机颜色
function randomColor() {
var colorStr = Math.floor(Math.random() * 0xFFFFFF).toString(16).toUpperCase();
return "000000".substring(0, 6 - colorStr) + colorStr;
}
//判断是否点击了这个东西
function calcuatePos(eve)
{
var x = (eve.data.global.x);
var y = (eve.data.global.y);
x =x- container.x;
y =y- container.y;
var increaseRectScale = 70;
for (var i = 0; i < bunnyArray.length; i++) {
for (var j = 0; j < bunnyArray[i].length; j++) {
var instance = bunnyArray[i][j];
//increaseRectScale *= instance.scale.x;
if (instance.position.x <= x && instance.position.x + increaseRectScale >= x && instance.position.y <= y && instance.position.y + increaseRectScale >= y) {
//instance.pivot.set(increaseRectScale/2 , increaseRectScale/2 );
var a = document.createElement('a');
a.href = randomLink();
a.target = '_blank';
a.style.visibility = "hidden";
document.body.appendChild(a);
a.click();
return instance;
}
}
}
}
container.updateLayersOrder = function () {
container.children.sort(function (a, b) {
a.zIndex = a.zIndex || 0;
b.zIndex = b.zIndex || 0;
return b.zIndex - a.zIndex;
});
}
function randomNumber()
{
return Math.ceil(Math.random() * 10);
}
function randomLink()
{
var hyperLink = "";
var number = randomNumber();
switch (number)
{
case 0:
hyperLink = "http://www.baidu.com";
break;
case 1:
hyperLink = "http://www.17173.com";
break;
case 2:
hyperLink = "http://www.stackoverflow.com";
break;
case 3:
hyperLink = "http://www.163.com";
break;
case 4:
hyperLink = "http://www.5173.com";
break;
case 5:
hyperLink = "http://www.sina.com";
break;
case 6:
hyperLink = "http://www.qq.com";
break;
case 7:
hyperLink = "http://www.hp.com";
break;
case 8:
hyperLink = "http://www.youku.com";
break;
case 9:
hyperLink = "http://www.tudou.com";
break;
}
return hyperLink;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://files.cnblogs.com/files/kmsfan/pixi.js"></script>
<div id="container"></div>
You used "+=" for scaling up the Rect and, as Goose Ninja noted, you didn't scaled down in the ScaleDel function. If you want a scale factor of 1.2 just set to this scale.
Turns out you don't need the function calculatePos for detecting the target object, since PIXI binds the this to them in the interactive callbacks - http://www.goodboydigital.com/pixi-js-now-even-better-at-being-interactive/
Here is a codepen: http://codepen.io/anon/pen/qOXKEZ. I just changed the onMouseOver and noMouseOut functions and set the hitArea of each object to a local rectangle: new PIXI.Rectangle(0,0, width,width)
function onMouseover(eventData)
{
//var thisPointer = calcuatePos(eventData);
//request = requestAnimationFrame(Scale);
//requestPointer= Scale(thisPointer);
this.scale.set(1.2,1.2);
}
function onMouseout(eventData)
{
//ScaleDel(calcuatePos(eventData));
this.scale.set(1.0,1.0);
}

Jquery .offset() setter doesn't work

I'm making a functional for some site, which helps to group objects in one div and then change it as group, resize, rotate, etc. I have an issue with saving parametres of edited objects inside div. After resizing i have to correct their position on the workarea, but it seems that jquery .offset() doesn't work.
function grouped_objects_saving(merged_block_id){
var count = $("#"+merged_block_id+" > .merged").length;
var angle = transform_to_angle(merged_block_id);
var scaleX = transform_to_scale(merged_block_id, "x");
var scaleY = transform_to_scale(merged_block_id, "y");
var brows = browser();
var topOff = [];
var leftOff = [];
var objId = [];
var width = [];
var height = [];
var imageAngle = [];
var resultAngle = [];
var transform = "";
var check = false;
switch(brows){
case "Chrome":
transform = $('#'+merged_block_id).css('-webkit-transform');
break;
case "IE":
transform = $('#'+merged_block_id).css('-ms-transform');
break;
case "Firefox":
transform = $('#'+merged_block_id).css('-moz-transform');
break;
default:
transform = $('#'+merged_block_id).css('transform');
break;
}
for (i=0; i<count; i++) {
objId[i] = $("#"+merged_block_id+" > .merged").eq(i).attr('id');
topOff[i] = $("#"+merged_block_id+" > .merged").eq(i).offset().top;
leftOff[i] = $("#"+merged_block_id+" > .merged").eq(i).offset().left;
width[i] = $("#"+objId[i]).width();
height[i] = $("#"+objId[i]).height();
imageAngle[i] = transform_to_angle(objId[i]);
resultAngle[i] = imageAngle[i]+angle;
$("#"+objId[i]).offset({top: topOff[i], left: leftOff[i]});
}
for (i=0; i<count; i++) {
$("#"+objId[i]).appendTo($('#workarea'));
switch(brows){
case "Chrome":
$("#"+objId[i]).css({'-webkit-transform': 'rotate('+resultAngle[i]+'deg)'});
break;
case "IE":
$("#"+objId[i]).css({'-ms-transform': 'rotate('+resultAngle[i]+'deg)'});
break;
case "Firefox":
$("#"+objId[i]).css({'-moz-transform': 'rotate('+resultAngle[i]+'deg)'});
break;
default:
$("#"+objId[i]).css({'transform': 'rotate('+resultAngle[i]+'deg)'});
break;
}
$("#"+objId[i]).width(width[i]*scaleX);
$("#"+objId[i]).height(height[i]*scaleY);
$("#"+objId[i]).appendTo($('#'+merged_block_id));
//$("#"+objId[i]).addClass("editable selectable");
if (i==count-1) {
check = true;
}
}
if (check==true){
for (i=0; i<count; i++) {
console.log('$("#'+objId[i]+'").offset({top:'+topOff[i]+', left:'+leftOff[i]+'});');
$("#"+objId[i]).offset({top: topOff[i], left: leftOff[i]});
}
}
return true;
}
Problem is in the last string:
$("#"+objId[i]).offset({top: topOff[i], left: leftOff[i]});
If i copy the string which comes from console:
console.log('$("#'+objId[i]+'").offset({top:'+topOff[i]+', left:'+leftOff[i]+'});'
for example
$("#custom-image-58clx").offset({top:393.089111328125, left:407.17822265625});
and use it in console, that works, offset sets correctly.
I have no idea why it doesn't work from code.
I still got no idea why original code didn't work and .offset was not applied, but after changing code to the one below, it worked fine.
function grouped_objects_saving(merged_block_id, type){
var count = $("#"+merged_block_id+" > .merged").length;
var angle = transform_to_angle(merged_block_id);
var scaleX = transform_to_scale(merged_block_id, "x");
var scaleY = transform_to_scale(merged_block_id, "y");
console.log("scaleX: " + scaleX);
console.log("scaleY: " + scaleY);
var brows = browser();
var transform = "";
switch(brows){
case "Chrome":
transform = $('#'+merged_block_id).css('-webkit-transform');
break;
case "IE":
transform = $('#'+merged_block_id).css('-ms-transform');
break;
case "Firefox":
transform = $('#'+merged_block_id).css('-moz-transform');
break;
default:
transform = $('#'+merged_block_id).css('transform');
break;
}
var topOff = [];
var leftOff = [];
var objId = [];
var width = [];
var height = [];
var imageAngle = [];
var resultAngle = [];
for (i=0; i<count; i++) {
objId[i] = $("#"+merged_block_id+" > .merged").eq(i).attr('id');
topOff[i] = $("#"+merged_block_id+" > .merged").eq(i).offset().top;
leftOff[i] = $("#"+merged_block_id+" > .merged").eq(i).offset().left;
width[i] = $("#"+objId[i]).width();
height[i] = $("#"+objId[i]).height();
imageAngle[i] = transform_to_angle(objId[i]);
resultAngle[i] = imageAngle[i]+angle;
$("#"+objId[i]).offset({top: topOff[i], left: leftOff[i]});
console.log("resultAngle: "+ resultAngle[i]);
console.log("ObjId: "+objId[i]);
console.log("topOff: "+topOff[i]);
console.log("leftOff: "+leftOff[i]);
}
for (i=0; i<count; i++) {
$("#"+objId[i]).removeAttr('style');
$("#"+objId[i]).appendTo($('#workarea'));
$("#"+objId[i]).css({
'width': width[i]*scaleX+"px",
'height': height[i]*scaleY+"px",
'-webkit-transform': 'rotate('+resultAngle[i]+'deg)',
'-ms-transform': 'rotate('+resultAngle[i]+'deg)',
'-moz-transform': 'rotate('+resultAngle[i]+'deg)',
'transform': 'rotate('+resultAngle[i]+'deg)',
'position': 'absolute'
}).offset({top: topOff[i], left: leftOff[i]});
}
}
return true;
}
I suppose that it was caused by wrong sequence of actions.

How can I access imageData from a renderTarget?

I'm a university masters degree student in Computer Graphics, I'm having difficulty using three.js to access the image data(pixels) of a texture created with a EffectComposer.
The first composer (composer) is using a line detection shader to find road lines in a lane, and put the result in a renderTarget (rt_Binary). My second composer (fcomposer2) uses a shader that paints an area green if is within a certain space.
The plan was to render the composer first and after analysing the rt_Binary image i could determine the limits.
I found some functions that allow me to get the imagedata (getImageData(image) and getPixel(imagedata, x, y)) but they only work on these occasions:
// before image
var imagedata = getImageData(videoTexture.image);
// processed image
var imagedata2 = getImageData(renderer.domElement);
If a put the first composer to render to screen, i get the correct values for the limits, but when i put the second composer, i get the wrong values for the limits.
Is there any way to get the imageData from a renderTarget? is so, how?
Edit1:
Here's the code for script that i use for the html:
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<title>Tests WebGL</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="three.js/build/three.js"></script>
<script src="js/CopyShader.js"></script>
<script src="js/EffectComposer.js"></script>
<script src="js/MaskPass.js" ></script>
<script src="js/RenderPass.js" ></script>
<script src="js/ShaderPass.js"></script>
<script src="js/stats.min.js" ></script>
<!-- Shaders -->
<script src="js/shaders/KernelShader.js" ></script>
<script src="js/shaders/SimpleShader.js"></script>
<script src="js/shaders/MyShader.js"></script>
<script src="js/shaders/BinaryShader.js"></script>
<script type="text/javascript">
var scene, fscene, sceneF;
var camera;
var renderer, rt_Binary;
var composer;
var stats;
var fmaterial;
var videoTexture;
var videoWidth = 480;
var videoHeight = 270;
var rendererWidth = videoWidth;
var rendererHeight = videoHeight;
var x_max = 345;//videoWidth*0.72; //
var x_min = 120;//videoWidth*0.25; //
var y_max = 189;//videoHeight*0.7 ;
var y_min = 148;//videoHeight*0.55;
// var ml=0.0, mr=0.0, mm=0.0;
// var bl=0.0, br=0.0, bm=0.0;
var yMaxL = 0, yMinL = 0, yMaxR = 0, yMinR = 0;
var xMaxL = 0, xMinL = 0, xMaxR = 0, xMinR = 0;
var frame = 0;
// init the scene
window.onload = function() {
renderer = new THREE.WebGLRenderer(
{
antialias: true, // to get smoother output
preserveDrawingBuffer: true // to allow screenshot
});
renderer.setClearColor(0xffffff, 1);
renderer.autoClear = false;
renderer.setSize(rendererWidth, rendererHeight);
document.getElementById('container').appendChild(renderer.domElement);
//add stats
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
document.getElementById('container').appendChild(stats.domElement);
// create Main scene
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(35, rendererWidth / rendererHeight, 1, 10000);
camera.position.set(0, 1, 6);
scene.add(camera);
// define video element
video = document.createElement('video');
// video.src = 'GOPR0007.webm';
video.src = 'output.webm';
video.width = videoWidth;
video.height = videoHeight;
video.autoplay = true;
video.loop = true;
//create 3d object and apply video texture to it
var videoMesh = new THREE.Object3D();
scene.add(videoMesh);
videoTexture = new THREE.Texture(video);
var geom = new THREE.PlaneGeometry(1, 1);
material = new THREE.MeshBasicMaterial({map: videoTexture});
var mesh = new THREE.Mesh(geom, material);
videoMesh.add(mesh);
var renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBufer: false };
rt_Binary = new THREE.WebGLRenderTarget( videoWidth, videoHeight, renderTargetParameters );
// Composers
// composer = new THREE.EffectComposer(renderer, renderTarget2);
composer = new THREE.EffectComposer(renderer, rt_Binary );
composer.addPass(new THREE.RenderPass(scene, camera));
var simple = new SimpleShader.Class(videoWidth, videoHeight);
var simEffect = new THREE.ShaderPass(simple.shader);
composer.addPass(simEffect);
var ef = new BinaryShader.Class(videoWidth, videoHeight, 1.1, [-2,-2,-2,0,0,0,2,2,2]);
var effect = new THREE.ShaderPass(ef.shader);
composer.addPass(effect);
var copyPass = new THREE.ShaderPass(THREE.CopyShader);
// copyPass.renderToScreen = true;
composer.addPass(copyPass);
//New scene
sceneF = new THREE.Scene();
sceneF.add(camera);
var videoMesh2 = new THREE.Object3D();
sceneF.add(videoMesh2);
var geomF = new THREE.PlaneGeometry(1, 1);
var materialF = new THREE.MeshBasicMaterial({map: videoTexture});
var meshF = new THREE.Mesh(geomF, materialF);
sceneF.add(meshF);
fcomposer2 = new THREE.EffectComposer(renderer );
fcomposer2.addPass(new THREE.RenderPass(sceneF, camera));
fcomposer2.addPass(simEffect);
var ef1 = new MyShader.Class(videoWidth, videoHeight, [yMaxL,yMinL,xMaxL,xMinL,yMaxR,yMinR,xMaxR,xMinR], videoTexture);
var effect1 = new THREE.ShaderPass(ef1.shader);
fcomposer2.addPass(effect1);
var copyPass2 = new THREE.ShaderPass(THREE.CopyShader);
copyPass2.renderToScreen = true;
fcomposer2.addPass(copyPass2);
animate();
}
// animation loop
function animate() {
// loop on request animation loop
// - it has to be at the begining of the function
requestAnimationFrame(animate);
// do the render
render();
stats.update();
if ((frame % 50) == 0) {
console.log("frame ", frame, " ");
console.log("yMaxL: ", yMaxL, " ");
console.log("yMinL: ", yMinL, " ");
console.log("xMaxL: ", xMaxL, " ");
console.log("xMinL: ", xMinL, " ");
console.log("yMaxR: ", yMaxR, " ");
console.log("yMinR: ", yMinR, " ");
console.log("xMaxR: ", xMaxR, " ");
console.log("xMinR: ", xMinR, " ");
manipulatePixels();
}
frame = frame + 1;
yMaxL = 0, yMinL = 0, yMaxR = 0, yMinR = 0;
xMaxL = 0, xMinL = 0, xMaxR = 0, xMinR = 0;
}
// render the scene
function render() {
if (video.readyState === video.HAVE_ENOUGH_DATA) {
videoTexture.needsUpdate = true;
}
// actually render the scene
renderer.clear();
composer.render();
var left_x = new Array();
var left_y = new Array();
var l = 0;
var right_x = new Array();
var right_y = new Array();
var r = 0;
if (frame == 200) {
var imagedata2 = getImageData(renderer.domElement);
var middle = imagedata2.width / 2;
for (var x=x_min; x < x_max; x=x+1) {
for (var y=y_min; y < y_max; y=y+1) {
var pixel = getPixel(imagedata2, x, y);
if (pixel.g > 0)
{
//console.log(pixel);
if (x < middle) {
left_x[l] = x;
left_y[l] = y;
l++;
}
else {
right_x[r] = x;
right_y[r] = y;
r++;
}
}
}
}
lineEquation(left_x, left_y, right_x, right_y);
}
fcomposer2.render();
}
function lineEquation(left_x,left_y,right_x,right_y) {
var newYMAX = left_y[0];
var newYMIN = left_y[0];
var maximosL = new Array();
var minimosL = new Array();
//left
for (var i=1; i < left_y.length; i++) {
if (left_y[i]>newYMAX) newYMAX = left_y[i];
else {
if (left_y[i]<newYMIN) newYMIN = left_y[i];
}
}
yMaxL = newYMAX;
yMinL = newYMIN;
// yMaxL = ymaxL/videoHeight;
// yMinL = yminL/videoHeight;
var pmin=0, pmax=0;
for (var i=0; i < left_y.length; i++) {
if (left_y[i] === newYMAX) {
// console.log(left_y[i]);
// console.log(left_x[i]);
maximosL[pmax] = left_x[i];
pmax++;
}
}
for (var j=0; j < left_y.length; j++) {
if (left_y[j] === newYMIN) {
// console.log(left_y[j]);
// console.log(left_x[j]);
minimosL[pmin] = left_x[j];
pmin++;
}
}
// console.log(maximosL);
// console.log(minimosL);
var sumMAX = 0, sumMIN = 0;
for (var i=0; i< maximosL.length; i++) {
sumMAX = sumMAX + maximosL[i];
}
for (var j=0; j< minimosL.length; j++) {
sumMIN = sumMIN + minimosL[j];
}
xMaxL = sumMAX/maximosL.length;
xMinL = sumMIN/minimosL.length;
// xMaxL /= videoWidth;
// xMinL /= videoWidth;
//right
var maximosR = new Array();
var minimosR = new Array();
newYMAX = right_y[0];
newYMIN = right_y[0];
pmin=0; pmax=0;
for (var i=0; i < right_y.length; i++) {
if (right_y[i]> newYMAX) newYMAX = right_y[i];
else {
if (right_y[i]< newYMIN) newYMIN = right_y[i];
}
}
yMaxR = newYMAX;
yMinR = newYMIN;
// yMaxR = ymaxR/videoHeight;
// yMinR = yminR/videoHeight;
for (var i=0; i < right_y.length; i++) {
if (right_y[i] === newYMAX)
{maximosR[pmax] = right_x[i]; pmax++;}
if (right_y[i] === newYMIN)
{minimosR[pmin] = right_x[i]; pmin++;}
}
// console.log(maximosR);
// console.log(minimosR);
xMaxR=0;
for (var i=0; i< maximosR.length; i++) {
xMaxR += maximosR[i];
}
xMinR=0;
for (var i=0; i< minimosR.length; i++) {
xMinR += minimosR[i];
}
// console.log(xMaxR);
// console.log(xMinR);
xMaxR /= maximosR.length;
xMinR /= minimosR.length;
// console.log(xMaxR);
// console.log(xMinR);
// xMinR /= videoWidth;
// xMaxR /= videoWidth;
}
function manipulatePixels() {
// imagem antes
var imagedata = getImageData(videoTexture.image);
// imagem processada
var imagedata2 = getImageData(renderer.domElement);
// console.log(getPixel(imagedata, 480 - 1, 270 - 1));
// console.log(getPixel(imagedata2, 480 - 1, 270 - 1));
}
function getImageData(image) {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
return context.getImageData(0, 0, image.width, image.height);
}
function getPixel(imagedata, x, y) {
var position = (x + imagedata.width * y) * 4, data = imagedata.data;
return {r: data[ position ], g: data[ position + 1 ], b: data[ position + 2 ], a: data[ position + 3 ]};
}
function findLineByLeastSquares(values_x, values_y) {
var sum_x = 0;
var sum_y = 0;
var sum_xy = 0;
var sum_xx = 0;
/*
* We'll use those variables for faster read/write access.
*/
var x = 0;
var y = 0;
var values_length = values_x.length;
if (values_length != values_y.length) {
throw new Error('The parameters values_x and values_y need to have same size!');
}
/*
* Nothing to do.
*/
if (values_length === 0) {
return [ [], [] ];
}
/*
* Calculate the sum for each of the parts necessary.
*/
for (var v = 0; v < values_length; v++) {
x = values_x[v];
y = values_y[v];
sum_x += x;
sum_y += y;
sum_xx += (x*x);
sum_xy += (x*y);
}
console.log (sum_x);
console.log(sum_y);
console.log(sum_xx);
console.log(sum_xy);
console.log(values_length);
/*
* Calculate m and b for the formular:
* y = x * m + b
*/
var m = (sum_x*sum_y - values_length*sum_xy) / (sum_x*sum_x - values_length*sum_xx);
var b = (sum_y - (m*sum_x))/values_length;
//console.log([m,b]);
return [m, b];
}
//resize method
/**window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
} */
</script>
Edit2 : Some images of what i'm trying to do: Image 1 shows the results from composer on the console, the limits i get from the lineEquation function are the correct ones for what i intend to do, but in Image 2 shows the results from fcomposer2 (fixed area) and on the console, the limits are the wrong ones.
![Image1]: http://prntscr.com/1ays73
![Image2]: http://prntscr.com/1ays0j
Edit3 :
By "access" i mean to be able to read the values of the pixels from the texture created by the binaryShader.
For example, in image1 the lines are painted in blue/green tone, I wanted to search the position of the pixels (x,y) in the image that the renderTarget would save. If i could find those pixels, i could adapt the green area in image2 to fit between the road lines.
This processing is need to make the green area overlap the current driving lane the user is currently on, if i can't get those points, i can't identify a lane.
I got it to work. Apparently i forgot to declare the fcomposer2 in the beginning of the script.
Thanks for the responses/comments, and sorry for the inconvenience.

Categories

Resources