SweepGradient扫描渐变的(float cx, float cy, int[] colors, float[] positions)参数的意义

本文深入讲解SweepGradient的使用方法,包括两个构造方法的具体参数解释及应用实例。着重介绍了如何通过指定颜色及其位置来实现非均匀变色的效果,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SweepGradient 作为画图时,用到的扫描渐变。
有两个方法。
第一个方法:
public SweepGradient(float cx, float cy, int color0, int color1)

Parameters:

  • cx 渲染中心点x 坐标
  • cy 渲染中心点y 坐标
  • color0 起始渲染颜色
  • color1 结束渲染颜色

第二个方法:
public SweepGradient(float cx, float cy, int[] colors, float[] positions)

Parameters:

  • cx 渲染中心点x 坐标
  • cy 渲染中心y 点坐标
  • colors 围绕中心渲染的颜色数组,至少要有两种颜色值
  • positions 相对位置的颜色数组,可为null,  若为null,可为null,颜色沿渐变线均匀分布

很明显,第一个方法是第二个方法的简化。
所以,我只用讲下面一个方法,就能两个方法都懂了。
查阅了API:

 /**
     * A subclass of Shader that draws a sweep gradient around a center point.
     *
     * @param cx       The x-coordinate of the center
     * @param cy       The y-coordinate of the center
     * @param colors   The colors to be distributed between around the center.
     *                 There must be at least 2 colors in the array.
     * @param positions May be NULL. The relative position of
     *                 each corresponding color in the colors array, beginning
     *                 with 0 and ending with 1.0. If the values are not
     *                 monotonic, the drawing may produce unexpected results.
     *                 If positions is NULL, then the colors are automatically
     *                 spaced evenly.
     */

前三个参数很容易理解:
- cx 渲染中心点x 坐标
- cy 渲染中心y 点坐标
- colors 围绕中心渲染的颜色数组,至少要有两种颜色值
而对于positions这个 float[]数组,写过代码的人,可能反而会很糊涂。
这个positions数组指定的是颜色在圆上的渲染分布。
- 假如要绘制完整的圆,positions指定为null就可以了,默认会按照颜色数组的顺序帮你渲染。
- 但,假如是像我要做的控件,是非均匀变色的圆,则需要我们去指定各个颜色的位置。
注意事项:渲染的方向是顺时针,位置从0开始,到1结束,而且数组要呈单调递增,不然可效果会错误。
所以举例:

image.png

颜色数组为{“绿色”,”黑色”,”红色”,”蓝色”,”黄色”},
绿色在180度,所以他对应的位置参数是0.5 (顺时针算)
以此类推,黑色225度,0.625f
红色 270度,0.75f
蓝色315度,0.875f
黄色360度,1
所以对应的positions数组就是{ 0.5f, 0.625f, 0.75f, 0.875f, 1f }

package com.hencoder.hencoderpracticedraw2.practice;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

public class Practice03SweepGradientView extends View {
    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

    public Practice03SweepGradientView(Context context) {
        super(context);
    }

    public Practice03SweepGradientView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public Practice03SweepGradientView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    {
        // 用 Paint.setShader(shader) 设置一个 SweepGradient
        // SweepGradient 的参数:圆心坐标:(300, 300);颜色:#E91E63 到 #2196F3

        Shader shader = new SweepGradient(300,300, new int[]{ Color.GREEN, Color.BLACK, Color.RED, Color.BLUE,Color.YELLOW},
                new float[]{0.5f, 0.625f, 0.75f, 0.875f, 1f}
        );
        paint.setShader(shader);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(300, 300, 200, paint);
    }
}

这样对第二个更详细的方法,就能理解了,至于第一个就是两种颜色的均匀分布,很好理解。

