package net.sf.openrocket.file.rocksim.export;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.Bulkhead;
import net.sf.openrocket.rocketcomponent.CenteringRing;
import net.sf.openrocket.rocketcomponent.EngineBlock;
import net.sf.openrocket.rocketcomponent.InnerTube;
import net.sf.openrocket.rocketcomponent.MassObject;
import net.sf.openrocket.rocketcomponent.Parachute;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.Streamer;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.rocketcomponent.TubeCoupler;
import net.sf.openrocket.util.Coordinate;
/**
* This class models the XML element for a Rocksim inside tube.
*/
@XmlRootElement(name = RocksimCommonConstants.BODY_TUBE)
@XmlAccessorType(XmlAccessType.FIELD)
public class InnerBodyTubeDTO extends BodyTubeDTO implements AttachableParts {
/**
* Constructor.
*/
public InnerBodyTubeDTO() {
super.setInsideTube(true);
}
/**
* Full copy constructor.
*
* @param bt the corresponding OR inner body tube
* @param parent the attached parts (subcomponents in Rocksim speak) of the InnerTube's parent. This instance
* is a member of those attached parts, as well as all sibling components. This is passed in the
* event that the inner tube is a cluster. In that situation this instance will be removed and
* individual instances for each cluster member will be added.
*/
public InnerBodyTubeDTO(InnerTube bt, AttachableParts parent) {
super(bt);
setEngineOverhang(bt.getMotorOverhang() * RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
setID(bt.getInnerRadius() * RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS);
setOD(bt.getOuterRadius() * RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS);
setMotorDia((bt.getMotorMountDiameter() / 2) * RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS);
setMotorMount(bt.isMotorMount());
setInsideTube(true);
setRadialAngle(bt.getRadialDirection());
setRadialLoc(bt.getRadialPosition() * RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
List<RocketComponent> children = bt.getChildren();
for (int i = 0; i < children.size(); i++) {
RocketComponent rocketComponents = children.get(i);
if (rocketComponents instanceof InnerTube) {
final InnerTube innerTube = (InnerTube) rocketComponents;
//Only if the inner tube is NOT a cluster, then create the corresponding Rocksim DTO and add it
//to the list of attached parts. If it is a cluster, then it is handled specially outside of this
//loop.
if (innerTube.getClusterCount() == 1) {
attachedParts.add(new InnerBodyTubeDTO(innerTube, this));
}
} else if (rocketComponents instanceof BodyTube) {
attachedParts.add(new BodyTubeDTO((BodyTube) rocketComponents));
} else if (rocketComponents instanceof Transition) {
attachedParts.add(new TransitionDTO((Transition) rocketComponents));
} else if (rocketComponents instanceof EngineBlock) {
attachedParts.add(new EngineBlockDTO((EngineBlock) rocketComponents));
} else if (rocketComponents instanceof TubeCoupler) {
attachedParts.add(new TubeCouplerDTO((TubeCoupler) rocketComponents));
} else if (rocketComponents instanceof CenteringRing) {
attachedParts.add(new CenteringRingDTO((CenteringRing) rocketComponents));
} else if (rocketComponents instanceof Bulkhead) {
attachedParts.add(new BulkheadDTO((Bulkhead) rocketComponents));
} else if (rocketComponents instanceof Streamer) {
attachedParts.add(new StreamerDTO((Streamer) rocketComponents));
} else if (rocketComponents instanceof Parachute) {
attachedParts.add(new ParachuteDTO((Parachute) rocketComponents));
} else if (rocketComponents instanceof MassObject) {
attachedParts.add(new MassObjectDTO((MassObject) rocketComponents));
}
}
//Do the cluster. For now this splits the cluster into separate tubes, which is how Rocksim represents it.
//The import (from Rocksim to OR) could be augmented to be more intelligent and try to determine if the
//co-located tubes are a cluster.
if (bt.getClusterConfiguration().getClusterCount() > 1) {
handleCluster(bt, parent);
parent.removeAttachedPart(this);
}
}
/**
* Handle the inner tube as a cluster. This amounts to splitting it up so that each motor mount in the cluster
* is created individually to support Rocksim's view of clusters.
*
* @param it the clustered tube
* @param p the collection (parent's attached parts really) to which all cluster tubes will be added
*/
private void handleCluster(InnerTube it, AttachableParts p) {
Coordinate[] coords = { Coordinate.NUL };
coords = it.shiftCoordinates(coords);
for (int x = 0; x < coords.length; x++) {
InnerTube partialClone = InnerTube.makeIndividualClusterComponent(coords[x], it.getName() + " #" + (x + 1), it);
p.addAttachedPart(new InnerBodyTubeDTO(partialClone, p));
}
}
@Override
public void addAttachedPart(BasePartDTO part) {
attachedParts.add(part);
}
@Override
public void removeAttachedPart(BasePartDTO part) {
attachedParts.remove(part);
}
}