import codedraw.CodeDraw; /** * A cosmic system that is composed of a central named body (of type 'NamedBodyForcePair') * and an arbitrary number of subsystems (of type 'CosmicSystem') in its orbit. * This class implements 'CosmicSystem'. */ public class HierarchicalSystem implements CosmicSystem, MassiveIterable { private final NamedBodyForcePair central; private CosmicSystem[] orbit; private CosmicSystem[] all; /** * Initializes this system with a name and a central body. */ public HierarchicalSystem(NamedBodyForcePair central, CosmicSystem... inOrbit) { this.central = central; this.orbit = inOrbit; this.all = new CosmicSystem[this.orbit.length + 1]; this.all[0] = central; System.arraycopy(this.orbit, 0, this.all, 1, this.orbit.length); } @Override public Vector3 getMassCenter() { double mass = this.getMass(); Vector3 massCenter = new Vector3(); for (CosmicSystem sys : all) { massCenter.add(sys.getMassCenter().times(sys.getMass() / mass)); } return massCenter; } @Override public double getMass() { double mass = 0; for (CosmicSystem sys : all) { mass += sys.getMass(); } return mass; } @Override public int numberOfBodies() { int num = 0; for (CosmicSystem sys : all) { num += sys.numberOfBodies(); } return num; } @Override public double distanceTo(CosmicSystem cs) { return this.getMassCenter().distanceTo(cs.getMassCenter()); } @Override public void addForceFrom(Body b) { for (CosmicSystem sys : all) { sys.addForceFrom(b); } } @Override public void addForceTo(CosmicSystem cs) { for (CosmicSystem sys : all) { sys.addForceTo(cs); } } @Override public BodyLinkedList getBodies() { BodyLinkedList list = new BodyLinkedList(); for (CosmicSystem sys : all) { for (Body b : sys.getBodies()) { list.addFirst(b); } } return list; } @Override public void update() { for (CosmicSystem sys : all) { sys.update(); } } @Override public void draw(CodeDraw cd) { for (CosmicSystem sys : all) { sys.draw(cd); } } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(central.getName()); sb.append(" {"); boolean first = true; for (CosmicSystem sys : orbit) { if (!first) sb.append(", "); sb.append(sys.toString()); first = false; } sb.append("}"); return sb.toString(); } /** * Puts the system 'cs' at the first place in the orbit of this system. * Precondition: cs != null */ public boolean putFirst(CosmicSystem cs) { CosmicSystem[] old = orbit; orbit = new CosmicSystem[old.length + 1]; all = new CosmicSystem[old.length + 2]; orbit[0] = cs; System.arraycopy(old, 0, orbit, 1, old.length); all[0] = central; System.arraycopy(orbit, 0, all, 1, orbit.length); return true; } @Override public MassiveIterator iterator() { return new MassiveIterator() { private int i = 0; private MassiveIterator cur = null; @Override public Massive next() { if (cur != null && cur.hasNext()) return cur.next(); for (; i < all.length; i++) { CosmicSystem sys = all[i]; if (sys instanceof NamedBodyForcePair m) { i++; return m.getBody(); } else if (sys instanceof HierarchicalSystem hs) { cur = hs.iterator(); if (cur.hasNext()) { i++; return cur.next(); } } } return null; } @Override public boolean hasNext() { if (cur != null && cur.hasNext()) return true; for (; i < all.length; i++) { CosmicSystem sys = all[i]; if (sys instanceof NamedBodyForcePair) { return true; } else if (sys instanceof HierarchicalSystem hs) { cur = hs.iterator(); if (cur.hasNext()) { i++; return true; } } } return false; } }; } }