Graphics2D won't fill a path - java

I'm making a game and I want to draw mountains myself. I make the mountains using mid point displacement, store the points in an arraylist and then retrieve them in my Jpanel in my view. I draw other stuff like grass and g2 will fill them with colors but not my mountain. Here is the result:
http://i.imgur.com/5ty3C.png
Here's the code:
Point2D.Double start = new Point2D.Double(50, 400);
listePoints.add(start);
Point2D.Double end = new Point2D.Double(modele.getLargeur(), 400);
listePoints.add(end);
this.maxIterations = 9;
int iterations = 0;
int minHeight = 5;
double nbrRandom = 10;
while(iterations < this.maxIterations) {
iterations ++;
int counter = 0;
int size = listePoints.size()-1;
int index = 0;
while (compteur < size) {
Point2D.Double point1 = listePoints.get(index);
Point2D.Double point2 = listePoints.get(index+1);
double milieu = Math.abs(point2.x - point1.x)/2;
int orientation = Equations.randInt(1);
switch(orientation ) {
case 0: orientation = -1;break;
case 1: orientation = 1;break;
}
Point2D.Double point3 = new Point2D.Double(point1.x+milieu,point1.y+(Equations.rand((nbrRandom+iterations = 0;
int minHeight)*orientation)));
nbrRandom = nbrRandom /2;
listePoints.add(index+1,point3);
index +=2;
counter++ ;
}
}
Point2D.Double point1 = new Point2D.Double(start.x,500);
listePoints.add(0,point1);
point1 = new Point2D.Double(end.x,500);
listePoints.add(listePoints.size(),point1);
point1 = new Point2D.Double(start.x,500);
listePoints.add(listePoints.size(),point1);
/***************************** VIEW **/
Path2D.Double path = new Path2D.Double(Path2D.Double.WIND_EVEN_ODD);
for (int j = 0;j < list.size()-1; j++) {
Point2D.Double point1 = list.get(j);
Point2D.Double point2 =list.get(j+1);
path.moveTo(point1.x, point1.y);
path.lineTo(point2.x, point2.y);
path.closePath();
g2.draw(path);
g2.fill(path);
}
}

If the question is "How do I fill the area below the jagged line with color?", the answer is:
Join the end (presumably the right-hand side of the ArrayList of points) to the bottom of the container on the RHS.
Join that point to the bottom LHS.
Then call path.closePath();
Or to put that another way, join the path end to the path start via the 'ground'.
If this explanation does not solve the problem for you (or if I guessed the question wrong), post an SSCCE.

Related

Java/Libgdx ShadowCast Rendering

