返回优化的 x 坐标以标准化/最大化具有定义的 y 位置的矩形数组的区域

2024-01-03

我已经包含了一个代码片段,希望能够很好地总结内容,并以某种“填空”状态表示。

如果通过在更大的背景下看待问题有助于理解问题的根源,那么我最终要做的就是在手机上的日历上显示每日查看时间表,可能类似于手机上日历的工作方式。当事件开始在时间上重叠时(由此处的垂直 y 轴表示),我希望能够优化这些事件的宽度和位置,不重叠它们,也不隐藏超出内容所需的内容 - 但是当事件太多时许多能够指示事物是隐藏的。

我不是在寻找任何基于 CSS/HTML 的解决方案,尽管示例是在 javascript 中 - DOM 结构或多或少是一成不变的,只是在寻找一种可以完成我正在寻找的算法,如果它是在 C++ 中, TurboPascal、Assembly、Java,无论什么都并不重要。在我的示例中,预期结果越复杂,场景越复杂,结果更像是粗略估计,并且在渲染我的预期结果时,它也会在演示中出现 - 我什至没有真正的方法来在我的头脑中进行数学计算一旦事情开始变得奇怪。

目标是填写函数optimizeLeftAndRightXStartPointsForNormalizedRectangleAreaWithoutOverlapping = (rectangles,minimumArea,minimumWidth,xMin,xMax)=>{}

// Let's say I have an array like this of rectangles where they have set y coordinates
// Some constraints on how this array comes out: it will besorted by the yTop property as shown below, but with no secondary sort criteria.
// The rectangles difference between yBottom and yTop is always at least 15, in other words this array won't contain any rectangles less than 15 in height

const rectanglesYcoordinatesOnlyExample1 = [
{"rectangle_id":"b22d","yTop":0,"yBottom":60},
{"rectangle_id":"8938","yTop":60,"yBottom":120},
{"rectangle_id":"e78a","yTop":60,"yBottom":120},
{"rectangle_id":"81ed","yTop":207,"yBottom":222},
{"rectangle_id":"b446","yTop":207,"yBottom":222},
{"rectangle_id":"ebd3","yTop":207,"yBottom":222},
{"rectangle_id":"2caf","yTop":208,"yBottom":223},
{"rectangle_id":"e623","yTop":227,"yBottom":242},
{"rectangle_id":"e6a3","yTop":270,"yBottom":320},
{"rectangle_id":"e613","yTop":272,"yBottom":460},
{"rectangle_id":"c2d1","yTop":272,"yBottom":290},
{"rectangle_id":"e64d","yTop":274,"yBottom":300},
{"rectangle_id":"b653","yTop":276,"yBottom":310},
{"rectangle_id":"e323","yTop":276,"yBottom":310},
{"rectangle_id":"fca3","yTop":300,"yBottom":315}
]

// I want to get a result sort of like this, explanations provided, although I'm not sure if my internal calculations in my head are 100% on the further I go.  

// And I want to a run a function like so:
// optimizeLeftAndRightXStartPointsForNormalizedRectangleAreaWithoutOverlapping(rectanglesYcoordinatesOnlyExample1,(33.3 * 15),10,0,100);  
// I will make this call later but I need to hoist my expected results here to enable the mocking to work for now at the point of the function definiton for my example. (see below)
// like so I'd get a result something like this, but I start becoming less certain of what the correct result should be the more I go into fringe stuff.

