0

The code below is presenting a strange behavior when filling a HashMap. As can be seen there is a for that goes through a list of Faces and adds one IntegrationCellVertex into the map called values of each Face. However, in the first loop it adds this object into more than one Face of the list (see the image, highlighted in blue). Would anyone have any idea what may be going on? Unfortunately, the code is too big, so I just sharing the section where is happening the problem. Thanks a lot!

int vertexCounter = 0;
for (Face face : this.getDomainDataStructure().getFacesList()) {
    IPolygon polygon = face.faceToPolygon();
    IPoint3d centroid = polygon.getCentroid();
    IntegrationCellVertex integrationCellVertex = new IntegrationCellVertex();
    integrationCellVertex.setPoint(centroid);
    vertexCounter += 1;
    integrationCellVertex.setLabel(String.valueOf(vertexCounter));
    integrationCellVertex.setContainingFace(face);
    face.setValue(MeshfreeModel.INTEGRATION_CELL_VERTEX, integrationCellVertex);
    this.getModel().addIntegrationCellsVertex(integrationCellVertex);
}

Face class:

public class Face implements Serializable {

  private static final long serialVersionUID = 1L;

  private LinkedList<Loop> loopList = new LinkedList<Loop>();
  private HashMap<String, Object> values;
  private ArrayList<String> keys;
  private Solid solid;
  private String id;
  private LinkedList<Vertex> internalVertices = new LinkedList<Vertex>();
  private ArrayList<Face> facesVizinhas = new ArrayList<Face>();
  private ArrayList<Edge> oldEdgesVizinhas = new ArrayList<Edge>();
  private ArrayList<Edge> newEdgesVizinhas = new ArrayList<Edge>();
  private ArrayList<Edge> oldOldEdgesVizinhas = new ArrayList<Edge>();

  /**
   * The constructor of this class.
   */
  public Face() {
    this.values = new HashMap<String, Object>();
    this.keys = new ArrayList<String>();
  }

  /**
   * The constructor of this class.
   * 
   * @param id The identification of this face.
   * @param loop The loop.
   */
  public Face(String id, Loop loop) {
    this.id = id;
    this.loopList.add(loop);
    loop.setFace(this);
    this.values = new HashMap<String, Object>();
    this.keys = new ArrayList<String>();
  }

  /**
   * getPlanarSubdivision.
   * @return Returns the planarSubdivision.
   */
  public Solid getSolid() {
    return solid;
  }

  /**
   * setPlanarSubdivision.
   * @param planarSubdivision The planarSubdivision to set.
   */
  public void setSolid(Solid planarSubdivision) {
    this.solid = planarSubdivision;
  }

  /**
   * getId.
   * @return Returns the index.
   */
  public String getId() {
    return id;
  }

  /**
   * setIndex.
   * @param id The index to set.
   */
  public void setId(String id) {
    this.id = id;
  }

  /**
   * getLoopList.
   * @return Returns the loopList.
   */
  public LinkedList<Loop> getLoopList() {
    return loopList;
  }

  /**
   * setLoopList.
   * @param loopList The loopList to set.
   */
  public void setLoopList(LinkedList<Loop> loopList) {
    this.loopList = loopList;
  }

  /**
   * Returns a value of this face.
   * 
   * @param key The key of the value.
   * @return The face value.
   */
  public Object getValue(String key) {
    return this.values.get(key);
  }

  /**
   * The method set a value at a key of the face values.
   * 
   * @param key The key of the value.
   * @param value The value.
   */
  public void setValue(String key, Object value) {
    if (!this.keys.contains(key)) {
      this.keys.add(key);
    }
    this.values.put(key, value);
  }

  /**
   * Returns true if the node has the point values for the key.
   * 
   * @param key The key of the point values.
   * @return True if the node has the point values for the key.
   */
  public boolean valuesContainsKey(String key) {
    return this.values.containsKey(key);
  }

  /**
   * The method return the values.
   * 
   * @return Returns The values.
   */
  public HashMap<String, Object> getValues() {
    return this.values;
  }

  /**
   * Returns the keys of this face.
   * 
   * @return The keys of this face.
   */
  public ArrayList<String> getKeys() {
    return keys;
  }

  /**
   * setKeys.
   * @param keys The keys to set.
   */
  public void setKeys(ArrayList<String> keys) {
    this.keys = keys;
  }

  /**
   * The method sets the HashMap.
   * 
   * @param values the values to set
   */
  public void setValues(HashMap<String, Object> values) {
    this.values = values;
  }

  /**
   * Returns true if the face contains the vertex.
   * 
   * @param vertex The vertex
   * @return If the face contains the vertex
   */
  public boolean contains(Vertex vertex) {
    boolean contains = false;
    for (int i = 0; i < this.loopList.size(); i++) {
      for (int j = 0; j < this.loopList.get(i).getHalfEdgeList().size(); j++) {
        if (vertex.equals(this.loopList.get(i).getHalfEdgeList().get(j).getVertex())) {
          contains = true;
          break;
        }
      }
    }
    return contains;
  }

  /**
   * Returns the internalVertices.
   * @return the internalVertices
   */
  public LinkedList<Vertex> getInternalVertices() {
    return internalVertices;
  }

  public ArrayList<Face> getFacesVizinhas() {
    return facesVizinhas;
  }

  public void setFacesVizinhas(ArrayList<Face> facesVizinhas) {
    this.facesVizinhas = facesVizinhas;
  }

  public ArrayList<Edge> getOldEdgesVizinhas() {
    return oldEdgesVizinhas;
  }

  public void setOldEdgesVizinhas(ArrayList<Edge> oldEdgesVizinhas) {
    this.oldEdgesVizinhas = oldEdgesVizinhas;
  }

