createRing(ring, center = null, startVertex = null, previousVertex = null) {
    if (ring.positioned) {
      return;
    }

    center = center ? center : new Vector2(0, 0);
    let orderedNeighbours = ring.getOrderedNeighbours(this.ringConnections);
    let startingAngle = startVertex ? Vector2.subtract(startVertex.position, center).angle() : 0;
    let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());
    let angle = MathHelper.centralAngle(ring.getSize());
    ring.centralAngle = angle;
    let a = startingAngle;
    let that = this;
    let startVertexId = startVertex ? startVertex.id : null;

    if (ring.members.indexOf(startVertexId) === -1) {
      if (startVertex) {
        startVertex.positioned = false;
      }

      startVertexId = ring.members[0];
    } // If the ring is bridged, then draw the vertices inside the ring
    // using a force based approach


    if (ring.isBridged) {
      this.graph.kkLayout(ring.members.slice(), center, startVertex.id, ring, this.opts.bondLength, this.opts.kkThreshold, this.opts.kkInnerThreshold, this.opts.kkMaxIteration, this.opts.kkMaxInnerIteration, this.opts.kkMaxEnergy);
      ring.positioned = true; // Update the center of the bridged ring

      this.setRingCenter(ring);
      center = ring.center; // Setting the centers for the subrings

      for (var i = 0; i < ring.rings.length; i++) {
        this.setRingCenter(ring.rings[i]);
      }
    } else {
      ring.eachMember(this.graph.vertices, function (v) {
        let vertex = that.graph.vertices[v];

        if (!vertex.positioned) {
          vertex.setPosition(center.x + Math.cos(a) * radius, center.y + Math.sin(a) * radius);
        }

        a += angle;

        if (!ring.isBridged || ring.rings.length < 3) {
          vertex.angle = a;
          vertex.positioned = true;
        }
      }, startVertexId, previousVertex ? previousVertex.id : null);
    }

    ring.positioned = true;
    ring.center = center; // Draw neighbours in decreasing order of connectivity

    for (var i = 0; i < orderedNeighbours.length; i++) {
      let neighbour = this.getRing(orderedNeighbours[i].neighbour);

      if (neighbour.positioned) {
        continue;
      }

      let vertices = RingConnection.getVertices(this.ringConnections, ring.id, neighbour.id);

      if (vertices.length === 2) {
        // This ring is a fused ring
        ring.isFused = true;
        neighbour.isFused = true;
        let vertexA = this.graph.vertices[vertices[0]];
        let vertexB = this.graph.vertices[vertices[1]]; // Get middle between vertex A and B

        let midpoint = Vector2.midpoint(vertexA.position, vertexB.position); // Get the normals to the line between A and B

        let normals = Vector2.normals(vertexA.position, vertexB.position); // Normalize the normals

        normals[0].normalize();
        normals[1].normalize(); // Set length from middle of side to center (the apothem)

        let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());
        let apothem = MathHelper.apothem(r, neighbour.getSize());
        normals[0].multiplyScalar(apothem).add(midpoint);
        normals[1].multiplyScalar(apothem).add(midpoint); // Pick the normal which results in a larger distance to the previous center
        // Also check whether it's inside another ring

        let nextCenter = normals[0];

        if (Vector2.subtract(center, normals[1]).lengthSq() > Vector2.subtract(center, normals[0]).lengthSq()) {
          nextCenter = normals[1];
        } // Get the vertex (A or B) which is in clock-wise direction of the other


        let posA = Vector2.subtract(vertexA.position, nextCenter);
        let posB = Vector2.subtract(vertexB.position, nextCenter);

        if (posA.clockwise(posB) === -1) {
          if (!neighbour.positioned) {
            this.createRing(neighbour, nextCenter, vertexA, vertexB);
          }
        } else {
          if (!neighbour.positioned) {
            this.createRing(neighbour, nextCenter, vertexB, vertexA);
          }
        }
      } else if (vertices.length === 1) {
        // This ring is a spiro
        ring.isSpiro = true;
        neighbour.isSpiro = true;
        let vertexA = this.graph.vertices[vertices[0]]; // Get the vector pointing from the shared vertex to the new centpositioner

        let nextCenter = Vector2.subtract(center, vertexA.position);
        nextCenter.invert();
        nextCenter.normalize(); // Get the distance from the vertex to the center

        let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());
        nextCenter.multiplyScalar(r);
        nextCenter.add(vertexA.position);

        if (!neighbour.positioned) {
          this.createRing(neighbour, nextCenter, vertexA);
        }
      }
    } // Next, draw atoms that are not part of a ring that are directly attached to this ring


    for (var i = 0; i < ring.members.length; i++) {
      let ringMember = this.graph.vertices[ring.members[i]];
      let ringMemberNeighbours = ringMember.neighbours; // If there are multiple, the ovlerap will be resolved in the appropriate step

      for (var j = 0; j < ringMemberNeighbours.length; j++) {
        let v = this.graph.vertices[ringMemberNeighbours[j]];

        if (v.positioned) {
          continue;
        }

        v.value.isConnectedToRing = true;
        this.createNextBond(v, ringMember, 0.0);
      }
    }
  }
Creates a new ring, that is, positiones all the vertices inside a ring.

@param {Ring} ring The ring to position.
@param {(Vector2|null)} [center=null] The center of the ring to be created.
@param {(Vertex|null)} [startVertex=null] The first vertex to be positioned inside the ring.
@param {(Vertex|null)} [previousVertex=null] The last vertex that was positioned.
@param {Boolean} [previousVertex=false] A boolean indicating whether or not this ring was force positioned already - this is needed after force layouting a ring, in order to draw rings connected to it.