Я не уверен, что неправильно понял ваш вопрос, однако вот мои мысли. Я предполагаю, что проекция будет такой, что гипотенуза треугольника ориентирована в том же направлении, что и самая длинная сторона прямоугольника, поскольку вы сказали, что они будут одного размера. Некоторые грубые картинки (не в масштабе):
Прямоугольник H = 4, W = 10
---------
| |
| |
---------
Треугольник Hyp = 10, S1 = 8, S2 = 6
.
. |
. |
--------
Таким образом, я предлагаю сделать отображение так, чтобы «блоки» прямоугольника приравнивались к точкам с треугольником, а каждая точка треугольника представляет собой среднее значение RGB для соответствующих блоков прямоугольника, учитывая, что блоки могут перекрываться в зависимости от масштаб оригинальных объектов.
Более конкретно, вернемся к приведенному выше примеру, сначала отношения, соотношение высоты будет фиксированным, прямоугольник высотой 4, треугольник высотой 6, поэтому для каждого пикселя по вертикали в треугольнике рассмотрим 6/4, или 1,5 в прямоугольник Теперь есть два варианта работы с «.5», вы можете рассмотреть округление в большую или меньшую сторону и использовать только целые блоки, или вы можете использовать веса для дробных сечений. Поскольку последний случай менее тривиален, мы рассмотрим его подробнее.
При перемещении по вертикали любая дробная часть будет преобразована в дробный вес пикселя этой строки, поэтому, если мы усредняем по вертикали и наши пиксели равны 128 и 137 (для простоты мы смотрим только на один компонент), тогда наше среднее значение будет
(128+ (0,5 * 137)) / 1,5 = (128 + 68,5) / 1,5 = 196,5 / 1,5 = 131
Теперь, поскольку мы смотрим дробно, нам нужно отслеживать дробную часть, которую мы не использовали, поэтому, если следующий пиксель выше 100, мы бы хотели посмотреть
((137 * 0,5) +100) / 1,5 = (68,5 + 100) / 1,5 = 168,5 / 1,5 = 112,3
Теперь мы следуем аналогичной стратегии, перемещая линию за линией вертикально вверх по треугольнику, корректируя соотношение при уменьшении ширины треугольника, поэтому для базы, где гипотенуза = прямоугольник, это будет тривиально 1. Далее, у вас может быть такое соотношение как 1.23 и может делать вычисления, как указано выше.
Наконец, грубый псевдокод:
map(rectangle, triangle) {
decimal yRatio = triangle.height / rectangle.height
decimal lastY = 0;//we need decimal indeices for fractional averages
for each line in dest height (yIndex, 0 based) {
//here you could even find the average width of the rectangle
//over the block height, but we won't bother
decimal xRatio = triangle[yIndex].width / rectangle[floor(yIndex*yRatio)].width
decimal lastX = 0; //again a decimal for fractional averages
for each pixel in dest line width (xIndex, 0 based) {
decimal pixelAverage = 0;
decimal tempYRatio = yRatio;
decimal destY = yRatio * yIndex;
//Here we calculate the source pixel block average
while(tempYRatio > 0) {
//the portion of this row of pixels we use is the minimum
//of the distance to the next integer, and what we need
decimal yFraction = minimum(tempYRatio, nextInt(destY) - destY);
decimal tempXRatio = xRatio;
decimal destX = xRatio * xIndex;
while(tempXRatio > 0) {
decimal xFraction = minimum(tempXRatio, nextInt(destX) - destX);
//now add the weighted pixel to the average
average += rectangle[floor(destY)][floor(destX)]*xFraction*yFraction;
tempXRatio -= xFraction; //reduce the block size
destX += xFraction; //and shift the source index
}
tempYRatio -= yFraction; //reduce the block size
destY += yFraction; //and shift the source index
}
destination[yIndex][xIndex] = average / (xRatio*yRatio);
}
}
}
//a helper function to find the next integer value
integer nextInt(decimal d) {
integer ret = ceiling(d);
return d == ret ? d+1 : ret;
}
Это не в моей голове, поэтому я не могу гарантировать, что это полностью правильно, но это должно быть хорошее начало, по крайней мере, выполнение усреднения в соответствии с каждым из компонентов RGB отдельных пикселей.