const expectedResultMoreOrLessForExample1 = [
{"rectangle_id":"b22d","leftX":0,"rightX":100,"yTop":0,"yBottom":60},
{"rectangle_id":"8938","leftX":0,"rightX":50,"yTop":60,"yBottom":120},
{"rectangle_id":"e78a","leftX":50,"rightX":100,"yTop":60,"yBottom":120},
{"rectangle_id":"81ed","leftX":0,"rightX":33.3,"yTop":207,"yBottom":222}, // Three rectangles side by side with minimum Area ["81ed","b446","ebd3"] from this point
{"rectangle_id":"b446","leftX":33.3,"rightX":66.6,"yTop":207,"yBottom":222},
{"rectangle_id":"ebd3","isMax":true,"leftX":66.7,"rightX":100,"yTop":207,"yBottom":222},  // has isMax property because there would be an overlap if it tried the next result, and it can't take area away from the other rectangles
// This rectangle gets thrown out because it would be there are 3 other rectangles in that area each with the minimum area (33.3 * 15);
// {"rectangle_id":"2caf","yTop":208,"yBottom":223}, This one gets thrown out from the result the time being because there are too many rectangles in one area of vertical space.
{"rectangle_id":"e623","yTop":227,"yBottom":242,"leftX":0,"rightX":100},
{"rectangle_id":"e6a3","leftX":0,"rightX":25,"yTop":270,"yBottom":320},
{"rectangle_id":"e613","leftX":25,"rightX":35,"yTop":272,"yBottom":460},
{"rectangle_id":"c2d1","leftX":71.28,"rightX":100,"yTop":272,"yBottom":290},  // fill the remaining space since optimizing to max area would take 99% 
{"rectangle_id":"e64d","leftX":35,"rightX":61.28,"yTop":274,"yBottom":300},
{"rectangle_id":"b653","yTop":276,"yBottom":940,"leftX":61.28,rightX:71.28},
{"rectangle_id":"fca3","leftX":35,"rightX":61.28,"yTop":300,"yBottom":315}
]

// the function name is really long to reflect what it is what I want to do.  Don't normally make functions this intense

const optimizeLeftAndRightXStartPointsForNormalizedRectangleAreaWithoutOverlapping = (rectangles,minimumArea,minimumWidth,xMin,xMax)=>{
	// TODO : fill in the optimization function.
	// Code I'm looking for would be swapped in here if you wanted to make changes to demo it do it here
	if(rectangles === rectanglesYcoordinatesOnlyExample1 && minimumArea === (33.3 * 15) && minimumWidth === 10 && xMin === 0 && xMax === 100){  // Just handling the example
		return expectedResultMoreOrLessForExample1;
	} else {
		console.log('I only know how to handle example 1, as computed by a human, poorly.  fill in the function and replace the block with working stuff');
		return [];
	}
}


const displayResults = (completedRectangleList) => {
	const rectangleColors = ['cyan','magenta','green','yellow','orange']
	completedRectangleList.forEach((rectangle,index) =>{
	 	let newRectangle = document.createElement('div');
	 	newRectangle.style.position = 'absolute';
	 	newRectangle.style.height = rectangle.yBottom - rectangle.yTop + 'px';
	  	newRectangle.style.top = rectangle.yTop + 'px';
	  	newRectangle.style.left = parseInt(rectangle.leftX)+'%';
	  	newRectangle.style.width = rectangle.rightX - rectangle.leftX + "%";
	  	newRectangle.style.backgroundColor = rectangleColors[index % rectangleColors.length];
	  	newRectangle.innerHTML = rectangle.rectangle_id;
	  	if(rectangle.isMax){
	  		newRectangle.innerHTML += '- more hidden';
	  	}
		document.body.appendChild(newRectangle);
})
}
// I am calling this function with minimum Area of 33.3 * 15, because it represents 3 min height rectangles taking up a third of the minX,maxX values, which are 0 & 100, representing a percentage value ultimately
let resultForExample1 = optimizeLeftAndRightXStartPointsForNormalizedRectangleAreaWithoutOverlapping(rectanglesYcoordinatesOnlyExample1,(33.3 * 15),10,0,100);
displayResults(resultForExample1);