After following a tutorial, I was able to form a simple shadowcasting algorithm that casts rays in different directions and connects those rays sorted by angle to form a polygon. Now that that's done with, I want to use this "field of view", in order to only show/render sprites inside that polygon. However, I do not really have an idea of how to do this.
Code in my render() method:
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
//Render my stuctues
for (Structure s : worldStructures)
{
for (Vector2[] polygon : s.polygonList)
{
float[] vertices = s.getPolygonVectors(polygon);
shapeRenderer.polygon(vertices);
}
}
//Re-initiate my array
rayAngles = new float[rays.size()];
rayPolygon = new float[rays.size()*2];
//Go through each of my rays, calculate their angle and point of intersection, put the latter in
a Map
//Go through the keyset of my map (T1 values) and find which ray is the closest
//render a ray according to that point of intersection's values
Map<Float,PointOfIntersection> angleMap = new HashMap<>();
for (Line2D.Float ray : rays)
{
float x2 = 0f;
float y2 = 0f;
Vector2 rV = new Vector2(ray.x2-player.getPos().x,ray.y2-player.getPos().y);
float angle = (float) Math.atan2(rV.y,rV.x);
Map<Float,PointOfIntersection> closestMap =new HashMap<Float,PointOfIntersection>();
for(Structure structure : worldStructures) {
for (Line2D.Float[] segments : structure.getBodySegments()) {
for (int i = 0; i < segments.length; i++) {
PointOfIntersection currentInt = getIntersection(ray, segments[i]);
if (currentInt != null) {
closestMap.put(currentInt.T1, currentInt);
}
}
}
}
Float[] allPoints = closestMap.keySet().toArray(new Float[0]);
if (allPoints.length > 0) {
float closestPoint = allPoints[0];
for (int i = 0; i < allPoints.length; i++) {
if(allPoints[i]<closestPoint)
{
closestPoint = allPoints[i];
}
}
PointOfIntersection closestIntersection = closestMap.get(closestPoint);
int index = rays.indexOf(ray);
rayAngles[index] = angle;
angleMap.put(rayAngles[index],closestIntersection);
x2 = closestIntersection.pointOfIntersection.x;
y2 = closestIntersection.pointOfIntersection.y;
}
shapeRenderer.line(ray.x1,ray.y1,x2,y2);
}
//Sort angles, Make a polygon according to those sorted angles and their point of intersection
//Lets me connect said polygon clockwise
Arrays.sort(rayAngles);
for (int i = 0, j = 0; i < rayAngles.length; i++, j += 2) {
PointOfIntersection point = angleMap.get(rayAngles[i]);
rayPolygon[j] = point.pointOfIntersection.x;
rayPolygon[j + 1] = point.pointOfIntersection.y;
}
System.out.println(rayPolygon.length);
shapeRenderer.end();
//Initialize my Region, texture and batch to render the polygon.
if (gameLightOn) {
polyReg = new PolygonRegion(new TextureRegion(textureSolid), rayPolygon,
triangulator.computeTriangles(rayPolygon).toArray());
poly = new PolygonSprite(polyReg);
poly.setOrigin(0, 0);
polyBatch = new PolygonSpriteBatch();
polyBatch.setProjectionMatrix(camera.combined);
polyBatch.begin();
poly.draw(polyBatch);
polyBatch.end();
}

I am trying to add collision detection to this particle system I made

I am doing this in processing which is essentially java and I have never attempted anything like this before. Can't find any examples of collision detection using arrays to map the pixels.
I am not really trying to make them realistic collisions. I was thinking it would have the same response as if it hit a wall which is just for it to change directions in whatever axis is appropriate for the wall it hit.
I have tried checking if the x and y position are the same but can't seem to make that work. I'd appreciate any input on this.
import java.util.Arrays;
int numOfParticles = 10;
float[] x = new float[numOfParticles]; //initial position of y only matters
float[] px = new float[numOfParticles];
float[] y = new float[numOfParticles];
float[] py = new float[numOfParticles];
int speed = 10;//inversly related to speed
float[] xIncrement = new float[numOfParticles]; //the ratio of increments determines the pattern
float[] yIncrement = new float[numOfParticles]; // it is the slope of the line
//float xIncrement = 10/speed; //the ratio of increments determines the pattern
//float yIncrement = 11/speed; // it is the slope of the line
color currentColor;
int alpha = 100;//range of 0-255
//radius of ball
int radius = 1;
//thickness of line behind ball
int thickness = 5;
int rateOfColor = 5; //this is inversely related to rate but also changes the range of colors
int maxColor = 255;
int minColor = 0;
void setup(){
size(500,500);
background(0);
colorMode(HSB);
strokeWeight(thickness);
frameRate(60);
//initialize particles
for(int i = 0;i<numOfParticles;i++){
xIncrement[i] = random(0,100)/speed; //the ratio of increments determines the pattern
yIncrement[i] = random(0,100)/speed; // it is the slope of the line
x[i] = random(0,width);
px[i] = x[i];
y[i] = random(0,height);
py[i] = y[i];
}
//you can either initialize all of them individually or do a random one
//x[0] = 0;
//px[0] = x[0];
//y[0] = 450;
//py[0] = y[0];
//x[1] = width;
//px[1] = x[1];
//y[1] = 450;
//py[1] = y[1];
}
void draw(){
background(0); //comment out for criss cross
for(int i = 0; i < numOfParticles; i++){
particle(i);
}
}
void particle(int particleNum){
currentColor = color(minColor + (x[particleNum]/rateOfColor)%maxColor,255,255,alpha);
stroke(currentColor);
fill(currentColor);
ellipse(x[particleNum],y[particleNum],radius,radius);
line(px[particleNum],py[particleNum],x[particleNum],y[particleNum]);
px[particleNum] = x[particleNum];
py[particleNum] = y[particleNum];
y[particleNum]+= yIncrement[particleNum];
x[particleNum]+= xIncrement[particleNum];
if(x[particleNum] > width + 1 || x[particleNum] < 0){
x[particleNum] -= 2*xIncrement[particleNum];
xIncrement[particleNum]*=-1;
}
if( y[particleNum] > height + 1 || y[particleNum] < 0){
y[particleNum] -= 2*yIncrement[particleNum];
yIncrement[particleNum]*=-1;
}
//if(Arrays.binarySearch(x,x[particleNum]) >= 0 && Arrays.binarySearch(y,y[particleNum]) >= 0){
// xIncrement[particleNum]*=-1;
// yIncrement[particleNum]*=-1;
// print("*\n");
// stop();
//}
print("x[0] = " + x[0] + "\n");
print("x[1] = " + x[1] + "\n");
print("y[0] = " + y[0] + "\n");
print("y[1] = " + y[1] + "\n");
}
Stack Overflow isn't really designed for general "how do I do this" type questions. It's for specific "I tried X, expected Y, but got Z instead" type questions. But I'll try to help in a general sense:
You need to break your problem down into smaller pieces and then take those pieces on one at a time. Don't worry about the whole particle system. Make it work for a single particle. Do some research on collision detection.
Then if you get stuck, you can post a more specific question along with a MCVE. Good luck.

