首页 > 其他分享 >SDF矩形(附圆角)公式推导

SDF矩形(附圆角)公式推导

时间:2024-07-10 18:11:38浏览次数:18  
标签:圆角 dist point float SDF 矩形

SDF矩形(附圆角)公式推导

矩形

一般情况下,我们会使用(top_left, top_bottom), (width, height)来定义一个矩形,但是对于SDF而言,使用(centerX, centerY), (HalfSizeX, HalfSizeY)会更方便一些。

假设一个矩形,我们先定义原点在(0, 0),那图像如下:

image-20240710144719755

记住要计算的内容:点与形状最近边缘之间的距离

那么会出现两种情况,当要计算矩形内点 与 矩形最近边缘的距离时,都是一致的:

image-20240710144859200

找到最近的边缘,然后做垂线就可以找到。A,B,C点皆是如此。

但是对于形状外的点,情况就有些不同:

image-20240710145351508

对于AB点来说,情况是一致的,找到最近的边缘,然后就可以得到距离了。

但是我们发现,对于C,D点,矩形内点与矩形最近边缘的距离其实是到角点E的距离。所以当计算矩形SDF时候,要考虑这种特殊情况。在第一象限的时候,代码如下:


float sdf_rect(vec2 point, vec2 half_size) {
    
    point = abs(point);

    // 计算每个点到两个边的距离
    float x_dist = point.x - half_size.x;
    float y_dist = point.y - half_size.y;
  	// 如果一正一负,或者全是负数
  	// 则可以直接取max(x_dist, y_dist)作为对应点的SDF值
  
    // distance to corner
    float c_dist = length(point - half_size); // 求一下到corner的距离
    // 如果都为正数,说明是C、D点的情况,则要返回到corner的距离
    float res = x_dist > 0.0 && y_dist > 0.0 ?
           c_dist :
           max(x_dist, y_dist);
    return  res;
}

那对于其他象限呢,要知道,一个矩形是对称的,所以现在假设要求的其他象限的点的SDF值,可以都映射到第一象限去求:

img

所以最终的代码是这样的:

float sdf_rect(vec2 point, vec2 half_size) {
    
    point = abs(point);

    // 计算每个点到两个边的距离
    float x_dist = point.x - half_size.x;
    float y_dist = point.y - half_size.y;
  	// 如果一正一负,或者全是负数
  	// 则可以直接取max(x_dist, y_dist)作为对应点的SDF值
  
    // distance to corner
    float c_dist = length(point - half_size); // 求一下到corner的距离
    // 如果都为正数,说明是C、D点的情况,则要返回到corner的距离
    float res = x_dist > 0.0 && y_dist > 0.0 ?
           c_dist :
           max(x_dist, y_dist);
    return  res;
}
image-20240710153220534

进一步探讨

圆角矩形

现在的设备设计都开始讲究一个圆角矩形了,比如苹果的各种设备,我们也希望得到的矩形是一个圆角,该怎么做呢,读者可以在这里自行分析一下。

image-20240710153505390

答案很简单,就是将最终的SDF值减去一个r,对的,就是这么简单。

image-20240710153622294

我们知道,处在矩形边缘上的点的SDF值是0,如果把所有相同值的SDF化成一条线,则可以得到一个类似这样的等高线图。

image-20240710154226650

其实问题的关键(问题的关键就是关键的问题?

标签:圆角,dist,point,float,SDF,矩形
From: https://www.cnblogs.com/curiositywang/p/18294750

相关文章

  • echarts折线图实现矩形圈中的点可拖拽,圈外的点不可拖拽
    原生HTML+JavaScript版本<!DOCTYPEhtml><html><head><metacharset="utf-8"><title>曲线形式的统计图示例</title><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.9.0-rc.1/echarts.min.js&q......
  • 代码随想录算法训练营第56天 | 42. 接雨水 、84.柱状图中最大的矩形
    图论理论基础大家可以在看图论理论基础的时候,很多内容看不懂,例如也不知道看完之后还是不知道邻接矩阵,邻接表怎么用,别着急。理论基础大家先对各个概念有个印象就好,后面在刷题的过程中,每个知识点都会得到巩固。https://www.programmercarl.com/kamacoder/图论理论基础.html......
  • 代码随想录算法训练营第55天 | 42. 接雨水 、84.柱状图中最大的矩形
    接雨水接雨水这道题目是面试中特别高频的一道题,也是单调栈应用的题目,大家好好做做。建议是掌握双指针和单调栈,因为在面试中写出单调栈可能有点难度,但双指针思路更直接一些。在时间紧张的情况有,能写出双指针法也是不错的,然后可以和面试官在慢慢讨论如何优化。https://p......
  • 代码随想录算法训练营第五十五天 | 42.接雨水 84.柱状图中最大的矩形
    42.接雨水题目链接文章讲解视频讲解思路找到当前柱子左边第一个比它高的和右边第一个比它高的柱子进行计算,右边第一个比它搞得柱子可以循环遍历得到,左边第一个比它高的柱子就是栈中下一个元素classSolution{public:inttrap(vector<int>&height){stack......
  • 【代码随想录】【算法训练营】【第55天】 [42]接雨水 [84]柱状图中最大的矩形
    前言思路及算法思维,指路代码随想录。题目来自LeetCode。day55,又是一个周一,不能再坚持~题目详情[42]接雨水题目描述42接雨水解题思路前提:雨水形成的情况是凹的,需要前中后3个元素,计算该元素左右两侧的第一个大于该高度的高度思路:单调递增栈重点:单调栈的思......
  • iOS 实现视图指定圆角
    需求可以设置单独设置视图的某个圆角可以设置几个指定的圆角可以设置是否绘制边框、边框宽度实现原理使用贝塞尔曲线实现代码由于不是很复杂,所以就直接贴上代码importUIKit@IBDesignablepublicclassCornerView:UIView{@IBInspectablepublicvardrawBor......
  • Eplan插件 - 矩形修订云线
    前言在CAD中,矩形云线一直是设计师们用于标注修订区域或突出重要部分的得力工具。然而,在Eplan中,没有直接绘制矩形云线的功能。为了填补这一空白,开发了专门用于Eplan的矩形修订云线插件。这款插件保留了Eplan绘制的习惯,可以简洁快速的框选出需要修订或者重点关注的区域,使整个......
  • 【数学】100332. 包含所有 1 的最小矩形面积 II
    本文涉及知识点数学LeetCode100332.包含所有1的最小矩形面积II给你一个二维二进制数组grid。你需要找到3个不重叠、面积非零、边在水平方向和竖直方向上的矩形,并且满足grid中所有的1都在这些矩形的内部。返回这些矩形面积之和的最小可能值。注意,这些......
  • Leetcode84 柱状图中最大的矩形
    题目描述给定n个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为1。求在该柱状图中,能够勾勒出来的矩形的最大面积解题思路思路一:暴力寻找,从每个位置出发,向左右两边扩散查找,若发现柱形比当前位置高,则宽度加一,组成长方形,代码实现如下,但是提交之后......
  • qt 简单实验 一个可以向右侧拖拽缩放的矩形
    1.概要目的是设置一个可以拖拽缩放的矩形,这里仅用右侧的一个边模拟这个过程。就是为了抓住核心,这个便解决了,其他的边也是一样的。而这个更能体现原理。2.代码2.1 resizablerectangle.h#ifndefRESIZABLERECTANGLE_H#defineRESIZABLERECTANGLE_H#include<QWidget>#in......