就我所尝试的而言,我开始做一些事情,然后我想到一些边缘案例,事情变得有点混乱。即使在我头脑中计算出的预期结果中,我认为我自己的人性化计算也有点偏差,所以当评估这个问题并查看我的预期结果和它的渲染时,它有点偏差。希望背后的意图和意义optimizeLeftAndRightXStartPointsForNormalizedRectangleAreaWithoutOverlapping()或多或少是清楚的。

我仍在研究可能的方法,但同时也在寻求群众的智慧,直到我想到为止。我很好奇解决方案,但我还没有找到正确的途径。


此答案中的算法尝试在固定宽度的边界框中排列矩形。该算法的输入是一个矩形数组,其topY and bottomY被指定。该算法计算leftX and rightX对于每个矩形。矩形的大小和位置都经过调整以避免重叠。例如,下图显示了算法排列的 7 个矩形。在区域 1 中,最大重叠为 2,因此矩形以半宽绘制。区域 2 没有重叠,因此矩形是全宽的。区域 3 具有重叠 3,因此矩形的宽度是边界框的三分之一。

该算法主要分为三个步骤:

  1. Fill the eventQueue based on the information in the input array. Each rectangle spawns two events: an EVENT_START with the topY, and an EVENT_STOP with the bottomY. The eventQueue is a priority queue, where the priority is based on the three values that define an event (evaluated in the order shown):
    • y: lower y价值观优先。
    • type:EVENT_STOP 的优先级高于 EVENT_START。
    • rectID: lower rectID价值观优先。
  2. Search for the end of a region while:
    • 将事件存储到regionQueue. The regionQueue是一个简单的 FIFO,它允许事件被第二次处理, 区域范围确定后。
    • 跟踪maxOverlap(受函数参数限制)。这maxOverlap决定了所有的宽度 区域内的矩形。
  3. 排干regionQueue计算每个的 X 值时 区域内的矩形。这部分算法使用了一个数组 被称为usedColumns。该数组中的每个条目都是-1(表示该色谱柱未使用)或rectID(表示 哪个矩形正在使用该列)。当EVENT_START被弹出 来自regionQueue,将一列分配给矩形。什么时候 一个EVENT_STOP是从弹出的regionQueue,该列返回到未使用 (-1) 状态。

算法的输入是矩形数组。这topY and bottomY这些矩形的值必须由调用者填充。这leftX and rightX值必须初始化为-1。如果算法完成时 X 值仍为 -1,则无法为矩形分配位置,因为overlapLimit被超过了。所有其他矩形都有完整的坐标集,并且可以绘制。

typedef struct
{
    int topY;       // input parameter, filled in by the caller
    int bottomY;    // input parameter, filled in by the caller
    int leftX;      // output parameter, must be initially -1
    int rightX;     // output parameter, must be initially -1
}
stRect;

typedef struct
{
    int y;          // this is the 'topY' or 'bottomY' of a rectangle
    int type;       // either EVENT_START or EVENT_STOP
    int rectID;     // the index into the input array for this rectangle
}
stEvent;

enum { EVENT_START, EVENT_STOP };

