Не обязательно лучший способ, но если вам просто нужно что-то сделать, вы можете немного изменить свой код круга. Добавьте параметр функции float arc_length
в подпись функции. Замените 2.0f * 3.1415926f
на arc_length
. Если вам нужно запустить дугу при заданном смещении, вы можете добавить еще один параметр с именем float arc_start
. Затем добавьте arc_start
в theta
на каждой итерации вашего цикла for
.
Редактирование на основе комментариев Saman:
То, что вы на самом деле хотите, это не дуга, а более общее представление кривой. Дуга представляет собой вид кривой, но это особый вид - т. Е. один с постоянным радиусом. Похоже, вы хотите нарисовать произвольные кривые, потенциально с разными радиусами. Если это так, то моя рекомендация - кривые Безье. Вот довольно солидное введение:
http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/
Обратите внимание на часть позже в руководстве по их рисованию, где автор говорит: «Самый простой способ - использовать небольшие приращения t для вычисления последовательных точек». Это в значительной степени то, что вам нужно сделать, чтобы нарисовать кривую Безье в OpenGL. Выберите значение t
и увеличьте его в цикле for, как и с theta
в исходном коде круга. Для каждой итерации нарисуйте точку.
Кажется, что и Car
, и Computer
имеют метод getColor()
. Поэтому имеет смысл перенести это в интерфейс:
interface Colored {
Color getColor();
}
и заставить Car
и Computer
реализовать Colored
. Тогда вы можете написать свой единственный метод как
private <T extends Colored> List<T> removeSameColor(List<T> list) {
Set<String> colorSet = new HashSet<>();
Iterator<T> iterator = list.iterator();
while (iterator.hasNext()) {
if(!colorSet .isEmpty() && colorSet .contains(iterator.next().getColor())) {
iterator.remove();
}
else{
colorSet.add(iterator.next().getColor());
}
}
return list;
}
Если классы Car
и Computer
еще не реализуют общий интерфейс, и вам нужно сделать это без изменения классов, вы можете передать дополнительный параметр, функцию для извлечения String
из перечислите элементы:
private <T> List<T> removeSameColor(List<T> list, Function<? super T, String> fn) {
Set<String> colorSet = new HashSet<>();
Iterator<T> iterator = list.iterator();
while (iterator.hasNext()) {
if(!colorSet .isEmpty() && colorSet .contains(fn.apply(iterator.next()))) {
iterator.remove();
}
else{
colorSet.add(fn.apply(iterator.next()));
}
}
return list;
}
и вызывайте как:
removeSameColor(listOfCars, Car::getColour);
removeSameColor(listOfComputers, Computer::getColour);
Обратите внимание, что вы дважды вызываете iterator.next()
в теле цикла. Возможно, вы захотите сохранить его в переменной:
T value = iterator.next();
if (!colorSet.isEmpty() && colorSet.contains(fn.apply(value))) {
iterator.remove();
} else {
colorSet.add(fn.apply(value));
}
На самом деле вы можете просто сохранить String color = fn.apply(iterator.next())
, а затем использовать его вместо fn.apply(value)
.
А затем вы можете еще больше упростить цикл, используя возвращаемое значение Set.add
:
while (iterator.hasNext()) {
String color = fn.apply(iterator.next());
if (!colorSet.add(color)) {
iterator.remove();
}
}
private <T extends HasColor> List<T> removeSameColor(List<T> list) {
Set<String> colorSet = new HashSet<>();
Iterator<T> iterator = list.iterator();
while (iterator.hasNext()) {
if(!colorSet .isEmpty() && colorSet .contains(iterator.next().getColor())) {
iterator.remove();
}
else{
colorSet.add(iterator.next().getColor());
}
}
return list;
}
Затем Computer
и Car
реализуют новый интерфейс, HasColor
:
interface HasColor {
String getColor();
}
Если вы используете Java 8 или выше, есть более простая альтернатива:
Set<String> seen = ConcurrentHashMap.newKeySet();
return list.stream()
.filter(t -> seen.add(t.getColor()))
.collect(Collectors.toList());
Это приведет к дедупликации списка в соответствии с различимостью цвета каждого элемента списка.