  public ArrayList<Edge> getNewEdgesVizinhas() {
    return newEdgesVizinhas;
  }

  public void setNewEdgesVizinhas(ArrayList<Edge> newEdgesVizinhas) {
    this.newEdgesVizinhas = newEdgesVizinhas;
  }

  public ArrayList<Edge> getOldOldEdgesVizinhas() {
    return oldOldEdgesVizinhas;
  }

  public void setOldOldEdgesVizinhas(ArrayList<Edge> oldOldEdgesVizinhas) {
    this.oldOldEdgesVizinhas = oldOldEdgesVizinhas;
  }

  /**
   * Returns the two edges of this face that are connected to the informed vertex.
   * @param vertex a vertex
   * @return the two edges connected to this vertex
   */
  public Edge[] getEdges(Vertex vertex) {

    // Initialization of the edges array
    Edge[] edges = new Edge[2];

    // Auxiliary variables
    Edge edge;
    HalfEdge halfEdge;
    int counter = 0;

    // Iteration over the loops of this face
    ListIterator<Loop> loops = this.getLoopList().listIterator();
    while (loops.hasNext()) {
      // This loop
      Loop loop = loops.next();
      // Iteration over the half-edges of this loop
      ListIterator<HalfEdge> halfEdges = loop.getHalfEdgeList().listIterator();
      while (halfEdges.hasNext()) {
        // This half-edge
        halfEdge = halfEdges.next();
        // The edge of this half-edge
        edge = halfEdge.getEdge();
        // Check if this edge contains the vertex
        if (edge.getRightHalfEdge().getVertex().isTheSame(vertex) || edge.getLeftHalfEdge().getVertex().isTheSame(vertex)) {
          edges[counter] = edge;
          counter++;
        }
      }
    }
    return edges;
  }

  /**
   * Returns the vertices associated to this face.
   * @return an {@link ArrayList} of instances of the class {@link Vertex}
   */
  public ArrayList<Vertex> getVertices() {

    ArrayList<Vertex> vertices = new ArrayList<>();

    ListIterator<Loop> loops = this.loopList.listIterator();
    while (loops.hasNext()) {
      Loop loop = loops.next();
      ListIterator<HalfEdge> halfEdges = loop.getHalfEdgeList().listIterator();
      while (halfEdges.hasNext()) {
        HalfEdge halfEdge = halfEdges.next();
        Vertex vertex = halfEdge.getVertex();
        vertices.add(vertex);
      }
    }

    return vertices;

  }

  /** 
   * Returns an instance of the class {@link IPolygon} constructed using the vertices of this face.
   * @return an instance of the class {@link IPolygon}
   */
  public IPolygon faceToPolygon() {
    ArrayList<IPoint3d> points = new ArrayList<>();
    ListIterator<Vertex> vertices = this.getVertices().listIterator();
    while (vertices.hasNext()) {
      Vertex vertex = vertices.next();
      points.add(vertex.getCoords());
    }
    return new IPolygon(points);
  }

}

enter image description here

4
  • Have you run your code under the debugger to see what's happening? You also need to show the code for Face. Commented Sep 28, 2020 at 23:05
  • @tgdavies thanks! Now I included the Face class. Commented Sep 29, 2020 at 0:56
  • As the answer says, remove the Face.setValues method and you'll find the problem. Commented Sep 29, 2020 at 1:41
  • @tgdavies thanks! I will do this! Commented Sep 29, 2020 at 14:06

2 Answers 2

1

Well, look at your code, which is in clear disagreement with your description.

You say:

As can be seen there is a for that goes through a list of Faces and adds one IntegrationCellVertex into the map called values of each Face.

and yet the one and only place that adds any integration cells vertex to anything is

this.getModel().addIntegrationCellsVertex(integrationCellVertex);

which is clearly adding it to this.getModel(), not face.

Your code does not include any put calls into any maps, and your picture is showing off how the same value is in the values map of multiple faces. Basically, the code you pasted is irrelevant to your question, perhaps paste more, or make a self contained test case. There may well be more problems with your code than just the disconnect between what it does and how you understand it.

If you can't make a self contained test case, face.setValue, and model.addIntegrationCellsVertex all look like required source code that needs to be added to your question in order for anybody to shed some light on your issue.

Sign up to request clarification or add additional context in comments.

1 Comment

rzwitserloot thanks! I included the Face class. This code is being developed by civil and mechanical engineers, it is part of a software of structural analysis. Regarding the line this.getModel... is ok. The problem happen in the line face.setValue(...), in this moment the IntegrationCellsVertex is add into the map.
1

Second answer now that you've updated your code:

Your code cannot result in the debug state you've shown, unless someone did something stupid, like, say:

Face a = this.getDomainDataStructure().getFacesList().get(0);
Face b = this.getDomainDataStructure().getFacesList().get(1);
a.setValues(b.getValues());

at which point a's values map and b's values map are just pointers to the same map. modify one, and the other one is also modified (if you a street address written on a piece of paper, and I have another entirely different piece of paper with the exact same address written on it, and you follow your paper and toss a brick through the window, and later I drive over there, I'll find a vandalized house. Same situation).

Take your Face class. Delete all the setters. Make all fields final.

Now, all errors? Those are the actual places that are buggy or at least sufficiently silly that other code (such as the one you pasted) will then fail. Fix THOSE. The problem is there, not in what you pasted.

1 Comment

rzwitserloot: I did what you proposed and the problem did not happen more. But, if I apply these changes, occur a lots of error in the code. So, could you explain with more detail what do you thought when you propose this? Maybe exist another solution. As I said there a group working in this software and the both class that I pasted were not developed by me. Sorry if my english is confuse! Thanks a lot for help me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.