void arrangeRectangles(stRect *rectArray, int length, int overlapLimit, int containerWidth)
{
    stQueue *eventQueue  = queueCreate();
    stQueue *regionQueue = queueCreate();

    // fill the event queue with START and STOP events for each rectangle
    for (int i = 0; i < length; i++)
    {
        stEvent startEvent = {rectArray[i].topY, EVENT_START, i};
        queueAdd(eventQueue, &startEvent);
        stEvent stopEvent  = {rectArray[i].bottomY, EVENT_STOP, i};
        queueAdd(eventQueue, &stopEvent);
    }

    while (queueIsNotEmpty(eventQueue))
    {
        // search for the end of a region, while keeping track of the overlap in that region
        int overlap = 0;
        int maxOverlap = 0;
        stEvent event;
        while (queuePop(eventQueue, &event))   // take from the event queue
        {
            queueAdd(regionQueue, &event);     // save in the region queue
            if (event.type == EVENT_START)
                overlap++;
            else
                overlap--;
            if (overlap == 0)                  // reached the end of a region
                break;
            if (overlap > maxOverlap)
                maxOverlap = overlap;
        }

        // limit the overlap as specified by the function parameter
        if (maxOverlap > overlapLimit)
            maxOverlap = overlapLimit;

        // compute the width to be used for rectangles in this region
        int width = containerWidth / maxOverlap;

        // create and initialize an array to keep track of which columns are in use
        int usedColumns[maxOverlap];
        for (int i = 0; i < maxOverlap; i++)
            usedColumns[i] = -1;

        // process the region, computing left and right X values for each rectangle
        while (queuePop(regionQueue, &event))
        {
            if (event.type == EVENT_START)
            {
                // find an available column for this rectangle, and assign the X values
                for (int column = 0; column < maxOverlap; column++)
                    if (usedColumns[column] < 0)
                    {
                        usedColumns[column] = event.rectID;
                        rectArray[event.rectID].leftX = column * width;
                        rectArray[event.rectID].rightX = (column+1) * width;
                        break;
                    }
            }
            else
            {
                // free the column that's being used for this rectangle
                for (int i = 0; i < maxOverlap; i++)
                    if (usedColumns[i] == event.rectID)
                    {
                        usedColumns[i] = -1;
                        break;
                    }
            }
        }
    }

    queueDestroy(eventQueue);
    queueDestroy(regionQueue);
}

void example(void)
{
    stRect inputArray[] = {
        {  0,150,-1,-1},
        { 30,180,-1,-1},
        {180,360,-1,-1},
        {360,450,-1,-1},
        {420,540,-1,-1},
        {450,570,-1,-1},
        {480,540,-1,-1}
    };
    int length = sizeof(inputArray) / sizeof(inputArray[0]);
    arrangeRectangles(inputArray, length, 3, 100);
}

注意:我对这段代码的有效性不做任何声明。彻底的审查和测试留给读者作为练习。


@主席曼莫 https://stackoverflow.com/users/3934988/chairmanmow慷慨地将算法翻译为 JavaScript,以节省其他人寻找 JavaScript 解决方案的时间。这是翻译:

const topZero = 0;
const parent = i => ((i + 1) >>> 1) - 1;
const left = i => (i << 1) + 1;
const right = i => (i + 1) << 1;

class PriorityQueue {

  constructor(comparator = (a, b) => a > b) {
    this._heap = [];
    this._comparator = comparator;
  }

  size() {
    return this._heap.length;
  }

  isEmpty() {
    return this.size() == 0;
  }

  peek() {
    return this._heap[topZero];
  }

  push(...values) {
    values.forEach(value => {
      this._heap.push(value);
      this._siftUp();
    });
    return this.size();
  }

  pop() {
    const poppedValue = this.peek();
    const bottom = this.size() - 1;
    if (bottom > topZero) {
      this._swap(topZero, bottom);
    }
    this._heap.pop();
    this._siftDown();
    return poppedValue;
  }

  replace(value) {
    const replacedValue = this.peek();
    this._heap[topZero] = value;
    this._siftDown();
    return replacedValue;
  }

  _greater(i, j) {
    return this._comparator(this._heap[i], this._heap[j]);
  }

  _swap(i, j) {
    [this._heap[i], this._heap[j]] = [this._heap[j], this._heap[i]];
  }

  _siftUp() {
    let node = this.size() - 1;
    while (node > topZero && this._greater(node, parent(node))) {
      this._swap(node, parent(node));
      node = parent(node);
    }
  }

  _siftDown() {
    let node = topZero;
    while (
      (left(node) < this.size() && this._greater(left(node), node)) ||
      (right(node) < this.size() && this._greater(right(node), node))
      ) {
      let maxChild = (right(node) < this.size() && this._greater(right(node), left(node))) ? right(node) : left(node);
      this._swap(node, maxChild);
      node = maxChild;
    }
  }
}

