Skip to content

Commit

Permalink
fix: rectangle subtract func (#1647)
Browse files Browse the repository at this point in the history
* fix: rectangle subtract func

* fix(render): migrate the subtract

* fix((render): type error

* feat: cr revise

---------

Co-authored-by: DR-Univer <wbfsa@qq.com>
  • Loading branch information
yuhongz and DR-Univer committed Mar 20, 2024
1 parent c39799f commit 345fddc
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 15 deletions.
80 changes: 80 additions & 0 deletions packages/core/src/shared/__test__/rectangle.spec.ts
@@ -0,0 +1,80 @@
/**
* Copyright 2023-present DreamNum Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { describe, expect, it } from 'vitest';

import { Rectangle } from '../rectangle';

describe('test "Rectangle"', () => {
it('test "subtract"', () => {
// completely covered
const rect1 = {
startRow: 1,
startColumn: 1,
endRow: 1,
endColumn: 1,
};

const rect2 = {
startRow: 1,
startColumn: 1,
endRow: 1,
endColumn: 1,
};
expect(Rectangle.subtract(rect1, rect2)).toEqual([]);

// partly covered
const rect3 = {
startRow: 1,
startColumn: 1,
endRow: 3,
endColumn: 3,
};

const rect4 = {
startRow: 1,
startColumn: 1,
endRow: 1,
endColumn: 1,
};
expect(Rectangle.subtract(rect3, rect4)).toStrictEqual([
{ startRow: 2, startColumn: 1, endRow: 3, endColumn: 3 },
{ startRow: 1, startColumn: 2, endRow: 1, endColumn: 3 },
]);

// covered at center point
const rect5 = {
startRow: 1,
startColumn: 1,
endRow: 3,
endColumn: 3,
};

const rect6 = {
startRow: 2,
startColumn: 2,
endRow: 2,
endColumn: 2,
};

expect(Rectangle.subtract(rect5, rect6)).toStrictEqual([
{ startRow: 1, startColumn: 1, endRow: 1, endColumn: 3 },
{ startRow: 3, startColumn: 1, endRow: 3, endColumn: 3 },
{ startRow: 2, startColumn: 1, endRow: 2, endColumn: 1 },
{ startRow: 2, startColumn: 3, endRow: 2, endColumn: 3 },
]);
});
});
28 changes: 15 additions & 13 deletions packages/core/src/shared/rectangle.ts
Expand Up @@ -224,30 +224,30 @@ export class Rectangle {
static subtract(range1: IRange, range2: IRange): IRange[] {
// 如果没有交集,则返回 range1
if (
range2.startRow >= range1.endRow ||
range2.endRow <= range1.startRow ||
range2.startColumn >= range1.endColumn ||
range2.endColumn <= range1.startColumn
range2.startRow > range1.endRow ||
range2.endRow < range1.startRow ||
range2.startColumn > range1.endColumn ||
range2.endColumn < range1.startColumn
) {
return [range1];
}

const ranges: IRange[] = [];

// 上部分
if (range2.startRow > range1.startRow) {
if (range2.startRow >= range1.startRow) {
ranges.push({
startRow: range1.startRow,
startColumn: range1.startColumn,
endRow: range2.startRow,
endRow: range2.startRow - 1,
endColumn: range1.endColumn,
});
}

// 下部分
if (range2.endRow < range1.endRow) {
if (range2.endRow <= range1.endRow) {
ranges.push({
startRow: range2.endRow,
startRow: range2.endRow + 1,
startColumn: range1.startColumn,
endRow: range1.endRow,
endColumn: range1.endColumn,
Expand All @@ -258,25 +258,27 @@ export class Rectangle {
const topBoundary = Math.max(range1.startRow, range2.startRow);
const bottomBoundary = Math.min(range1.endRow, range2.endRow);

if (range2.startColumn > range1.startColumn) {
if (range2.startColumn >= range1.startColumn) {
ranges.push({
startRow: topBoundary,
startColumn: range1.startColumn,
endRow: bottomBoundary,
endColumn: range2.startColumn,
endColumn: range2.startColumn - 1,
});
}

// 右部分
if (range2.endColumn < range1.endColumn) {
if (range2.endColumn <= range1.endColumn) {
ranges.push({
startRow: topBoundary,
startColumn: range2.endColumn,
startColumn: range2.endColumn + 1,
endRow: bottomBoundary,
endColumn: range1.endColumn,
});
}

return ranges;
const result = ranges.filter((range) => range.startRow <= range.endRow && range.startColumn <= range.endColumn);

return result;
}
}
77 changes: 77 additions & 0 deletions packages/engine-render/src/basics/viewport-subtract.ts
@@ -0,0 +1,77 @@
/**
* Copyright 2023-present DreamNum Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import type { IRange } from '@univerjs/core';

export function subtractViewportRange(range1: IRange, range2: IRange): IRange[] {
// If there is no intersection, return range1.

if (
range2.startRow >= range1.endRow ||
range2.endRow <= range1.startRow ||
range2.startColumn >= range1.endColumn ||
range2.endColumn <= range1.startColumn
) {
return [range1];
}

const ranges: IRange[] = [];

// top
if (range2.startRow > range1.startRow) {
ranges.push({
startRow: range1.startRow,
startColumn: range1.startColumn,
endRow: range2.startRow,
endColumn: range1.endColumn,
});
}

// bottom
if (range2.endRow < range1.endRow) {
ranges.push({
startRow: range2.endRow,
startColumn: range1.startColumn,
endRow: range1.endRow,
endColumn: range1.endColumn,
});
}

// left
const topBoundary = Math.max(range1.startRow, range2.startRow);
const bottomBoundary = Math.min(range1.endRow, range2.endRow);

if (range2.startColumn > range1.startColumn) {
ranges.push({
startRow: topBoundary,
startColumn: range1.startColumn,
endRow: bottomBoundary,
endColumn: range2.startColumn,
});
}

// right
if (range2.endColumn < range1.endColumn) {
ranges.push({
startRow: topBoundary,
startColumn: range2.endColumn,
endRow: bottomBoundary,
endColumn: range1.endColumn,
});
}

return ranges;
}
5 changes: 3 additions & 2 deletions packages/engine-render/src/viewport.ts
Expand Up @@ -15,7 +15,7 @@
*/

import type { EventState, IPosition, IRange, Nullable } from '@univerjs/core';
import { Observable, Rectangle, Tools } from '@univerjs/core';
import { Observable, Tools } from '@univerjs/core';

import type { BaseObject } from './base-object';
import { RENDER_CLASS_TYPE } from './basics/const';
Expand All @@ -28,6 +28,7 @@ import { Vector2 } from './basics/vector2';
import type { UniverRenderingContext } from './context';
import type { BaseScrollBar } from './shape/base-scroll-bar';
import type { ThinScene } from './thin-scene';
import { subtractViewportRange } from './basics/viewport-subtract';

interface IViewPosition {
top?: number;
Expand Down Expand Up @@ -1089,7 +1090,7 @@ export class Viewport {
endColumn: subBound.right,
};

const ranges = Rectangle.subtract(range1, range2);
const ranges = subtractViewportRange(range1, range2);

return ranges.map((range) => {
const { startRow, endRow, startColumn, endColumn } = range;
Expand Down

0 comments on commit 345fddc

Please sign in to comment.