How to fit small cubes into a given volume and represent it graphically on a web page?

My query is to show programmatically, the fitting of many given non regular (but rectangular) cubes (i.e. boxes) of individually different sizes, inside a larger volume cube, such as a storage unit.
The mathematics part is understood. Like in Linear programming / linear algebra, we can add fit volume of all smaller cubes to find out the best fit for the volume of the larger cube.
The actual requirement is to show or allow this fitting graphically on a web-page, preferably in 3d. If possible, to allow user to interact with the fitting, i.e. shuffling the placement of the cubes, etc.
Also, since I am a Java developer by profession, Java or related languages / frameworks would be my choice. However, I can use any other technology / framework / language if the end results are met.
NB: Weight is also a concern (parameter). There is a maximum weight which can be stacked in any given storage unit.
Also, since storage units can be accessed without permission (by thieves), cost of the cubes stacked in one unit is also limited. The user may desire to fit cubes of higher cost in one unit which has higher security and vice versa.
Example: allow fitting many rectangular boxes containing household electronics in a given room. The boxes maybe of TVs, refrigerators, washing machines, dishwashers, playstations, xbox 360s, etc. The different dimensions of these boxes, is to give you an idea of what to expect while fitting to the limited volume.
If there is any FOSS library / project (or even non FOSS library or project) for the same, a pointer towards it would be welcome.
Disclaimer: Okay, I know it does not 100% answer your question and also the code it veeery old (as can be concluded from the old-fashioned CVS comments) and today I would not write it that way anymore. It does still run on Java 8, though, I tested it. But in addition to solving the little informatics challenge problem of water flowing through a 3D matrix of cuboids from top to bottom depending how "leaky" the matrix (symbolising some kind of Swiss cheese) is, it also uses some very simple 3D visualisation via Java 3D. Thus, you need to install Java 3D and put the corresponding libraries onto your classpath.
The 3D output looks something like this:
package vhs.bwinfo.cheese;
// $Id: Cuboid.java,v 1.1.2.1 2006/01/10 19:48:41 Robin Exp $
import javax.media.j3d.Appearance;
import javax.media.j3d.QuadArray;
import javax.media.j3d.Shape3D;
import javax.vecmath.Point3f;
import javax.vecmath.TexCoord2f;
import javax.vecmath.Vector3f;
public class Cuboid extends Shape3D {
private static final float POS = +0.5f;
private static final float NEG = -0.5f;
private static final Point3f[] POINTS = new Point3f[] {
new Point3f(NEG, NEG, NEG),
new Point3f(POS, NEG, NEG),
new Point3f(POS, NEG, POS),
new Point3f(NEG, NEG, POS),
new Point3f(NEG, POS, NEG),
new Point3f(POS, POS, NEG),
new Point3f(POS, POS, POS),
new Point3f(NEG, POS, POS)
};
private static final TexCoord2f[] TEX_COORDS = new TexCoord2f[] {
new TexCoord2f(0, 1),
new TexCoord2f(1, 1),
new TexCoord2f(1, 0),
new TexCoord2f(0, 0)
};
private static final int VERTEX_FORMAT =
QuadArray.COORDINATES |
QuadArray.NORMALS |
QuadArray.TEXTURE_COORDINATE_2;
public Cuboid(float scaleX, float scaleY, float scaleZ) {
Point3f[] points = new Point3f[8];
for (int i = 0; i < 8; i++)
points[i] = new Point3f(
POINTS[i].x * scaleX,
POINTS[i].y * scaleY,
POINTS[i].z * scaleZ
);
Point3f[] vertices = {
points[3], points[2], points[1], points[0], // bottom
points[4], points[5], points[6], points[7], // top
points[7], points[3], points[0], points[4], // left
points[6], points[5], points[1], points[2], // right
points[7], points[6], points[2], points[3], // front
points[5], points[4], points[0], points[1] // back
};
QuadArray geometry = new QuadArray(24, VERTEX_FORMAT);
geometry.setCoordinates(0, vertices);
for (int i = 0; i < 24; i++)
geometry.setTextureCoordinate(0, i, TEX_COORDS[i % 4]);
Vector3f normal = new Vector3f();
Vector3f v1 = new Vector3f();
Vector3f v2 = new Vector3f();
Point3f[] pts = new Point3f[4];
for (int i = 0; i < 4; i++)
pts[i] = new Point3f();
for (int face = 0; face < 6; face++) {
geometry.getCoordinates(face * 4, pts);
v1.sub(pts[0], pts[2]);
v2.sub(pts[1], pts[3]);
normal.cross(v1, v2);
normal.normalize();
for (int i = 0; i < 4; i++)
geometry.setNormal((face * 4 + i), normal);
}
setGeometry(geometry);
setAppearance(new Appearance());
}
public Cuboid(float scaleFactor) {
this(scaleFactor, scaleFactor, scaleFactor);
}
}
package vhs.bwinfo.cheese;
// $Id: LeakyCheese.java,v 1.2.2.2 2006/01/10 15:37:14 Robin Exp $
import com.sun.j3d.utils.applet.JMainFrame;
import javax.swing.*;
import java.util.Random;
import static java.lang.System.out;
public class LeakyCheese {
private int width = 20, height = 20, depth = 20;
private int numClasses = 100, samplesPerClass = 100;
private double pMin = 0, pMax = 1;
private double pDiff = pMax - pMin;
private double classSize = pDiff / numClasses;
private int[] stats;
enum CubeState {CHEESE, AIR, WATER}
final private CubeState[][][] cheese;
private static final Random RND = new Random();
public LeakyCheese(
int width, int height, int depth,
int numClasses, int samplesPerClass,
double pMin, double pMax
) {
this.width = width;
this.height = height;
this.depth = depth;
this.numClasses = numClasses;
this.samplesPerClass = samplesPerClass;
this.pMin = pMin;
this.pMax = pMax;
pDiff = pMax - pMin;
classSize = pDiff / numClasses;
cheese = new CubeState[width][height][depth];
}
public LeakyCheese(
int width, int height, int depth,
int numClasses, int samplesPerClass
) {
this(width, height, depth, numClasses, samplesPerClass, 0, 1);
}
public LeakyCheese() {
cheese = new CubeState[width][height][depth];
}
private boolean pourWater(int x, int y, int z) {
if (x < 0 || x >= width || y < 0 || y >= height || z < 0 || z >= depth)
return false;
if (cheese[x][y][z] != CubeState.AIR)
return false;
cheese[x][y][z] = CubeState.WATER;
boolean retVal = (y == 0);
retVal = pourWater(x + 1, y, z) || retVal;
retVal = pourWater(x - 1, y, z) || retVal;
retVal = pourWater(x, y + 1, z) || retVal;
retVal = pourWater(x, y - 1, z) || retVal;
retVal = pourWater(x, y, z + 1) || retVal;
retVal = pourWater(x, y, z - 1) || retVal;
return retVal;
}
private boolean isLeaky(double p) {
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
for (int z = 0; z < depth; z++)
cheese[x][y][z] = (RND.nextDouble() < p)
? CubeState.CHEESE
: CubeState.AIR;
boolean retVal = false;
for (int x = 0; x < width; x++)
for (int z = 0; z < depth; z++)
retVal = pourWater(x, height - 1, z) || retVal;
return retVal;
}
private void generateStats() {
if (stats != null)
return;
stats = new int[numClasses];
for (int i = 0; i < numClasses; i++) {
for (int j = 0; j < samplesPerClass; j++) {
double p = pMin + classSize * (RND.nextDouble() + i);
if (isLeaky(p))
stats[i]++;
}
}
}
public void printStats() {
generateStats();
out.println(
"p (cheese) | p (leaky)\n" +
"------------------+-----------"
);
for (int i = 0; i < numClasses; i++) {
out.println(
String.format(
"%1.5f..%1.5f | %1.5f",
pMin + classSize * i,
pMin + classSize * (i + 1),
(double) stats[i] / samplesPerClass
)
);
}
}
public static void main(String[] args) {
//new LeakyCheese().printStats();
//new LeakyCheese(40, 40, 40, 50, 100, 0.66, .71).printStats();
LeakyCheese cheeseBlock = new LeakyCheese(5, 20, 5, 20, 100);
//LeakyCheese cheeseBlock = new LeakyCheese(20, 20, 20, 20, 100);
while (!cheeseBlock.isLeaky(0.65))
;
out.println("*** required solution found - now rendering... ***");
JMainFrame f = new JMainFrame(new LeakyCheeseGUI(cheeseBlock.cheese), 512, 512);
f.setLocationRelativeTo(null);
f.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
}
package vhs.bwinfo.cheese;
// $Id: LeakyCheeseGUI.java,v 1.1.2.1 2006/01/10 15:25:18 Robin Exp $
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.SimpleUniverse;
import vhs.bwinfo.cheese.LeakyCheese.CubeState;
import javax.media.j3d.*;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;
import java.applet.Applet;
import java.awt.*;
import java.util.Random;
public class LeakyCheeseGUI extends Applet {
static final long serialVersionUID = -8194627556699837928L;
public BranchGroup createSceneGraph(CubeState[][][] cheese) {
// Create the root of the branch graph
BranchGroup bgRoot = new BranchGroup();
// Composite of two rotations around different axes. The resulting
// TransformGroup is the parent of all our cheese cubes, because their
// orientation is identical. They only differ in their translation
// values and colours.
Transform3D tRotate = new Transform3D();
Transform3D tRotateTemp = new Transform3D();
tRotate.rotX(Math.PI / 8.0d);
tRotateTemp.rotY(Math.PI / -4.0d);
tRotate.mul(tRotateTemp);
TransformGroup tgRotate = new TransformGroup(tRotate);
bgRoot.addChild(tgRotate);
// Bounding sphere for rendering
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
// Set background colour
// Note: Using Canvas3D.setBackground does not work, because it is an
// AWT method. Java 3D, though, gets its background colour from its
// background node (black, if not present).
Background background = new Background(0.5f, 0.5f, 0.5f);
background.setApplicationBounds(bounds);
bgRoot.addChild(background);
TransparencyAttributes transpAttr;
// Little cheese cubes
Appearance cheeseAppearance = new Appearance();
transpAttr =
new TransparencyAttributes(TransparencyAttributes.NICEST, 0.98f);
cheeseAppearance.setTransparencyAttributes(transpAttr);
cheeseAppearance.setColoringAttributes(
new ColoringAttributes(1, 1, 0, ColoringAttributes.NICEST));
PolygonAttributes pa = new PolygonAttributes();
//pa.setPolygonMode(PolygonAttributes.POLYGON_LINE);
pa.setCullFace(PolygonAttributes.CULL_NONE);
cheeseAppearance.setPolygonAttributes(pa);
// Little water cubes
Appearance waterAppearance = new Appearance();
transpAttr =
new TransparencyAttributes(TransparencyAttributes.NICEST, 0.85f);
waterAppearance.setTransparencyAttributes(transpAttr);
waterAppearance.setColoringAttributes(
new ColoringAttributes(0, 0, 1, ColoringAttributes.NICEST));
pa = new PolygonAttributes();
pa.setCullFace(PolygonAttributes.CULL_NONE);
waterAppearance.setPolygonAttributes(pa);
// Little air cubes
Appearance airAppearance = new Appearance();
transpAttr =
new TransparencyAttributes(TransparencyAttributes.NICEST, 0.95f);
airAppearance.setTransparencyAttributes(transpAttr);
airAppearance.setColoringAttributes(
new ColoringAttributes(1, 1, 1, ColoringAttributes.NICEST));
pa = new PolygonAttributes();
//pa.setPolygonMode(PolygonAttributes.POLYGON_LINE);
pa.setCullFace(PolygonAttributes.CULL_NONE);
airAppearance.setPolygonAttributes(pa);
// Water-coloured (i.e. blue) wire frame around cheese block, if leaky
Appearance waterWireFrameAppearance = new Appearance();
waterWireFrameAppearance.setColoringAttributes(
new ColoringAttributes(0, 0, 1, ColoringAttributes.NICEST));
pa = new PolygonAttributes();
pa.setPolygonMode(PolygonAttributes.POLYGON_LINE);
pa.setCullFace(PolygonAttributes.CULL_NONE);
waterWireFrameAppearance.setPolygonAttributes(pa);
// Cheese-coloured (i.e. yellow) wire frame around cheese block, if not leaky
Appearance cheeseWireFrameAppearance = new Appearance();
cheeseWireFrameAppearance.setColoringAttributes(
new ColoringAttributes(1, 1, 0, ColoringAttributes.NICEST));
pa = new PolygonAttributes();
pa.setPolygonMode(PolygonAttributes.POLYGON_LINE);
pa.setCullFace(PolygonAttributes.CULL_NONE);
cheeseWireFrameAppearance.setPolygonAttributes(pa);
// Absolute offsets for the cheese block to fit into the viewing canvas
final float xOffs = -0.8f;
final float yOffs = -0.55f;
final float zOffs = 0;
// Create all those little cubes ;-)
final int xSize = cheese.length;
final int ySize = cheese[0].length;
final int zSize = cheese[0][0].length;
final int maxSize = Math.max(xSize, Math.max(ySize, zSize));
final float xCenterOffs = 0.5f * (maxSize - xSize) / maxSize;
final float yCenterOffs = 0.5f * (maxSize - ySize) / maxSize;
final float zCenterOffs = -0.5f * (maxSize - zSize) / maxSize;
boolean isLeaky = false;
for (int x = 0; x < xSize; x++)
for (int y = 0; y < ySize; y++)
for (int z = 0; z < zSize; z++) {
Transform3D tTranslate = new Transform3D();
tTranslate.setTranslation(
new Vector3f(
xOffs + xCenterOffs + 1.0f * x / maxSize,
yOffs + yCenterOffs + 1.0f * y / maxSize,
zOffs + zCenterOffs - 1.0f * z / maxSize
)
);
TransformGroup tgTranslate = new TransformGroup(tTranslate);
tgRotate.addChild(tgTranslate);
Cuboid cube = new Cuboid(1.0f / maxSize);
switch (cheese[x][y][z]) {
case CHEESE:
cube.setAppearance(cheeseAppearance);
break;
case WATER:
cube.setAppearance(waterAppearance);
if (y == 0)
isLeaky = true;
break;
case AIR:
cube.setAppearance(airAppearance);
}
tgTranslate.addChild(cube);
}
// If cheese block is leaky, visualise it by drawing a water-coloured
// (i.e. blue) wire frame around it. Otherwise use a cheese-coloured
// (i.e. yellow) one.
Transform3D tTranslate = new Transform3D();
tTranslate.setTranslation(
new Vector3f(
xOffs + xCenterOffs + 0.5f * (xSize - 1) / maxSize,
yOffs + yCenterOffs + 0.5f * (ySize - 1) / maxSize,
zOffs + zCenterOffs - 0.5f * (zSize - 1) / maxSize
)
);
TransformGroup tgTranslate = new TransformGroup(tTranslate);
tgRotate.addChild(tgTranslate);
Cuboid cuboid = new Cuboid(
1.0f * xSize / maxSize,
1.0f * ySize / maxSize,
1.0f * zSize / maxSize
);
cuboid.setAppearance(isLeaky ? waterWireFrameAppearance : cheeseWireFrameAppearance);
tgTranslate.addChild(cuboid);
// Let Java 3D perform optimizations on this scene graph.
bgRoot.compile();
return bgRoot;
}
public LeakyCheeseGUI(CubeState[][][] cheese) {
// Create a simple scene and attach it to the virtual universe
GraphicsConfiguration graphCfg = SimpleUniverse.getPreferredConfiguration();
Canvas3D canvas = new Canvas3D(graphCfg);
setLayout(new BorderLayout());
add(canvas, "Center");
SimpleUniverse universe = new SimpleUniverse(canvas);
// This will move the ViewPlatform back a bit so the objects
// in the scene can be viewed.
universe.getViewingPlatform().setNominalViewingTransform();
universe.addBranchGraph(createSceneGraph(cheese));
}
public static void main(String[] args) {
final Random RND = new Random(System.currentTimeMillis());
CubeState[][][] testCheese = new CubeState[5][8][11];
for (int x = 0; x < 5; x++)
for (int y = 0; y < 8; y++)
for (int z = 0; z < 11; z++)
testCheese[x][y][z] = (RND.nextFloat() < 0.7f)
? CubeState.CHEESE
: (RND.nextBoolean() ? CubeState.WATER : CubeState.AIR);
// Applet can also run as a stand-alone application
new MainFrame(new LeakyCheeseGUI(testCheese), 512, 512);
}
}
You will probably want to use Javascript, and specifically WebGL. Javascript is the de facto language for interactive web pages, and WebGL is a Javascript API for rendering 2D and 3D scenes on an HTML5 canvas element. A solution using WebGL should be compatible with all major browsers. Programming even simple scenes in WebGL can be pretty involved though, so I'd recommend using a framework such as three.js to simplify things.
Here is an example of interactive, draggable cubes using three.js. Some of the key lines of code from that example are:
// create the cube
var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
// set coordinates, rotation, and scale of the cubes
object.position.x = ...
object.position.y = ...
object.position.z = ...
object.rotation.x = ...
object.rotation.y = ...
object.rotation.z = ...
object.scale.x = ...
object.scale.y = ...
object.scale.z = ...
// lighting stuff
object.castShadow = true;
object.receiveShadow = true;
// add to scene and list of objects
scene.add( object );
objects.push( object );
Again, the full, working example is found at this link (click view source on that page to view the code on github).

Reading through an array 2d from center to corners

So for this java project I´m working on I need a loop that reads trough an 2d array from center first then 4 adjecent values then the corners of that and keep doing that till it reaches and completes the most outer layer. I need it to work on all odd sizes of square 2d arrays. I made this image to clarify my goal: http://gyazo.com/80ed4502cb16795d37b75a14ee57f565 . I personally was not able to achieve this. Thank you for your time! any piece of pseudo code or java code is welcome!
You could logically redefine the grid so that the center is 0,0.
Then, sort each grid coordinate according to distance from the center.
This assumes that the grid is an odd width.
For example:
class Point
{
int x;
int y;
}
Point gridCenter;
Comparator<Point> comparator = new Comparator<Point>()
{
#Override
public int compare(Point arg0, Point arg1)
{
int x = arg0.x - gridCenter.x;
int y = arg0.y - gridCenter.y;
int distance0 = x*x + y*y;
x = arg1.x - gridCenter.x;
y = arg1.y - gridCenter.y;
int distance1 = x*x + y*y;
return distance0 - distance1;
}
};
void test()
{
int width = 11;
int height = 13;
gridCenter = new Point();
gridCenter.x = width/2;
gridCenter.y = height/2;
List<Point> points = new ArrayList<>();
for(int x=0;x<width;x++)
{
for(int y=0;y<height;y++)
{
Point p = new Point();
p.x = x;
p.y = y;
points.add(p);
}
}
Collections.sort(points, comparator);
for(Point p : points)
{
System.out.println(p.x + "," + p.y);
}
}
You could bias center slightly if you want to guarantee that it chooses left,top before right,bottom in the sort.

My method scale isn't working, what may be the issue?

I have been trying to scale a Shape in java, but I'm having some problems. When i try it the Shape simple dissapears... This method receives 2 points, toScale is the point that i want the shape to extend to, and p1 is the point that I clicked in the rectangle that is around the shape to select (there's a rectangle(boundingBox) surrounding the shape wheter is a polygone or a rectangle or just polylines)
Here's the scale method code:
public void scale(Point toScale, Point p1) {
Graphics g = parent.getGraphics();
int distanceToClicked = 0;
int distanceToBoundingBox = 0;
int scaleFactor = 0;
Vector<Point> pointsAux = new Vector<Point>();
Iterator<Point> it = points.iterator();
while (it.hasNext()){
Point p = it.next();
distanceToClicked = (int) Math.sqrt(Math.pow(getCentroid().getX()-p1.getX(), 2)+Math.pow(getCentroid().getY()-p1.getY(),2));
distanceToBoundingBox = (int) Math.sqrt(Math.pow(getCentroid().getX()-toScale.getX(),2)+Math.pow(getCentroid().getY()-toScale.getY(),2));
scaleFactor = distanceToClicked/distanceToBoundingBox;
p = new Point((int)p.getX()*scaleFactor,(int) p.getY()*scaleFactor);
pointsAux.add(p);
}
points.clear();
points.addAll(pointsAux);
}
public Point getCentroid(){
int sumx = 0;
int sumy = 0;
for(int i = 0; i<points.size();i++){
sumx+=points.get(i).getX();
sumy+=points.get(i).getY();
}
Point centroid = new Point(sumx/points.size(), sumy/points.size());
return centroid;
}
Any help would be appreciated
Thanks in advance, and eventually I'm sorry for the misunderstanding code
Something like that would do the trick:
public Collection<Point> scaleShape(float scale, Collection<Point> shape) {
Point centroid = getCentroid();
Collection<Point> scaledShape = new ArrayList<>(shape.size());
for (Point point : shape) {
Point diff = new Point(point.x() - centroid.x(), point.y() - centroid.y());
Point scaledPoint = new Point(
(int) (centroid.x() + scale * diff.x()),
(int) (centroid.y() + scale * diff.y()));
scaledShape.add(scaledPoint);
}
return scaledShape;
}
Basically, every points make a linear function with the centroid. Centroid's relative x = 0, while the current computed point is at relative x = 1. You want to find the point if it were at relative x = scale.

Categories

Resources