const rectangles = [{
  rectID: "b22d",
  "yTop": 0,
  "yBottom": 60,
  "leftX": -1,
  "rightX": -1
},
  {
    rectID: "8938",
    "yTop": 60,
    "yBottom": 120,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "e78a",
    "yTop": 60,
    "yBottom": 120,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "81ed",
    "yTop": 207,
    "yBottom": 222,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "b446",
    "yTop": 207,
    "yBottom": 222,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "ebd3",
    "yTop": 207,
    "yBottom": 222,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "2caf",
    "yTop": 208,
    "yBottom": 223,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "e623",
    "yTop": 227,
    "yBottom": 242,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "e6a3",
    "yTop": 270,
    "yBottom": 320,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "e613",
    "yTop": 272,
    "yBottom": 460,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "c2d1",
    "yTop": 272,
    "yBottom": 290,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "e64d",
    "yTop": 274,
    "yBottom": 300,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "b653",
    "yTop": 276,
    "yBottom": 310,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "e323",
    "yTop": 276,
    "yBottom": 310,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "fca3",
    "yTop": 300,
    "yBottom": 315,
    "leftX": -1,
    "rightX": -1
  }
];

let eventQueue = new PriorityQueue((a, b) => {
  if (a.y !== b.y) return a.y < b.y;
  if (a.type !== b.type) return a.type > b.type;
  return a.rectID > b.rectID;
})
let regionQueue = []; // FIFO
const EVENT_START = 0;
const EVENT_STOP = 1;

const queueAdd = (queue, toAdd, type, priority) => {

  return queue.push(toAdd);
}


const queuePop = (queue) => {
  return queue.pop();
}

const queueDestroy = (queue) => {
  return queue = [];
}

const optimizeLeftAndRightXStartPointsForNormalizedRectangleAreaWithoutOverlapping = (rectArray, length, overlapLimit, containerWidth) => {
  // fill the event queue with START and STOP events for each rectangle
  for (let i = 0; i < length; i++) {
    let startEvent = {
      y: rectArray[i].yTop,
      type: EVENT_START,
      index: i
    };
    eventQueue.push(startEvent);
    let stopEvent = {
      y: rectArray[i].yBottom,
      type: EVENT_STOP,
      index: i
    };
    eventQueue.push(stopEvent);
  }
  while (eventQueue.size()) { // queueIsNotEmpty(eventQueue)
    // search for the end of a region, while keeping track of the overlap in that region
    let overlap = 0;
    let maxOverlap = 0;
    let event;
    while (event = eventQueue.pop()) { // take from the event queue
      queueAdd(regionQueue, event); // save in the region queue
      if (event.type === 0) {
        overlap++;
      } else {
        overlap--;
      }
      if (overlap === 0) { // reached the end of a region
        break;
      }
      // if we have a new maximum for the overlap, update 'maxOverlap'
      if (overlap > maxOverlap) {
        maxOverlap = overlap;
      }
    }
    // limit the overlap as specified by the function parameter
    if (maxOverlap > overlapLimit) {
      maxOverlap = overlapLimit;
    }

    // compute the width to be used for rectangles in this region
    const width = parseInt(containerWidth / maxOverlap);

    // create and initialize an array to keep track of which columns are in use
    let usedColumns = new Array(maxOverlap);
    for (let i = 0; i < maxOverlap; i++) {
      if (usedColumns[i] == event.rectID) {
        usedColumns[i] = -1;
        break;
      }
    }
    // process the region, computing left and right X values for each rectangle
    while (event = queuePop(regionQueue)) {
      if (event.type == 0) {
        // find an available column for this rectangle, and assign the X values
        for (let column = 0; column < maxOverlap; column++) {
          if (usedColumns[column] < 0) {
            usedColumns[column] = event.rectID;
            rectArray[event.index].leftX = column * width;
            rectArray[event.index].rightX = (column + 1) * width;
            break;
          }

        }
      } else {
        // free the column that's being used for this rectangle
        for (let i = 0; i < maxOverlap; i++)
          if (usedColumns[i] == event.rectID) {
            usedColumns[i] = -1;
            break;
          }
      }
    }

  }
  return rectArray;
}


