I found a neat plugin named "isomer master". This allows you to make an isometric landscape using coordinates and colors. What im trying to do currently is make a placement grid in which you hover your mouse over an area to place a block. The syntax is as follows:
var Shape = Isomer.Shape;
var Point = Isomer.Point;
var Color = Isomer.Color;
var red = new Color(160, 60, 50);
var blue = new Color(226, 99, 0);
iso.add(Shape.Prism(Point.ORIGIN, 3, 3, 1));
iso.add(Shape.Pyramid(Point(0, 2, 1)), red);
I figured it out, I was using incorrect syntax in getting the mouse's position.
Related
I am using LineSegmentsGeometry and LineMaterial to create thick cube edges. I want to change the color of the edge on hover.
const edgesGeometry = new LineSegmentsGeometry().fromEdgesGeometry(
new THREE.EdgesGeometry(mesh.geometry, 40)
);
const colors = [];
for (let i = 0; i < edgesGeometry.attributes.position.count; i++) {
colors.push(0, 0, 0);
}
edgesGeometry.setAttribute(
"color",
new THREE.Float32BufferAttribute(colors, 3)
);
const edgesMaterial = new LineMaterial({
color: "black",
vertexColors: true,
linewidth: 0.001
});
const line = new THREE.LineSegments(edgesGeometry, edgesMaterial);
const setLineColor = (color) => {
const { index, object } = intersected;
object.geometry.attributes.color.setXYZ(index, color.r, color.g, color.b);
object.geometry.attributes.color.setXYZ(index + 1, color.r, color.g, color.b);
object.geometry.attributes.color.needsUpdate = true;
};
This code only works if using thin lines with LineBasicMaterial. Can I do it somehow with bold lines?
I also have other shapes with this logic
sandbox here
https://codesandbox
You can do it with fat lines! LineSegmentsGeometry (fat lines) is structured quite a bit differently from EdgesGeometry, though, so the approach must be updated.
Looking at your example there are a few things to note:
When creating fat lines instanced BufferAttributes are created for the start and end of each line (instanceStart and instanceEnd). You cannot use geometry.attributes.position to determine the number of colors needed for a segment. Instead you should use attributes.instanceStart.count and use the LineSegmentsGeometry.setColors function to ensure the correct instanced color attributes for each segment are set up.
The LineMaterial color should be set to white so the vertex colors show when multiplied.
"index" is not provided when intersecting with fat lines. Instead you should use "faceIndex" and use that to set the color fields on the instanceColorStart and instanceColorEnd attributes and update them accordingly.
Here's demo modified for your provided code showing how to accomplish this with some short inline comments:
https://jsfiddle.net/juoz5yLv/1/
I'm using opencv for Javascript to generate the source image, which I place in a canvas' context via putImageData.
I need to draw a line around the red part of the image that is about 20 pixels away from the red. The second image is what I'm after... hand drawn, but hopefully you get the idea.
Simply cloning (into an overlaid canvas) and scaling an image behind the red image doesn't work (scaling isn't the right approach). I thought about using dilate but it doesn't seem to be reliable, and it's very slow.
Update: Per a commenter's request, here is an example of why dilation doesn't work well.
// Dilate the image
let src = cv.imread('canvasOffset');
let dst = new cv.Mat();
let M = cv.Mat.ones(40, 40, cv.CV_8U);
let anchor = new cv.Point(-1, -1);
cv.dilate(src, dst, M, anchor, 1, cv.BORDER_CONSTANT,
cv.morphologyDefaultBorderValue());
cv.imshow('canvasOffset', dst);
src.delete(); dst.delete(); M.delete()
Thanks to Cris Luengo this is solved.
I was able to use OpenCV's dilate with an elliptical structuring element. It does exactly what I needed.
Given a "canvasOffset" canvas containing the original image:
let src = cv.imread('canvasOffset');
let dst = new cv.Mat();
let M = new cv.Mat();
let ksize = new cv.Size(25, 25);
M = cv.getStructuringElement(cv.MORPH_ELLIPSE, ksize);
let anchor = new cv.Point(-1, -1);
cv.dilate(src, dst, M, anchor, 1, cv.BORDER_CONSTANT, cv.morphologyDefaultBorderValue());
cv.imshow('canvasOffset', dst);
Result:
I have a simple solution implemented in Python.
First I converted the given image to a binary image where the red object is the region of interest (white)
Next I found contours using the built-in function available in OpenCV. I drew the resulting contour with thick borders on another image with black pixels having the same shape as the original image.
I found contours on this black image and drew the resulting contours on the original image. I drew contours with no thickness this time.
(As I said, the code is written in python, if you want me to share it)
import cv2
import numpy as np
import os
path = r'C:\Users\Desktop\Stack\contour'
im = cv2.imread(os.path.join(path, 'handle.jpg'))
im = cv2.resize(im, (0, 0), fx=0.5, fy=0.5) #--- resizing the image
im2 = im.copy() #--- having another copy of the original image
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
ret2, th2 = cv2.threshold(imgray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
cv2.imshow('th2.jpg', th2) #--- Image 1
_, contours, hierarchy = cv2.findContours(th2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]
mask = np.zeros_like(im)
cv2.drawContours(mask, contours, -1, (255, 255, 255), 33)
cv2.imshow('mask.jpg', mask) #--- Image 2
ret2, mask_th2 = cv2.threshold(mask[:,:,1], 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
_, contours1, hierarchy = cv2.findContours(mask_th2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(im2, contours1, -1, (0, 0, 0), 2)
cv2.imshow('final.jpg', im2) #--- Image 3
cv2.waitKey(0)
cv2.destroyAllWindows()
I have a web app prototype where nodes similar to Blender shader editor are connected to each other. I am using Paper.js framework
I want them to be connected using those smooth Bezier-like curves. So I have 2 shapes and I can connect them by making a straight line, but now I want to have handles at the endpoints that smooth these objects out, kinda like this:
So 2 handles on endpoints, pointing horizontally for half the bounding box of the path.
The problem is I can't figure out how to add and edit those handles using Paper.js
The code I have is this:
function makeRectangle(topLeft, size, cornerSize, colour){
var rectangle = new Rectangle(topLeft, size);
var cornerSize = cornerSize;
var path = new Path.RoundRectangle(rectangle, cornerSize);
path.fillColor = colour;
return path;
}
var xy1 = new Point(50,50); //Position of 1st rectangle.
var size = new Size(100, 80); //Size
var c = new Size(8,8); //Corner radius
var col = "#167ee5"; //Colour
var r1 = makeRectangle(xy1, size, c, col); //Make first rectangle
var xy2 = new Point(467,310); //Position of second rectangle
var size2 = new Size(115, 70); //Size of second rectangle
var r2 = makeRectangle(xy2, size2, c, col); //Make secont rectangle
var r1cent = r1.bounds.center; //Get the center points, they will be used as endpoints for the curve.
var r2cent = r2.bounds.center;
var connector = new Path(r1cent, r2cent); //Ok so I made this path... Now what? How do access and edit the handlers at endpoints like in the image?
connector.strokeColor = 'black'; //Give it some colour so we can see it.
You can paste all this code here without any setup, it's a good way to test the framework.
You can use Segment objects when defining the connector rather than using Points (or you can set the handleIn and handleOut properties after creating the path).
The doc is here: Segment
And here is a sketch showing how to use handleIn and handleOut with your code:
sketch.paperjs.org solution
Is there any way to group bunch of elements of paper in one set and only position that set in the paper?
For example At This Example I was trying to put some circles in side a rectangle and just position the rectangle in each part of the paper. Can you please let me know how to do it?
var paper = Raphael('my-canvas', 500, 300);
paper.canvas.style.backgroundColor = '#F00';
var rect = paper.rect(5, 5, 100, 100);
var st = paper.set();
st.push(
rect.circle(10, 10, 5),
rect.circle(30, 10, 5));
You can do this via a transform on the set (you could also do it with another attribute like x,y but only if the elements use that specific attribute).
Its worth noting, that although you can apply a transform to the set, it is in effect applying the transform to each element in the set. Ie there is no specific 'set' or 'group' element in Raphael (there is in Snap.svg which is its updated brother, but doesn't quite have the same backwards compatibility). So there is no true hierarchy of groups, where they could have separate transforms which cascade down.
var paper = Raphael('my-canvas', 500, 300);
paper.canvas.style.backgroundColor = '#F00';
var rect = paper.rect(5, 5, 100, 100);
var st = paper.set();
st.push(
paper.rect(5, 5, 100, 100),
paper.circle(10, 10, 5).attr({ fill: 'blue' }),
paper.circle(30, 10, 5).attr({ fill: 'green' })
);
st.transform('t20,20');
st.animate({ transform: 't100,100' }, 2000);
Its worth looking at the Raphael docs for transforms if not sure here
jsfiddle
Instead of using a set, you can create a new div, add a new paper element to this div and then change the position of the div.
If you are using jquery, it could look something like this:
$(".body").append('<div id="setContainer"></div>');
paper = new Raphael(document.getElementById("setContainer"), 500, 300);
paper.canvas.style.backgroundColor = '#F00';
var rect = paper.rect(5, 5, 100, 100);
var circle = paper.circle(10, 10, 5);
var circle2 = paper.circle(30, 10, 5);
// then you can adjust the position of the div, for example to 100,100
$("#setContainer").css("top", 100);
$("#setContainer").css("left", 100);
The advantage of using this approach rather than a set is that it gives you more flexibility for the way you want to manipulate the elements you are grouping together.
You can even wrap a function around this code in order to define the id of the container programatically if you wanted to create several instances of the same group of elements.
I'd like to make a minimap of my rpg game.
Is making a minimap as simple as dividing all object dimensions, velocities, and coordinates by however large you want the minimap?
For example below... You have a size of 1000x1000px, a canvas (viewport) of 500x500px, the player is located in the center of the viewport... If you wanted a minimap half the size of the actual world, you would do:
Player/Viewport x,y velocity/2
Player/Viewport x,y coordinates/2
Canvas, world, and all objects' width and height are divided by 2
etc...
That way the rendering of the minimap on the world and the velocities are scaled accurately? Am I missing anything?
Thanks!
EDIT: Something like this?
function miniMap() {
$(".minimapHolder").show();
$("#mini_map").text("hide minimap");
var minicanvas = document.getElementById("miniMap");
ministage = new createjs.Stage("miniMap");
minicam = new createjs.Shape();
minicam.graphics.beginStroke("white").drawRoundRect(0, 0, 100, 40, 5);
//blip representation of Player
player_blip = new createjs.Shape();
player_blip.graphics.beginFill("yellow").drawRoundRect(0, 0, 11.2, 12, 1);
animal_blip = new createjs.Shape();
animal_blip.graphics.beginFill("red").drawRoundRect(0, 0, 24.4, 21.6, 1);
player_blip.x = players_Array[0].x/5;
player_blip.y = players_Array[0].y/5;
animal_blip.x = animalContainer.x/5;
animal_blip.y = animalContainer.y/5;
minicam.x = players_Array[0].x-110;
minicam.y = players_Array[0].y-110;
ministage.addChild(player_blip, animal_blip, minicam);
ministage.update();
}
function updateMiniMap() {
player_blip.x = players_Array[0].x/5;
player_blip.y = players_Array[0].y/5;
if (ContainerOfAnimals.children[0] != null) {
var pt = ContainerOfAnimals.localToGlobal(ContainerOfAnimals.children[0].x, ContainerOfAnimals.children[0].y);
console.log(pt.x);
animal_blip.x = pt.x/5;
animal_blip.y = pt.y/5;
} else {
ministage.removeChild(animal_blip);
}
minicam.x = player_blip.x-40;
minicam.y = player_blip.y-15;
ministage.update();
}
Gives:
Short anwswer: "It will(most likely) work." ... but:
What you are trying to achieve is just scaling the stage/container, so you could also just use a copy of everything and put it into a container and scale it down to 0.5, but that is not the purpose of a minimap.
Objects of the minimap should only be a representation of the object in the 'real' world and should therefore not have any velocity ect.(that should especially not be updated separately from the 'real' world) - while your approach will probably work, you'd allways have to keep track and update every property, this will get messy quickly or even lead to differences if you miss some tiny things.
A more 'clean'(and simple) approach to this would be, that each minimap-object has a reference to the object in the 'real' world and on each tick, it just reads the x/y-coordinates and updates its' own coordinates based on the minimap-scale.
Another thing is the graphics: Scaling-operations can be costly(performance wise), especially when they are done each frame, so IF you use the same graphics for the minimap you should at least used a cached DisplayObject and not have the graphics scaled each frame.