package attracdemo;

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

public class AttracDemo {
   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         @Override public void run() {
            createAndShowGUI();
         }
      });
   }

   private static void createAndShowGUI() {
      JFrame f = new JFrame("AttracDemo");
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.add(new MyPanel());
      f.pack();
      f.setVisible(true);
   }
}

class MyPanel extends JPanel {
   public static Vector r0 = new Vector(0.1);
   public static Vector r1 = new Vector(0.1);
   public static Vector r2 = new Vector(0.1);
   public static Vector r01 = new Vector(0.0);
   public static Vector r02 = new Vector(0.0);
   public static Vector r12 = new Vector(0.0);
   public static Vector dr01 = new Vector(1.0);
   public static Vector dr02 = new Vector(1.0);
   public static Vector dr12 = new Vector(1.0);
   Color color0 = new Color( 255, 0, 0 );
   Color color1 = new Color( 0, 255, 0 );
   Color color2 = new Color( 0, 0, 255 );
   
   public MyPanel() {
      setBackground(Color.BLACK);
   }
   
   @Override
   public Dimension getPreferredSize() {
      return new Dimension(800,800);
   }
   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);

      //Paint specifications
      double zoom = 100.0;
      int x0 = 400;
      int y0 = 400;
      int n = 300000; //Number of pixels
      double eist;
//============================================================
//Algorithm with vectors
      for( int i = 0; i < n; ++i){
         r01 = r1.minus(r0);
         r02 = r2.minus(r0);
         r12 = r2.minus(r1);
         // Boundary value
         eist = r01.mag() + r02.mag() + r12.mag();
         //Reflection?
         if (eist > Vector.e && r01.mag() > Vector.s) dr01 = r01.reflect(dr01);
         if (eist > Vector.e && r02.mag() > Vector.s) dr02 = r02.reflect(dr02);
         if (eist > Vector.e && r12.mag() > Vector.s) dr12 = r12.reflect(dr12);
         // Superposition
         // node 0 (red)
         r0 = r0.plus(dr01);
         r0 = r0.plus(dr02);
         // node 1 (green)
         r1 = r1.minus(dr01);
         r1 = r1.plus(dr12);
         // node 2 (blue)
         r2 = r2.minus(dr02);
         r2 = r2.minus(dr12);
//============================================================
      //Draw Pixels
         g.setColor(color0);
         g.drawLine(x0 + (int)(zoom*(r0.vect[0])), y0 - (int)(zoom*(r0.vect[1])),
         x0 + (int)(zoom*(r0.vect[0])), y0 - (int)(zoom*(r0.vect[1])));
         g.setColor(color1);
         g.drawLine(x0 + (int)(zoom*(r1.vect[0])), y0 - (int)(zoom*(r1.vect[1])),
         x0 + (int)(zoom*(r1.vect[0])), y0 - (int)(zoom*(r1.vect[1])));
         g.setColor(color2);
         g.drawLine(x0 + (int)(zoom*(r2.vect[0])), y0 - (int)(zoom*(r2.vect[1])),
         x0 + (int)(zoom*(r2.vect[0])), y0 - (int)(zoom*(r2.vect[1])));
      }
   }
}


======================================================================================



package attracdemo;

public class Vector {
   public double[] vect;
   public static int dim = 4; //dim > 1
   public static int s = 1; //s > 0
   public static int e = 40; //e > 0

   //Constructor
   public Vector( double[] vect) {
      this.vect = vect;
   }

   //Returns a random vector (initial conditions)
   public Vector(double c){
      this.vect = new double[dim];
      for (int i = 0; i < dim; i++)
         this.vect[i] = c*(Math.random()-0.5);
   }

   // vector times scalar
   public Vector mult(double b){
      double[] temp = new double[dim];
      Vector a = this;
      for (int i = 0; i < dim; i++)
         temp[i] = b * a.vect[i];
      Vector c = new Vector(temp);
      return c;
   }
   
   //Sum of two vectors
   public Vector plus(Vector b){
      double[] temp = new double[dim];
      Vector a = this;
      for (int i = 0; i < dim; i++)
         temp[i] = a.vect[i] + b.vect[i];
      Vector c = new Vector(temp);
      return c;
   }

   //Difference of two vectors
   public Vector minus(Vector b){
      double[] temp = new double[dim];
      Vector a = this;
      for (int i = 0; i < dim; i++)
         temp[i] = a.vect[i] - b.vect[i];
      Vector c = new Vector(temp);
      return c;
   }

   // Dot product of two vectors
   public double dot(Vector b){
      Vector a = this;
      double c = 0.0;
      for (int i = 0; i < dim; i++)
         c = c + a.vect[i] * b.vect[i];
      return c;
   }

   //Returns the magnitude of this vector.
   public double mag() {
      return Math.sqrt(this.dot(this));
   }

   //Returns the unit vector of this vector.
   public Vector unit() {
      double[] tmp = new double[dim];
      double scalar = this.mag();
      if (scalar > 0.0) 
         scalar = 1.0 / scalar;
      for (int i = 0; i < dim; i++)
      tmp[i] = scalar * this.vect[i];
      return new Vector(tmp);
   }

   //Reflection at the boundary
   public Vector reflect(final Vector dre) {
      double r, rq, scalar, radi, x;
      rq = this.dot(this);
      if (rq < 1.0E-15) rq = 1.0E-15;
      r = Math.sqrt(rq);
      scalar = this.dot(dre);
      radi = (rq / (s*s) - 1.0)
           * (1.0 - scalar*scalar / rq);
      if (radi < 0) radi = 0;
      x = -scalar / r + Math.sqrt(radi);
      Vector dra = dre.plus(this.mult(x / r)).unit();
      return dra;
   }
}