const displayResults = (completedRectangleList) => {
  const rectangleColors = ['cyan', 'magenta', 'green', 'yellow', 'orange']
  completedRectangleList.forEach((rectangle, index) => {
    if (rectangle.leftX > -1 && rectangle.rightX > -1) {
      let newRectangle = document.createElement('div');
      newRectangle.style.position = 'absolute';
      newRectangle.style.height = rectangle.yBottom - rectangle.yTop + 'px';
      newRectangle.style.top = rectangle.yTop + 'px';
      newRectangle.style.left = parseInt(rectangle.leftX) + '%';
      newRectangle.style.width = rectangle.rightX - rectangle.leftX + "%";
      newRectangle.style.backgroundColor = rectangleColors[index % rectangleColors.length];
      newRectangle.innerHTML = rectangle.rectID;
      if (rectangle.isMax) {
        newRectangle.innerHTML += '- more hidden';
      }
      document.body.appendChild(newRectangle);
    }

  })
}
let results = optimizeLeftAndRightXStartPointsForNormalizedRectangleAreaWithoutOverlapping(rectangles, (rectangles.length), 3, 100);
console.log('results ' + JSON.stringify(results));
displayResults(results);

下面是java代码

public class Main {

public static void main(String[] args) {
    ArrayList<stRect> inputArray = new ArrayList<>();
    inputArray.add(new stRect( 0,150,-1,-1));
    inputArray.add(new stRect( 30,180,-1,-1));
    inputArray.add(new stRect( 180,360,-1,-1));
    inputArray.add(new stRect( 360,450,-1,-1));
    inputArray.add(new stRect( 420,540,-1,-1));
    inputArray.add(new stRect( 450,570,-1,-1));
    inputArray.add(new stRect( 480,540,-1,-1));
    arrangeRectangles(inputArray, inputArray.size(), 3, 100);

    for(int i = 0;i<inputArray.size();i++){
        System.out.println(inputArray.get(i).topY+" "+inputArray.get(i).bottomY+" "+inputArray.get(i).leftX+" "+inputArray.get(i).rightX);
    }
}

private static void arrangeRectangles(ArrayList<stRect>rectArray, int length, int overlapLimit, int containerWidth){
    int EVENT_START = 0, EVENT_STOP = 1;

    PriorityQueue<stEvent> eventQueue = new PriorityQueue<>(new MyComparator());
    Queue<stEvent> regionQueue = new LinkedList<>();

    for (int i = 0; i < length; i++) {
        stEvent startEvent = new stEvent(rectArray.get(i).topY,EVENT_START, i);
        eventQueue.add(startEvent);
        stEvent stopEvent = new stEvent(rectArray.get(i).bottomY,EVENT_STOP, i);
        eventQueue.add(stopEvent);
    }

    while (!eventQueue.isEmpty()){
        int overlap = 0;
        int maxOverlap = 0;
        stEvent event;

        while (!eventQueue.isEmpty()){ // take from the event queue
            event = eventQueue.remove();

            regionQueue.add(event);    // save in the region queue

            if (event.type == EVENT_START)
                overlap++;
            else
                overlap--;

            if (overlap == 0)          // reached the end of a region
                break;

            if (overlap > maxOverlap)
                maxOverlap = overlap;
        }

        // limit the overlap as specified by the function parameter
        if (maxOverlap > overlapLimit)
            maxOverlap = overlapLimit;

        // compute the width to be used for rectangles in this region
        int width = containerWidth / maxOverlap;

        int usedColumns[] = new int[maxOverlap];
        for (int i = 0; i < maxOverlap; i++)
            usedColumns[i] = -1;

        while (!regionQueue.isEmpty()){
            event = regionQueue.remove();

            if (event.type == EVENT_START) {
                // find an available column for this rectangle, and assign the X values
                for (int column = 0; column < maxOverlap; column++){
                    if (usedColumns[column] < 0) {
                        usedColumns[column] = event.rectID;
                        rectArray.get(event.rectID).leftX = column * width;
                        rectArray.get(event.rectID).rightX = (column+1) * width;
                        break;
                    }
                }
            }else {
                // free the column that's being used for this rectangle
                for (int i = 0; i < maxOverlap; i++){
                    if (usedColumns[i] == event.rectID)
                    {
                        usedColumns[i] = -1;
                        break;
                    }
                }
            }
        }
    }
    eventQueue.clear();
    regionQueue.clear();
    }
}

