Create SwitchLatchingSymbol.java

This commit is contained in:
Bane Stojkovic
2022-10-30 13:33:30 +01:00
parent 36abdc1381
commit c843f54248
@@ -0,0 +1,341 @@
/*
*
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
*
* This file is part of DIYLC.
*
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
package org.diylc.components.electromechanical;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import org.diylc.common.ObjectCache;
import org.diylc.common.Orientation;
import org.diylc.components.AbstractComponent;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.ISwitch;
import org.diylc.core.Project;
import org.diylc.core.VisibilityPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.annotations.KeywordPolicy;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
import org.diylc.utils.Constants;
@ComponentDescriptor(name = "Switch (Latching)", author = "Branislav Stojkovic",
category = "Schematic Symbols", instanceNamePrefix = "SW",
description = "Schematic symbol of various types of latching switches",
zOrder = IDIYComponent.COMPONENT, keywordPolicy = KeywordPolicy.SHOW_TAG_AND_VALUE,
keywordTag = "Schematic")
public class SwitchLatchingSymbol
extends AbstractComponent<SwitchLatchingSymbol.SwitchConfiguration> implements ISwitch {
private static final long serialVersionUID = 1L;
public static Color COLOR = Color.black;
public static Size SIZE = new Size(0.15d, SizeUnit.in);
public static Size THROW_SPACING = new Size(0.1d, SizeUnit.in);
public static Size SPACING = new Size(0.3d, SizeUnit.in);
public static Size TERMINAL_SIZE = new Size(0.05d, SizeUnit.in);
public static int ARC_ANGLE = 24;
private Orientation orientation = Orientation.DEFAULT;
private SwitchConfiguration configuration = SwitchConfiguration._2x2;
private PoleCount poleCount = PoleCount.ONE;
private Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0)};
public SwitchLatchingSymbol() {
super();
updateControlPoints();
}
@Override
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode,
Project project, IDrawingObserver drawingObserver) {
double terminalSize = getClosestOdd(TERMINAL_SIZE);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((float) (terminalSize / 4)));
for (int i = 0; i < controlPoints.length; i++) {
Ellipse2D.Double terminal = new Ellipse2D.Double(controlPoints[i].getX() - terminalSize / 2,
controlPoints[i].getY() - terminalSize / 2, terminalSize, terminalSize);
g2d.setColor(Constants.TRANSPARENT_COLOR);
g2d.fill(terminal);
g2d.setColor(
componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING
? SELECTION_COLOR
: COLOR);
g2d.draw(terminal);
}
double theta = orientation.toRadians();
g2d.setColor(
componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING
? SELECTION_COLOR
: COLOR);
// draw latch
int throwCount = configuration.getThrowCount();
for (int j = 0; j < poleCount.getCount(); j++) {
double offset = terminalSize * 3 / 5;
Point2D startPoint = new Point2D.Double(controlPoints[(1 + throwCount) * j].getX() + Math.cos(theta) * offset,
controlPoints[(1 + throwCount) * j].getY() + Math.sin(theta) * offset);
double offsetX;
double offsetY;
if ("SHORT".equalsIgnoreCase(configuration.getInBetween())) {
offsetX = terminalSize * 6 / 5;
offsetY = 0;
} else {
offsetX = terminalSize * 2 / 3;
offsetY = terminalSize / 2;
}
Point2D endPoint = new Point2D.Double(
controlPoints[(1 + throwCount) * j + 1].getX() + Math.cos(theta + Math.PI) * offsetX
+ Math.cos(theta + Math.PI * 3 / 2) * offsetY,
controlPoints[(1 + throwCount) * j + 1].getY() + Math.sin(theta + Math.PI) * offsetX
+ Math.sin(theta + Math.PI * 3 / 2) * offsetY);
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((float) (terminalSize / 4)));
Line2D latch =
new Line2D.Double(startPoint.getX(), startPoint.getY(), endPoint.getX(), endPoint.getY());
g2d.draw(latch);
if ("SHORT".equalsIgnoreCase(configuration.getInBetween())) {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke((float) (terminalSize / 2)));
double d = startPoint.distance(endPoint) + terminalSize / 3;
double latchAngle =
Math.atan2(endPoint.getY() - startPoint.getY(), endPoint.getX() - startPoint.getX());
int startAngle = (int) Math.toDegrees(-latchAngle) - ARC_ANGLE / 2;
g2d.drawArc((int) (startPoint.getX() - d), (int) (startPoint.getY() - d), (int) (d * 2),
(int) (d * 2), startAngle, ARC_ANGLE);
}
}
if (poleCount.getCount() > 1) {
g2d.setStroke(ObjectCache.getInstance().fetchStroke(1f, new float[] {4f, 6f}, 0f, BasicStroke.CAP_SQUARE));
Line2D line = new Line2D.Double(
(controlPoints[0].getX() + controlPoints[1].getX()) / 2,
(controlPoints[0].getY() + controlPoints[1].getY()) / 2,
(controlPoints[(1 + throwCount) * (poleCount.getCount() - 1)].getX() +
controlPoints[(1 + throwCount) * (poleCount.getCount() - 1) + 1].getX()) / 2,
(controlPoints[(1 + throwCount) * (poleCount.getCount() - 1)].getY() +
controlPoints[(1 + throwCount) * (poleCount.getCount() - 1) + 1].getY()) / 2);
g2d.draw(line);
}
}
@Override
public void drawIcon(Graphics2D g2d, int width, int height) {
int margin = 3 * width / 32;
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
g2d.setColor(COLOR);
int diameter = 5;
g2d.drawOval(margin, width / 2 - diameter / 2, diameter, diameter);
g2d.drawOval(width - margin - diameter, (int) (width / 2 - 1.5 * diameter), diameter, diameter);
g2d.drawOval(width - margin - diameter, (int) (width / 2 + 0.5 * diameter), diameter, diameter);
g2d.drawLine(margin + diameter, width / 2 - diameter / 2, width - margin - diameter - 1,
(int) (width / 2 - 1.5 * diameter));
}
@EditableProperty
public Orientation getOrientation() {
if (orientation == null)
orientation = Orientation.DEFAULT;
return orientation;
}
public void setOrientation(Orientation orientation) {
this.orientation = orientation;
updateControlPoints();
}
@Override
public Point2D getControlPoint(int index) {
return controlPoints[index];
}
@Override
public int getControlPointCount() {
return controlPoints.length;
}
@Override
public boolean isControlPointSticky(int index) {
return true;
}
@Override
public void setControlPoint(Point2D point, int index) {
controlPoints[index].setLocation(point);
}
@Override
public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
return VisibilityPolicy.NEVER;
}
@EditableProperty(name = "Configuration")
@Override
public SwitchConfiguration getValue() {
return configuration;
}
@Override
public void setValue(SwitchConfiguration value) {
this.configuration = value;
updateControlPoints();
}
@EditableProperty(name = "Poles")
public PoleCount getPoleCount() {
return poleCount;
}
public void setPoleCount(PoleCount poleCount) {
this.poleCount = poleCount;
updateControlPoints();
}
protected void updateControlPoints() {
Point2D firstPoint = controlPoints[0];
int throwCount = configuration.getThrowCount();
double spacing = SPACING.convertToPixels();
double throwSpacing = THROW_SPACING.convertToPixels();
controlPoints = new Point2D[(1 + throwCount) * poleCount.getCount()];
double theta = orientation.toRadians();
for (int j = 0; j < poleCount.getCount(); j++) {
Point2D commonPoint = new Point2D.Double(firstPoint.getX() + Math.cos(theta + Math.PI / 2) * j * (throwCount + 1) * throwSpacing,
firstPoint.getY() + Math.sin(theta + Math.PI / 2) * j * (throwCount + 1) * throwSpacing);
controlPoints[(1 + throwCount) * j] = commonPoint;
AffineTransform tx = null;
if (theta != 0) {
tx = AffineTransform.getRotateInstance(theta, commonPoint.getX(), commonPoint.getY());
}
for (int i = 0; i < throwCount; i++) {
double x = commonPoint.getX() + spacing;
double y = commonPoint.getY() - (throwCount - 1) * throwSpacing / 2 + throwSpacing * i;
Point2D point = new Point2D.Double(x, y);
if (tx != null) {
tx.transform(point, point);
}
controlPoints[(1 + throwCount) * j + i + 1] = point;
}
}
}
@Override
public boolean canPointMoveFreely(int pointIndex) {
return false;
}
@Override
public int getPositionCount() {
return configuration.getPositionCount();
}
@Override
public String getPositionName(int position) {
return Integer.toString(position);
}
@Override
public boolean arePointsConnected(int index1, int index2, int position) {
// TODO Auto-generated method stub
return false;
}
public static enum SwitchConfiguration {
_1x1, _2x2, _2x3xOFF, _3x3, _3x5xSHORT, _4x4, _5x5, _6x6, _7x7, _8x8, _9x9, _10x10, _11x11, _12x12;
private int throwCount;
private int positionCount;
private String inBetween;
private SwitchConfiguration() {
String[] split = this.name().replaceAll("_", "").split("x");
this.throwCount = Integer.parseInt(split[0]);
this.positionCount = Integer.parseInt(split[1]);
if (split.length > 2) {
inBetween = split[2];
}
}
public int getPositionCount() {
return positionCount;
}
public int getThrowCount() {
return throwCount;
}
public String getInBetween() {
return inBetween;
}
@Override
public String toString() {
return throwCount + " throws / " + positionCount + " positions"
+ (inBetween == null ? "" : " / " + inBetween + " even positions");
}
}
public static enum PoleCount {
ONE(1), TWO(2), THREE(3), FOUR(4), FIVE(5), SIX(6);
private int count;
private PoleCount(int count) {
this.count = count;
}
public int getCount() {
return count;
}
@Override
public String toString() {
return name().substring(0, 1) + name().substring(1).toLowerCase();
}
}
}