Мне не хватает какой-то функциональности сбора для конкретной проблемы.
Я хотел бы начать с нескольких сведений о предыстории проблемы - возможно, есть более элегантный способ ее решения, который не заканчивается конкретной проблемой, с которой я застрял:
Я моделирую объемную сетку из тетраэдрических ячеек (2D-аналогом будет треугольная сетка). Два тетраэдра считаются смежными, если они имеют одну треугольную грань (которая занимает три вершины). Мое приложение должно иметь возможность перемещаться от ячейки к ячейке через их общее лицо.
Чтобы удовлетворить некоторые другие требования, мне пришлось разделить грани на две так называемые полу-грани, которые имеют одинаковые вершины, но принадлежат разным ячейкам и имеют противоположную ориентацию.
Приложение должно иметь возможность совершать такие звонки (где Face
моделирует половину лица):
Cell getAdjacentCell(Cell cell, int faceIndex) {
Face face = cell.getFace(faceIndex);
Face partnerFace = face.getPartner();
if (partnerFace == null) return null; // no adjacent cell present
Cell adjacentCell = partnerFace.getCell();
return adjacentCell;
}
Реализация getPartner()
-метода является рассматриваемым методом. Мой подход заключается в следующем:
Face
-объекты могут создавать некий неизменный Signature
-объект, содержащий только конфигурацию вершины, ориентацию (по часовой стрелке (по часовой стрелке) или против часовой стрелки (по часовой стрелке)) и обратную ссылку на исходную Face-объект. Face.Signature-объекты считаются равными (@Override equals()
), если они занимают одни и те же три вершины - независимо от их ориентации и связанной с ними ячейки.
Я создал два набора в Mesh
-объектах, чтобы они содержали все полупериоды, сгруппированные по их ориентации:
Set<Face.Signature> faceSignatureCcw = new HashSet<Face.Signature>();
Set<Face.Signature> faceSignatureCw = new HashSet<Face.Signature>();
Теперь я могу определить, существует ли партнер ...
class Face {
public Face getPartner() {
if (this.getSignature().isCcw()) {
boolean partnerExists = this.getMesh().faceSignatureCw.contains(this);
} else {
boolean partnerExists = this.getMesh().faceSignatureCcw.contains(this);
}
}
}
... но Set
не позволяет получить конкретный объект, который он содержит! Это просто подтверждает, что он содержит объект, который соответствует через .equals()
.
(конец фоновой информации)
Мне нужна Collection
-концепция, которая обеспечивает следующие функциональные возможности:
- добавить
Face
-объект в коллекцию (дубликаты запрещены приложением и поэтому не могут возникать)
- получить партнера из коллекции для данного
Face
-объекта, который .equals()
, но имеет противоположную ориентацию
Возможное (но способ замедлить) решение:
class PartnerCollection {
List<Face.Signature> faceSignatureCcw = new ArrayList<Face.Signature>();
List<Face.Signature> faceSignatureCw = new ArrayList<Face.Signature>();
void add(Face.Signature faceSignature) {
(faceSignature.isCcw() ? faceSignatureCw : faceSignatureCcw).add(faceSignature);
}
Face.Signature getPartner(Face.Signature faceSignature) {
List<Face.Signature> partnerList = faceSignature.isCcw() ? faceSignatureCw : faceSignatureCcw;
for (Face.Signature partnerSignature : partnerList) {
if (faceSignature.equals(partnerSignature)) return partnerSignature;
}
return null;
}
}
Для завершения. Конечное приложение должно обрабатывать сотни тысяч Face
-объектов в режиме реального времени. Так что производительность это проблема.
Заранее спасибо всем, кто хотя бы пытался следовать за мной до этого момента :)
Я надеюсь, что есть кто-то, у кого есть правильная идея, чтобы решить эту проблему.