public class MyComparator implements Comparator<stEvent> {

    @Override
    public int compare(stEvent o1, stEvent o2) {
        if(o1.y<o2.y)
            return -1;
        if(o1.y>o2.y)
            return 1;

        if(o1.type == 0 && o2.type ==1)
            return 1;
        if(o1.type == 1 && o2.type ==0)
            return -1;

        if(o1.rectID<o2.rectID)
            return -1;
        if(o1.rectID>o2.rectID)
            return 1;

        return 0;
    }
}

class stEvent {
    int y;          
    int type;       
    int rectID;

    stEvent(int y, int type, int rectID) {
        this.y = y;
        this.type = type;
        this.rectID = rectID;
    }
}

class stRect {
    int topY;       // input parameter, filled in by the caller
    int bottomY;    // input parameter, filled in by the caller
    int leftX;      // output parameter, must be initially -1
    int rightX;

    stRect(int topY, int bottomY, int leftX, int rightX) {
        this.topY = topY;
        this.bottomY = bottomY;
        this.leftX = leftX;
        this.rightX = rightX;
    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

返回优化的 x 坐标以标准化/最大化具有定义的 y 位置的矩形数组的区域 的相关文章

  • 删除所有标记谷歌地图v3

    在我的第一次点击事件中 所有标记都显示在谷歌地图中 我想在第二次点击中删除它们 当我执行代码时 仅删除最后一个标记 这是我的 JavaScript 代码 var showmarkers false google maps event add
  • 是否有相当于 jquery .load() 的原生 JavaScript

    与下面的 jquery 等效的本机 javascript 是什么 anyDiv load anyPage htm 就在这里 function load target url var r new XMLHttpRequest r open G
  • 如何通过文本搜索返回 JSON 数组中项目的索引位置?

    这是我的 JSON 数组 var planets Name Mercury Temperature 427 C Position 1 Name Venus Temperature 462 C Position 2 Name Earth Te
  • JavaScript 符号并不能阻止对象中的名称冲突

    我已经开始研究 JavaScript 中的符号 并开始在我的对象中使用它们来帮助解决名称冲突 但是在使用它们时我仍然可以覆盖属性吗 我很难理解 JavaScript 中符号的意义 它们被谈论了很多 人们说它们很聪明 因为它们不会导致对象中的
  • Svelte 路线给我 404

    我在 Svelte 中为我的应用程序创建了一个简单的路由器 如果我从导航栏访问链接 它就可以工作 如果我重新加载页面 它会给我 404 为什么
  • Facebook API 注销我的应用程序,但不注销 Facebook

    如何使用 Facebook 的 api 进行注销 让我退出我的应用程序 网站 但保持登录 facebook com 的状态 这让我登录正常 window fbAsyncInit function FB init appId status t
  • 如何从字符串调用并执行运算符?

    例如 var s 3 3 s replace d g function all n1 operator n2 r new Number n1 new Number n2 return r 注意 不使用eval 变量运算符可以吗 https
  • 查找数组中的重叠数据

    我们正在编写一个 C 应用程序 它将有助于删除不必要的数据重复器 只有在以下情况下才可以移除中继器 all它接收到的数据被其他中继器接收 我们第一步需要做的事情解释如下 例如 我有 int 数组的集合 A 1 2 3 4 5 b 2 4 6
  • 埃拉托斯特尼筛法是生成 1 到 N 素数的最佳算法吗?

    我在一次采访中被问到这个问题 我使用埃拉托色尼筛子概念和数组实现了一种算法 有没有更好的方法来解决这个问题 对于不知道筛子的人 请点击以下链接 http en wikipedia org wiki Sieve of Eratosthenes
  • NodeJS 中的 uglify-js“找不到模块”

    在这里我正在创建应用程序来压缩 javascript 文件 我所做的步骤 在我的本地机器上安装了nodeJS 检查节点和 npm 正在工作 通过 npm install uglify js g 安装 uglify js 并安装 当我尝试在命
  • 如何调试requireJS模块定义的路径/文件

    我是 RequireJS 世界的新手 我越来越Load Timeout error对于我已经在主文件中定义的模块之一 我在 Chrome 的 网络 选项卡中没有看到任何请求 可能是因为 require 之前已经加载了该文件 我已经迷上了on
  • 防止Rails Turbolinks导致Google地图JS多次执行

    我目前正在开发 Rails 应用程序 但出现以下错误 您已在此页面上多次包含 Google Maps API 这可能会导致意外错误 经过一番研究后 我发现 Turbolinks 导致了这个问题 当 的时候link to单击后 Google
  • 关闭模态后清除模态字段

    我有这个模式
  • Lua 的标准(或最好支持的)大数(任意精度)库是什么?

    我正在处理大量无法四舍五入的数字 使用 Lua 的标准数学库 似乎没有方便的方法来保持精度超过某些内部限制 我还看到有几个库可以加载以处理大数字 http oss digirati com br luabignum http oss dig
  • Express.js“app.use()需要中间件功能”

    我正在学习 Express js 4 和 Node 但遇到了一个我无法弄清楚的错误 我正在尝试使用 node sass 包来编译我的 sass 代码 但我无法启动并运行它 这是我的主文件的精简版本 var express require e
  • 在React Native中在Android真实设备上运行应用程序时console.log输出在哪里

    我目前正在做一个项目 在那个项目中 我正在打印控制台日志但没有消息在任何地方打印 我在用npm 和 React native cli在真正的 Android 设备上运行 Thanks 如果您使用模拟器 可以按 Cmd M Android 或
  • 辅助功能:在密码输入中显示/隐藏密码按钮

    密码输入具有显示 隐藏按钮是很常见的 但我在网上发现很少有关于与其相关的可访问性问题的内容 我是否应该将任何类型的 ARIA 属性附加到按钮或密码输入 是一个复选框还是一个触发JS的按钮也能达到很好的效果 不知道我应该注意什么 作为一个不太
  • 意外标记:使用映射形成对象数组[重复]

    这个问题在这里已经有答案了 我想制作这个 name james age 10 name john age 12 name johnny age 56 我的下面的代码失败了 得到了预期的令牌吗 let x name james age 10
  • ES6 Bare Import:如何使用以及何时使用?

    ES6 允许我们使用新的导入语法 使用它 我们可以将模块导入到我们的代码中 或者这些模块的一部分 使用示例包括 Import the default export from a module import React from react
  • 删除已从另一个下拉菜单中选择的下拉值

    我在网上搜索了一段时间 但仍然找不到答案 我的网站上有三个下拉菜单 我使用它们来接受用户首选项 以便用户可以控制结果的输出 所以我想知道如果在其中一个下拉列表中选择了该值 是否可以从其他两个下拉列表中取出该值 例如 如果用户在第一个电影中选

随机推荐