这个错误通常发生在尝试将一个序列(如列表)与浮点数相乘时。在您的代码中,问题可能出现在 `PSO` 类的 `update_particles` 方法中,当更新粒子速度时,可能错误地将速度(列表)与浮点数相乘。 以下是修复后的代码,重点修改了 `update_particles` 方法中的速度更新逻辑: ```python import numpy as np import matplotlib.pyplot as plt import random import heapq from typing import List, Tuple, Optional # 设置中文显示 plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"] class GridMap: """栅格地图类""" def __init__(self, width: int = 20, height: int = 20, obstacle_ratio: float = 0.2): """ 初始化栅格地图 参数: width: 地图宽度 height: 地图高度 obstacle_ratio: 障碍物比例 """ self.width = width self.height = height self.obstacle_ratio = obstacle_ratio self.grid = np.zeros((height, width), dtype=int) # 0表示可通行,1表示障碍物 self.start = (0, 0) self.goal = (width-1, height-1) # 随机生成障碍物 self.generate_random_obstacles() def generate_random_obstacles(self): """随机生成障碍物""" obstacle_count = int(self.width * self.height * self.obstacle_ratio) obstacles = random.sample(range(self.width * self.height), obstacle_count) for obs in obstacles: x = obs % self.width y = obs // self.width self.grid[y, x] = 1 def generate_custom_map1(self): """生成自定义地图1:中央有大障碍物""" self.grid = np.zeros((self.height, self.width), dtype=int) # 中央大障碍物 mid_x, mid_y = self.width // 2, self.height // 2 for i in range(mid_y - 4, mid_y + 5): for j in range(mid_x - 4, mid_x + 5): if 0 <= i < self.height and 0 <= j < self.width: self.grid[i, j] = 1 # 随机添加一些小障碍物 obstacle_count = int(self.width * self.height * (self.obstacle_ratio / 2)) obstacles = random.sample(range(self.width * self.height), obstacle_count) for obs in obstacles: x = obs % self.width y = obs // self.width if self.grid[y, x] == 0: # 避免覆盖中央障碍物 self.grid[y, x] = 1 def generate_custom_map2(self): """生成自定义地图2:对角线障碍物""" self.grid = np.zeros((self.height, self.width), dtype=int) # 对角线障碍物 for i in range(self.height): for j in range(self.width): if abs(i - j) < 2: self.grid[i, j] = 1 # 随机添加一些小障碍物 obstacle_count = int(self.width * self.height * (self.obstacle_ratio / 2)) obstacles = random.sample(range(self.width * self.height), obstacle_count) for obs in obstacles: x = obs % self.width y = obs // self.width if self.grid[y, x] == 0: # 避免覆盖对角线障碍物 self.grid[y, x] = 1 def is_valid(self, x: int, y: int) -> bool: """检查坐标是否有效(在地图内且不是障碍物)""" return 0 <= x < self.width and 0 <= y < self.height and self.grid[y, x] == 0 def get_neighbors(self, x: int, y: int) -> List[Tuple[int, int]]: """获取相邻节点""" neighbors = [] for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)]: nx, ny = x + dx, y + dy if self.is_valid(nx, ny): neighbors.append((nx, ny)) return neighbors class PSO: """粒子群优化算法""" def __init__(self, grid_map: GridMap, start: Tuple[int, int], goal: Tuple[int, int], num_particles: int = 30, max_iter: int = 100, w: float = 0.7, c1: float = 1.5, c2: float = 1.5): """ 初始化PSO算法 参数: grid_map: 栅格地图 start: 起点坐标 (x, y) goal: 终点坐标 (x, y) num_particles: 粒子数量 max_iter: 最大迭代次数 w: 惯性权重 c1: 个体学习因子 c2: 社会学习因子 """ self.grid_map = grid_map self.start = start self.goal = goal self.num_particles = num_particles self.max_iter = max_iter self.w = w self.c1 = c1 self.c2 = c2 # 粒子位置和速度 self.particles = [] self.velocities = [] self.pbest_positions = [] self.pbest_fitness = [] self.gbest_position = None self.gbest_fitness = float('inf') # 初始化粒子 self.initialize_particles() def initialize_particles(self): """初始化粒子群""" for _ in range(self.num_particles): # 生成一条随机路径 path = self.generate_random_path() self.particles.append(path) # 初始化速度为小随机值(每个节点的速度是一个二维元组) velocity = [(random.uniform(-1, 1), random.uniform(-1, 1)) for _ in range(len(path))] self.velocities.append(velocity) # 初始化个体最优 fitness = self.calculate_fitness(path) self.pbest_positions.append(path.copy()) self.pbest_fitness.append(fitness) # 更新全局最优 if fitness < self.gbest_fitness: self.gbest_fitness = fitness self.gbest_position = path.copy() def generate_random_path(self) -> List[Tuple[int, int]]: """生成随机路径""" path = [self.start] current = self.start for _ in range(18): # 20个节点的路径(包括起点和终点) neighbors = self.grid_map.get_neighbors(current[0], current[1]) if not neighbors: break next_node = random.choice(neighbors) path.append(next_node) current = next_node # 确保路径最后一个节点是终点 if path[-1] != self.goal: path.append(self.goal) return path def calculate_fitness(self, path: List[Tuple[int, int]]) -> float: """计算路径适应度(路径长度)""" fitness = 0.0 # 计算路径长度 for i in range(len(path) - 1): dx = path[i+1][0] - path[i][0] dy = path[i+1][1] - path[i][1] fitness += np.sqrt(dx*dx + dy*dy) # 如果路径经过障碍物,增加惩罚 if not self.grid_map.is_valid(path[i+1][0], path[i+1][1]): fitness += 1000 # 检查路径是否包含重复节点 unique_nodes = set(path) if len(unique_nodes) < len(path): fitness += 1000 * (len(path) - len(unique_nodes)) return fitness def update_particles(self): """更新粒子位置和速度""" for i in range(self.num_particles): particle = self.particles[i] velocity = self.velocities[i] pbest = self.pbest_positions[i] # 更新每个节点的位置 for j in range(len(particle)): if j == 0 or j == len(particle) - 1: # 起点和终点不能改变 continue # 更新速度(修正:速度是二维元组,不能直接与浮点数相乘) r1, r2 = random.random(), random.random() # 计算认知和社会分量 cognitive_x = self.c1 * r1 * (pbest[j][0] - particle[j][0]) cognitive_y = self.c1 * r1 * (pbest[j][1] - particle[j][1]) social_x = self.c2 * r2 * (self.gbest_position[j][0] - particle[j][0]) social_y = self.c2 * r2 * (self.gbest_position[j][1] - particle[j][1]) # 更新速度(分量形式) new_vx = self.w * velocity[j][0] + cognitive_x + social_x new_vy = self.w * velocity[j][1] + cognitive_y + social_y # 限制速度 max_vel = 2 new_vx = max(-max_vel, min(max_vel, new_vx)) new_vy = max(-max_vel, min(max_vel, new_vy)) # 更新位置 new_x = int(particle[j][0] + new_vx) new_y = int(particle[j][1] + new_vy) # 确保新位置有效 if not self.grid_map.is_valid(new_x, new_y): neighbors = self.grid_map.get_neighbors(particle[j][0], particle[j][1]) if neighbors: new_x, new_y = random.choice(neighbors) else: new_x, new_y = particle[j] particle[j] = (new_x, new_y) velocity[j] = (new_vx, new_vy) # 更新速度 # 计算新适应度 fitness = self.calculate_fitness(particle) # 更新个体最优 if fitness < self.pbest_fitness[i]: self.pbest_fitness[i] = fitness self.pbest_positions[i] = particle.copy() # 更新全局最优 if fitness < self.gbest_fitness: self.gbest_fitness = fitness self.gbest_position = particle.copy() def optimize(self) -> Tuple[List[Tuple[int, int]], List[float]]: """执行优化""" fitness_history = [] for iteration in range(self.max_iter): self.update_particles() fitness_history.append(self.gbest_fitness) if iteration % 10 == 0: print(f"迭代 {iteration}/{self.max_iter}, 最优适应度: {self.gbest_fitness}") return self.gbest_position, fitness_history class AStar: """A*算法""" def __init__(self, grid_map: GridMap, start: Tuple[int, int], goal: Tuple[int, int]): """ 初始化A*算法 参数: grid_map: 栅格地图 start: 起点坐标 (x, y) goal: 终点坐标 (x, y) """ self.grid_map = grid_map self.start = start self.goal = goal def heuristic(self, a: Tuple[int, int], b: Tuple[int, int]) -> float: """启发式函数(曼哈顿距离)""" return abs(a[0] - b[0]) + abs(a[1] - b[1]) def find_path(self) -> Optional[List[Tuple[int, int]]]: """寻找路径""" open_set = [] heapq.heappush(open_set, (0, self.start)) came_from = {} g_score = {self.start: 0} f_score = {self.start: self.heuristic(self.start, self.goal)} while open_set: _, current = heapq.heappop(open_set) if current == self.goal: # 重建路径 path = [current] while current in came_from: current = came_from[current] path.append(current) path.reverse() return path for neighbor in self.grid_map.get_neighbors(current[0], current[1]): # 计算从当前节点到邻居的成本 dx = neighbor[0] - current[0] dy = neighbor[1] - current[1] cost = 1.0 if dx * dy == 0 else 1.4 # 对角线移动成本更高 tentative_g_score = g_score[current] + cost if neighbor not in g_score or tentative_g_score < g_score[neighbor]: # 这是更好的路径 came_from[neighbor] = current g_score[neighbor] = tentative_g_score f_score[neighbor] = tentative_g_score + self.heuristic(neighbor, self.goal) heapq.heappush(open_set, (f_score[neighbor], neighbor)) return None # 没有找到路径 def visualize_results(grid_map: GridMap, pso_path: List[Tuple[int, int]], astar_path: List[Tuple[int, int]], title: str): """可视化结果""" plt.figure(figsize=(12, 10)) # 绘制地图 plt.imshow(grid_map.grid, cmap='gray_r', interpolation='nearest') # 绘制起点和终点 plt.plot(grid_map.start[0], grid_map.start[1], 'go', markersize=10) plt.plot(grid_map.goal[0], grid_map.goal[1], 'ro', markersize=10) # 绘制PSO路径 pso_x = [p[0] for p in pso_path] pso_y = [p[1] for p in pso_path] plt.plot(pso_x, pso_y, 'b-', linewidth=2, label='PSO路径') # 绘制A*路径 astar_x = [p[0] for p in astar_path] astar_y = [p[1] for p in astar_path] plt.plot(astar_x, astar_y, 'g-', linewidth=2, label='A*路径') plt.title(title) plt.legend() plt.grid(True) plt.tight_layout() plt.show() def main(): """主函数""" # 创建两个不同的地图 map1 = GridMap(width=20, height=20, obstacle_ratio=0.2) map1.generate_custom_map1() map1.start = (2, 2) map1.goal = (18, 18) map2 = GridMap(width=20, height=20, obstacle_ratio=0.2) map2.generate_custom_map2() map2.start = (2, 18) map2.goal = (18, 2) # 对地图1执行路径规划 print("=== 地图1路径规划 ===") # 使用PSO算法 pso1 = PSO(map1, map1.start, map1.goal, num_particles=30, max_iter=100) pso_path1, pso_fitness_history1 = pso1.optimize() # 使用A*算法 astar1 = AStar(map1, map1.start, map1.goal) astar_path1 = astar1.find_path() if astar_path1: print(f"PSO路径长度: {len(pso_path1)}") print(f"A*路径长度: {len(astar_path1)}") # 可视化结果 visualize_results(map1, pso_path1, astar_path1, "地图1路径规划结果对比") # 绘制适应度历史 plt.figure(figsize=(10, 6)) plt.plot(pso_fitness_history1) plt.title("PSO算法适应度历史(地图1)") plt.xlabel("迭代次数") plt.ylabel("适应度(路径长度)") plt.grid(True) plt.show() else: print("A*算法未能找到路径") # 对地图2执行路径规划 print("\n=== 地图2路径规划 ===") # 使用PSO算法 pso2 = PSO(map2, map2.start, map2.goal, num_particles=30, max_iter=100) pso_path2, pso_fitness_history2 = pso2.optimize() # 使用A*算法 astar2 = AStar(map2, map2.start, map2.goal) astar_path2 = astar2.find_path() if astar_path2: print(f"PSO路径长度: {len(pso_path2)}") print(f"A*路径长度: {len(astar_path2)}") # 可视化结果 visualize_results(map2, pso_path2, astar_path2, "地图2路径规划结果对比") # 绘制适应度历史 plt.figure(figsize=(10, 6)) plt.plot(pso_fitness_history2) plt.title("PSO算法适应度历史(地图2)") plt.xlabel("迭代次数") plt.ylabel("适应度(路径长度)") plt.grid(True) plt.show() else: print("A*算法未能找到路径") # 算法性能对比 plt.figure(figsize=(12, 6)) plt.subplot(1, 2, 1) plt.bar(['PSO', 'A*'], [len(pso_path1), len(astar_path1)]) plt.title('地图1路径长度对比') plt.ylabel('路径长度') plt.ylim(0, max(len(pso_path1), len(astar_path1)) * 1.1) plt.subplot(1, 2, 2) plt.bar(['PSO', 'A*'], [len(pso_path2), len(astar_path2)]) plt.title('地图2路径长度对比') plt.ylabel('路径长度') plt.ylim(0, max(len(pso_path2), len(astar_path2)) * 1.1) plt.tight_layout() plt.show() if __name__ == "__main__": main() ``` ### **关键修复点**: 1. **速度初始化**: - 原先 `self.velocities.append([random.uniform(-1, 1) for _ in range(len(path))])` 会导致速度是一个列表的列表,后续无法直接与浮点数相乘。 - 修复为 `velocity = [(random.uniform(-1, 1), random.uniform(-1, 1)) for _ in range(len(path))]`,即每个节点的速度是一个二维元组 `(vx, vy)`。 2. **速度更新**: - 原先 `velocity[j] = (self.w * velocity[j][0] + cognitive_component[0] + social_component[0], ...)` 会尝试将列表与浮点数相乘。 - 修复为分别更新 `vx` 和 `vy` 分量: ```python new_vx = self.w * velocity[j][0] + cognitive_x + social_x new_vy = self.w * velocity[j][1] + cognitive_y + social_y ``` 3. **位置更新**: - 使用 `new_vx` 和 `new_vy` 更新位置,而不是直接操作速度列表。 ### **其他注意事项**: - 如果仍然报错,请检查 `random.uniform(-1, 1)` 是否生成了合法的浮点数。 - 确保 `particle[j]` 和 `velocity[j]` 的维度一致(均为 `(x, y)` 元组)。 运行修复后的代码应该可以正常生成路径规划结果和图像。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值