use of org.concord.energy3d.undo.AddArrayCommand in project energy3d by concord-consortium.
the class Foundation method addCircularHeliostatArrays.
public int addCircularHeliostatArrays(final HeliostatCircularFieldLayout layout) {
EnergyPanel.getInstance().updateRadiationHeatMap();
final Class<?>[] clazz = new Class[] { Mirror.class };
final AddArrayCommand command = new AddArrayCommand(removeChildrenOfClass(clazz), this, clazz);
final double a = 0.5 * Math.min(getAbsPoint(0).distance(getAbsPoint(2)), getAbsPoint(0).distance(getAbsPoint(1)));
final Vector3 center = getAbsCenter();
final double w = (layout.getApertureWidth() + layout.getAzimuthalSpacing()) / Scene.getInstance().getAnnotationScale();
final double h = (layout.getApertureHeight() + layout.getRadialSpacing()) / Scene.getInstance().getAnnotationScale();
final double rows = a / h;
final int nrows = (int) (rows > 2 ? rows - 2 : rows);
final double roadHalfWidth = 0.5 * layout.getAxisRoadWidth() / Scene.getInstance().getAnnotationScale();
switch(layout.getType()) {
case EQUAL_AZIMUTHAL_SPACING:
for (int r = nrows - 1; r >= 0; r--) {
double b = a * (1.0 - r / rows);
b += b * b * layout.getRadialSpacingIncrement();
if (b > a) {
break;
}
final double roadAngle = Math.toDegrees(Math.atan(roadHalfWidth / b));
final int n = (int) (2 * Math.PI * b / w);
for (int i = 0; i < n; i++) {
final double theta = i * 2.0 * Math.PI / n;
final double az = Math.toDegrees(theta);
if (az >= layout.getStartAngle() && az < layout.getEndAngle()) {
if (!Util.isZero(roadAngle) && nearAxes(az, roadAngle)) {
continue;
}
final Vector3 p = new Vector3(center.getX() + b * Math.cos(theta), center.getY() + b * Math.sin(theta), 0);
addMirror(p, layout.getBaseHeight(), layout.getApertureWidth(), layout.getApertureHeight(), az);
}
}
}
break;
case // http://www.powerfromthesun.net/Book/chapter10/chapter10.html#10.1.3%20%20%20Field%20Layout
RADIAL_STAGGER:
final double rmin = a * (1.0 - (nrows - 5) / rows);
final int n = (int) (rmin / layout.getApertureWidth() * Scene.getInstance().getAnnotationScale());
for (int i = 0; i < n; i++) {
double theta = i * 2.0 * Math.PI / n;
double az = Math.toDegrees(theta);
if (az >= layout.getStartAngle() && az < layout.getEndAngle()) {
for (int j = 0; j < nrows; j++) {
final double r = a * (1.0 - j / rows);
final Vector3 p = new Vector3(center.getX() + r * Math.cos(theta), center.getY() + r * Math.sin(theta), 0);
addMirror(p, layout.getBaseHeight(), layout.getApertureWidth(), layout.getApertureHeight(), az);
}
}
theta = (i + 0.5) * 2.0 * Math.PI / n;
az = Math.toDegrees(theta);
if (az >= layout.getStartAngle() && az < layout.getEndAngle()) {
for (int j = 0; j < nrows; j++) {
final double r = a * (1.0 - j / rows) - 0.5 * h;
final Vector3 p = new Vector3(center.getX() + r * Math.cos(theta), center.getY() + r * Math.sin(theta), 0);
addMirror(p, layout.getBaseHeight(), layout.getApertureWidth(), layout.getApertureHeight(), az);
}
}
}
break;
}
SceneManager.getInstance().getUndoManager().addEdit(command);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
EnergyPanel.getInstance().updateProperties();
}
});
return countParts(Mirror.class);
}
use of org.concord.energy3d.undo.AddArrayCommand in project energy3d by concord-consortium.
the class Foundation method addSolarRackArrays.
public void addSolarRackArrays(final SolarPanel panel, double tiltAngle, final double baseHeight, final int panelRowsPerRack, final double rowSpacing, final int rowAxis, final double poleDistanceX, final double poleDistanceY) {
EnergyPanel.getInstance().updateRadiationHeatMap();
final Class<?>[] clazz = new Class[] { Rack.class, SolarPanel.class };
final AddArrayCommand command = new AddArrayCommand(removeChildrenOfClass(clazz), this, clazz);
final double az = Math.toRadians(getAzimuth());
if (!Util.isZero(az)) {
rotate(az, null, false);
}
if (Util.isZero(tiltAngle - 90)) {
tiltAngle = 89.999;
} else if (Util.isZero(tiltAngle + 90)) {
tiltAngle = -89.999;
}
final Vector3 p0 = getAbsPoint(0);
final double a = p0.distance(getAbsPoint(2));
final double b = p0.distance(getAbsPoint(1));
double x0 = Math.min(Math.min(p0.getX(), getAbsPoint(1).getX()), getAbsPoint(2).getX());
double y0 = Math.min(Math.min(p0.getY(), getAbsPoint(1).getY()), getAbsPoint(2).getY());
final double x1 = Math.max(Math.max(p0.getX(), getAbsPoint(1).getX()), getAbsPoint(2).getX());
final double y1 = Math.max(Math.max(p0.getY(), getAbsPoint(1).getY()), getAbsPoint(2).getY());
final double panelHeight = panel.isRotated() ? panel.getPanelWidth() : panel.getPanelHeight();
final double rackHeight = panelHeight * panelRowsPerRack;
final double halfHeight = 0.5 * rackHeight / Scene.getInstance().getAnnotationScale();
final double h = rowSpacing / Scene.getInstance().getAnnotationScale();
double rackWidth, rows;
final Vector3 center = new Vector3();
final Vector3 v1 = new Vector3();
final Vector3 v2 = new Vector3();
final List<Point2D.Double> intersections = new ArrayList<Point2D.Double>();
double[] bounds = null;
switch(rowAxis) {
case 1:
center.setX((x0 + x1) * 0.5);
rackWidth = a * Scene.getInstance().getAnnotationScale() - panelHeight;
rows = (int) Math.floor(b / h);
double margin = (b - rows * h) * 0.5;
for (int r = 0; r < rows; r++) {
if (foundationPolygon != null && foundationPolygon.isVisible()) {
if (bounds == null) {
bounds = foundationPolygon.getBounds();
}
x0 = Math.max(x0, bounds[0]);
y0 = Math.max(y0, bounds[2]);
center.setY(y0 + halfHeight + h * r);
v1.set(x0, center.getY(), 0);
v2.set(x1, center.getY(), 0);
intersections.clear();
intersections.addAll(foundationPolygon.getIntersectingPoints(v1, v2));
final int n = intersections.size();
if (n >= 2) {
for (int i = 0; i < n; i += 2) {
final Point2D.Double pd1 = intersections.get(i);
final Point2D.Double pd2 = intersections.get(i + 1);
rackWidth = pd2.distance(pd1) * Scene.getInstance().getAnnotationScale();
final Rack rack = addRack(panel, tiltAngle, baseHeight, rowAxis, poleDistanceX, poleDistanceY, new Vector3(0.5 * (pd1.getX() + pd2.getX()), 0.5 * (pd1.getY() + pd2.getY()), 0), rackWidth, rackHeight, false);
rack.draw();
}
}
} else {
center.setY(y0 + margin + h * (r + 0.5));
addRack(panel, tiltAngle, baseHeight, rowAxis, poleDistanceX, poleDistanceY, center, rackWidth, rackHeight, false).draw();
}
}
break;
case 0:
center.setY((y0 + y1) * 0.5);
rackWidth = b * Scene.getInstance().getAnnotationScale() - panelHeight;
rows = (int) Math.floor(a / h);
margin = (a - rows * h) * 0.5;
for (int r = 0; r < rows; r++) {
if (foundationPolygon != null && foundationPolygon.isVisible()) {
if (bounds == null) {
bounds = foundationPolygon.getBounds();
}
x0 = Math.max(x0, bounds[0]);
y0 = Math.max(y0, bounds[2]);
center.setX(x0 + halfHeight + h * r);
v1.set(center.getX(), y0, 0);
v2.set(center.getX(), y1, 0);
intersections.clear();
intersections.addAll(foundationPolygon.getIntersectingPoints(v1, v2));
final int n = intersections.size();
if (n >= 2) {
for (int i = 0; i < n; i += 2) {
final Point2D.Double pd1 = intersections.get(i);
final Point2D.Double pd2 = intersections.get(i + 1);
rackWidth = pd2.distance(pd1) * Scene.getInstance().getAnnotationScale();
final Rack rack = addRack(panel, tiltAngle, baseHeight, rowAxis, poleDistanceX, poleDistanceY, new Vector3(0.5 * (pd1.getX() + pd2.getX()), 0.5 * (pd1.getY() + pd2.getY()), 0), rackWidth, rackHeight, true);
rack.draw();
}
}
} else {
center.setX(x0 + margin + h * (r + 0.5));
addRack(panel, tiltAngle, baseHeight, rowAxis, poleDistanceX, poleDistanceY, center, rackWidth, rackHeight, true).draw();
}
}
break;
}
if (!Util.isZero(az)) {
rotate(-az, null, false);
}
Scene.getInstance().redrawFoundationNow(this);
SceneManager.getInstance().getUndoManager().addEdit(command);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
EnergyPanel.getInstance().updateProperties();
}
});
}
use of org.concord.energy3d.undo.AddArrayCommand in project energy3d by concord-consortium.
the class Foundation method addSpiralHeliostatArrays.
public int addSpiralHeliostatArrays(final HeliostatSpiralFieldLayout layout) {
EnergyPanel.getInstance().updateRadiationHeatMap();
final Class<?>[] clazz = new Class[] { Mirror.class };
final AddArrayCommand command = new AddArrayCommand(removeChildrenOfClass(clazz), this, clazz);
final double a = 0.5 * Math.min(getAbsPoint(0).distance(getAbsPoint(2)), getAbsPoint(0).distance(getAbsPoint(1)));
final double b = layout.getScalingFactor() * Math.max(layout.getApertureWidth(), layout.getApertureHeight()) / Scene.getInstance().getAnnotationScale();
final Vector3 center = getAbsCenter();
final double theta0 = layout.getStartTurn() * 2 * Math.PI;
final double roadHalfWidth = 0.5 * layout.getAxisRoadWidth() / Scene.getInstance().getAnnotationScale();
switch(layout.getType()) {
case FERMAT_SPIRAL:
for (int i = 1; i < 10000; i++) {
double r = b * Math.sqrt(i);
r += r * r * layout.getRadialSpacingIncrement();
if (r > a) {
break;
}
final double theta = i * GOLDEN_ANGLE;
if (theta < theta0) {
continue;
}
final double roadAngle = Math.toDegrees(Math.atan(roadHalfWidth / r));
double az = Math.toDegrees(theta);
az = az % 360;
if (az >= layout.getStartAngle() && az < layout.getEndAngle()) {
if (!Util.isZero(roadAngle) && nearAxes(az, roadAngle)) {
continue;
}
final Vector3 p = new Vector3(center.getX() + r * Math.cos(theta), center.getY() + r * Math.sin(theta), 0);
addMirror(p, layout.getBaseHeight(), layout.getApertureWidth(), layout.getApertureHeight(), az);
}
}
break;
}
SceneManager.getInstance().getUndoManager().addEdit(command);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
EnergyPanel.getInstance().updateProperties();
}
});
return countParts(Mirror.class);
}
use of org.concord.energy3d.undo.AddArrayCommand in project energy3d by concord-consortium.
the class Foundation method addRectangularHeliostatArrays.
public int addRectangularHeliostatArrays(final HeliostatRectangularFieldLayout layout) {
EnergyPanel.getInstance().updateRadiationHeatMap();
final Class<?>[] clazz = new Class[] { Mirror.class };
final AddArrayCommand command = new AddArrayCommand(removeChildrenOfClass(clazz), this, clazz);
final double az = Math.toRadians(getAzimuth());
if (!Util.isZero(az)) {
rotate(az, null, false);
}
final Vector3 p0 = getAbsPoint(0);
final double a = p0.distance(getAbsPoint(2));
final double b = p0.distance(getAbsPoint(1));
final double x0 = Math.min(Math.min(p0.getX(), getAbsPoint(1).getX()), getAbsPoint(2).getX());
final double y0 = Math.min(Math.min(p0.getY(), getAbsPoint(1).getY()), getAbsPoint(2).getY());
final double w = (layout.getApertureWidth() + layout.getColumnSpacing()) / Scene.getInstance().getAnnotationScale();
final double h = (layout.getApertureHeight() + layout.getRowSpacing()) / Scene.getInstance().getAnnotationScale();
switch(layout.getRowAxis()) {
case // north-south axis
0:
int rows = (int) Math.floor(b / w);
int cols = (int) Math.floor(a / h);
for (int c = 0; c < cols; c++) {
for (int r = 0; r < rows; r++) {
final Vector3 p = new Vector3(x0 + h * (c + 0.5), y0 + w * (r + 0.5), 0);
addMirror(p, layout.getBaseHeight(), layout.getApertureWidth(), layout.getApertureHeight(), az);
}
}
break;
case // east-west axis
1:
rows = (int) Math.floor(a / w);
cols = (int) Math.floor(b / h);
for (int c = 0; c < cols; c++) {
for (int r = 0; r < rows; r++) {
final Vector3 p = new Vector3(x0 + w * (r + 0.5), y0 + h * (c + 0.5), 0);
addMirror(p, layout.getBaseHeight(), layout.getApertureWidth(), layout.getApertureHeight(), az);
}
}
break;
}
if (!Util.isZero(az)) {
rotate(-az, null, false);
}
Scene.getInstance().redrawFoundationNow(this);
SceneManager.getInstance().getUndoManager().addEdit(command);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
EnergyPanel.getInstance().updateProperties();
}
});
return countParts(Mirror.class);
}
use of org.concord.energy3d.undo.AddArrayCommand in project energy3d by concord-consortium.
the class Foundation method addSolarPanelArrays.
public void addSolarPanelArrays(final SolarPanel solarPanel, final double rowSpacing, final double colSpacing, final int rowAxis) {
EnergyPanel.getInstance().updateRadiationHeatMap();
final Class<?>[] clazz = new Class[] { Rack.class, SolarPanel.class };
final AddArrayCommand command = new AddArrayCommand(removeChildrenOfClass(clazz), this, clazz);
final double az = Math.toRadians(getAzimuth());
if (!Util.isZero(az)) {
rotate(az, null, false);
}
final Vector3 p0 = getAbsPoint(0);
final double a = p0.distance(getAbsPoint(2));
final double b = p0.distance(getAbsPoint(1));
final double x0 = Math.min(Math.min(p0.getX(), getAbsPoint(1).getX()), getAbsPoint(2).getX());
final double y0 = Math.min(Math.min(p0.getY(), getAbsPoint(1).getY()), getAbsPoint(2).getY());
final double w = colSpacing / Scene.getInstance().getAnnotationScale();
final double h = rowSpacing / Scene.getInstance().getAnnotationScale();
Path2D.Double path = null;
if (foundationPolygon != null && foundationPolygon.isVisible()) {
path = new Path2D.Double();
final int n = foundationPolygon.points.size();
Vector3 v = foundationPolygon.getAbsPoint(0);
path.moveTo(v.getX(), v.getY());
for (int i = 1; i < n / 2; i++) {
// use only the first half of the vertices from the polygon
v = foundationPolygon.getAbsPoint(i);
path.lineTo(v.getX(), v.getY());
}
path.closePath();
}
switch(rowAxis) {
case 0:
int rows = (int) Math.floor(b / w);
int cols = (int) Math.floor(a / h);
double marginx = (a - cols * h) * 0.5;
double marginy = (b - rows * w) * 0.5;
for (int c = 0; c < cols; c++) {
for (int r = 0; r < rows; r++) {
final double x = x0 + marginx + h * (c + 0.5);
final double y = y0 + marginy + w * (r + 0.5);
if (path != null && !path.contains(x, y)) {
continue;
}
final SolarPanel sp = (SolarPanel) solarPanel.copy(false);
sp.setContainer(this);
final Vector3 v = sp.toRelative(new Vector3(x, y, 0));
sp.points.get(0).setX(v.getX());
sp.points.get(0).setY(v.getY());
sp.points.get(0).setZ(height);
Scene.getInstance().add(sp, false);
sp.complete();
sp.setRelativeAzimuth(90);
sp.draw();
}
}
break;
case 1:
rows = (int) Math.floor(a / w);
cols = (int) Math.floor(b / h);
marginx = (a - rows * w) * 0.5;
marginy = (b - cols * h) * 0.5;
for (int c = 0; c < cols; c++) {
for (int r = 0; r < rows; r++) {
final double x = x0 + marginx + w * (r + 0.5);
final double y = y0 + marginy + h * (c + 0.5);
if (path != null && !path.contains(x, y)) {
continue;
}
final SolarPanel sp = (SolarPanel) solarPanel.copy(false);
sp.setContainer(this);
final Vector3 v = sp.toRelative(new Vector3(x, y, 0));
sp.points.get(0).setX(v.getX());
sp.points.get(0).setY(v.getY());
sp.points.get(0).setZ(height);
Scene.getInstance().add(sp, false);
sp.complete();
sp.draw();
}
}
break;
}
if (!Util.isZero(az)) {
rotate(-az, null, false);
}
Scene.getInstance().redrawFoundationNow(this);
SceneManager.getInstance().getUndoManager().addEdit(command);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
EnergyPanel.getInstance().updateProperties();
}
});
}
Aggregations