import java.awt.Component;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.util.Random;

import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.vecmath.Point2f;
import javax.vecmath.Point3f;

import org.cellmicrocosmos.cm2.membranepackingalgorithm.*;

 * This is a very simple membrane algorithm that i wrote to show a good example
 * how a membrane algorithm works. It simply places new lipids at a rondom
 * position untill the desired number of lipids has been reached or it is
 * getting aborted. It provides a small GUI so that you can see how to use this
 * feature and it also supports microdomains
 * @author Tim Dingersen 
 This email address is being protected from spambots. You need JavaScript enabled to view it.
public class MyMembraneAlgorithm extends MembranePackingAlgorithm {

	// the desired number of lipids
	int desiredNumberOfLipids;

	// indicates if lipids should be rotated
	boolean rotateLipids;

	// a flag that can be toggled to abort the algorithm
	boolean stop = false;

	 * This method gets invoked before the fillWithLipids() process is started
	 * This is the point where you should present your GUI, like i'm doing here
	public boolean buildAndShowGui() {

		 * Testing if there are any lipid templates available for the default
		 * area or at least in any microdomain.

		boolean makesSense = this.MembraneHasAnyExtracellularLipids()
				|| this.MembraneHasAnyIntracellularLipids();
		for (int i = 0; i < this.getMicroDomainCount(); i++) {
			if ((this.getMicroDomainAt(i).hasAnyExtracellularLipids() || this
					.getMicroDomainAt(i).hasAnyIntracellularLipids()) == false)
				makesSense = false;
		if (!makesSense) {

					"No lipids that could be added available!", "No lipids",

			return false;

		// building up the options panel for the GUI
		JPanel controlPanel = new JPanel();
		JLabel textLabel = new JLabel("Desired number of lipids: ");
		JTextField textField = new JTextField();
		JCheckBox checkBox = new JCheckBox("Rotate lipids");

		textField.setPreferredSize(new Dimension(100, 30));


		 * showing the GUI to the user. The returnvalue indicates if the user
		 * confirmed or cancelled the dialog so far
		boolean returnValue = MembranePackingAlgorithmGUI.popUpGUI(controlPanel,
				"Options", "Set up some options here");

		// returning false if all should be cancelled
		if (returnValue == false)
			return false;

		 * trying to retrieve the number of desired lipids from the textfield.
		 * in case of an error the algorithm gets cancelled with a message
		try {
			this.desiredNumberOfLipids = Integer.parseInt(textField.getText());
			if (this.desiredNumberOfLipids < 1
					|| this.desiredNumberOfLipids > 1000)
				throw new Exception();
		} catch (Exception e) {
					"You need to enter a number between 1 and 1000\n"
							+ "into the textfield!", "Invalid Value",

			return false;

		this.rotateLipids = checkBox.isSelected();

		 * the user settings are ok plus the user must have confirmed if the
		 * thread reaches this code, so true gets returned in order to proceed
		return true;


	 * This method gets called when the algorithm gets started. Remember: The
	 * algorithm finishes when the thread leaves this method
	public void fillWithLipids() throws Exception {

		// the current count of lipids that have been added on this run.
		int currentCount = 0;

		// the value indicates which membraneside should be handled
		int mSide = MembranePackingAlgorithm.INTRA;

		 * starting a loop that runs until the terminal condition is reached or
		 * the stop flag has been set on true
		while (stop == false && currentCount < this.desiredNumberOfLipids) {

			// toggling membranesides to handle at each loop
			if (mSide == MembranePackingAlgorithm.INTRA)
				mSide = MembranePackingAlgorithm.EXTRA;
				mSide = MembranePackingAlgorithm.INTRA;

			// creating a random position on the x/z plane
			Point2f randomPosition = this.createRandomXZPosition(new Rectangle(
					0, 0, this.getMembraneSize().width,

			// initializing the new lipid for this run
			Lipid newLipid;

			 * determining the domainID for the microdomain at the random point.
			 * If no microdomains are available or if the point hits the default
			 * area, the value 0 gets returned
			int domainID = this.getMicroDomainAtPoint(randomPosition);

			 * creating the new lipid by using the convenient methods for this
			 * if the random point should hit a microdomain, then the methods of
			 * the specified microdomains are used in order to get the proper
			 * lipids
			if (domainID > 0) {
				// the lowest domainID is 1, so we have to use domainID-1 as the
				// index
				MicroDomain domain = this.getMicroDomainAt(domainID - 1);
				newLipid = mSide == EXTRA ? domain
						.createNextExtracellularLipid() : domain
			} else {
				newLipid = mSide == EXTRA ? this.createNextExtracellularLipid()
						: this.createNextIntracellularLipid();

			 * if the lipid should be null at this point, then the user dind't
			 * add any lipid templates to the membrane side of the domain (or
			 * default area) we are trying to create it for.
			if (newLipid == null)

			 * Assigning the new position to the lipid while maintaining its
			 * y-translation that we don't want to change in this algorithm
			newLipid.setPosition(new Point3f(randomPosition.x, newLipid
					.getYTranslation(), randomPosition.y));

			// randomly rotating the lipid if this option has been selected
			if (this.rotateLipids)
				newLipid.rotY(new Random().nextInt(359)
						+ new Random().nextFloat());

			 * The most interesting part: Testing for intersections. First for
			 * intersections with the borders, then for intersections with any
			 * other molecules. If an intersection occured then we could
			 * initiate corrections, but instead we simply retry from the top
			if (this.intersectsBorders(newLipid) || this.intersects(newLipid))

			 * If the lipid doesn't intersect at it's current alignment, we can
			 * add itonto its specified membrane side.
			if (mSide == EXTRA)

			// one more lipid added here :)


	public String getFullInformation() {

		// this string is getting displayed in the textarea were the algorithms
		// are selected
		return "This algorithm simply places all lipids\n"
				+ "at random position";

	public String getName() {

		// the chosen name for this algorithm. It has to return a unique name in
		// order to get accepted
		return "My Algorithm";

	public Component getRuntimeControlPanel() {

		// we don't provide any runtime controls for this simple algorithm
		return null;

	public String getShortInformation() {

		// you can leave out some information if you want
		return null;

	public String getStringRepresentationOfSetupParameters() {

		// returning a String that describes the users setup
		return "Desired Lipids: " + this.desiredNumberOfLipids + "\n"
				+ "Rotate Lipids: " + this.rotateLipids;

	public boolean overrideExistingLipids() {

		// existing lipids may remain in this case
		return false;

	public void stopAlgorithm() {
		// setting the stop flag on true, forcing the algorithm to stop at the
		// next loop
		this.stop = true;

	public boolean supportsMicrodomains() {
		// this algorithm provides a full microdomain support
		return true;