来自:http://www.duzengqiang.com/blog/post/971.html 转载请标明出处。
What's MaxRectsBinPack
MaxRects算法是一个二维图像排列算法,在FlashCS6的Sprite导出功能和TexturePacker中均有使用.
Reference
Based on the Public Domain MaxRectanglesBinPack.cpp source by Jukka Jylänki
https://github.com/juj/RectangleBinPack/
Based on C# port by Sven Magnus
http://unifycommunity.com/wiki/index.php?title=MaxRectanglesBinPack
Ported to ActionScript3 by DUZENGQIANG
This version is also public domain - do whatever you want with it.
Source Code
/* Based on the Public Domain MaxRectanglesBinPack.cpp source by Jukka Jyl?nki https://github.com/juj/RectangleBinPack/ Based on C# port by Sven Magnus http://unifycommunity.com/wiki/index.php?title=MaxRectanglesBinPack Ported to ActionScript3 by DUZENGQIANG http://www.duzengqiang.com/blog/post/971.html This version is also public domain - do whatever you want with it. */ package { import flash.display.*; import flash.events.*; import flash.geom.Rectangle; import flash.net.*; /** * MaxRectanglesBinPack * @author DUZENGQIANG * @date Jun 7, 2012 * @version 1.0 * <p>SinaMicroBlog: http://weibo.com/duzengqiang</p> * <p>blog: http://www.duzengqiang.com</p> */ public class MaxRectsBinPack { public var binWidth:int = 0; public var binHeight:int = 0; public var allowRotations:Boolean = false; public var usedRectangles:Vector.<Rectangle> = new Vector.<Rectangle>(); public var freeRectangles:Vector.<Rectangle> = new Vector.<Rectangle>(); private var score1:int = 0; // Unused in this function. We don't need to know the score after finding the position. private var score2:int = 0; private var bestShortSideFit:int; private var bestLongSideFit:int; public function MaxRectsBinPack( width:int, height:int, rotations:Boolean = true) { init(width, height, rotations); } private function init(width:int, height:int, rotations:Boolean = true):void { if( count(width) % 1 != 0 ||count(height) % 1 != 0) throw new Error("Must be 2,4,8,16,32,...512,1024,..."); binWidth = width; binHeight = height; allowRotations = rotations; var n:Rectangle = new Rectangle(); n.x = 0; n.y = 0; n.width = width; n.height = height; usedRectangles.length = 0; freeRectangles.length = 0; freeRectangles.push( n ); } private function count(n:Number):Number { if( n >= 2 ) return count(n / 2); return n; } /** * Insert a new Rectangle * @param width * @param height * @param method * @return * */ public function insert(width:int, height:int, method:int):Rectangle { var newNode:Rectangle = new Rectangle(); score1 = 0; score2 = 0; switch(method) { case FreeRectangleChoiceHeuristic.BestShortSideFit: newNode = findPositionForNewNodeBestShortSideFit(width, height); break; case FreeRectangleChoiceHeuristic.BottomLeftRule: newNode = findPositionForNewNodeBottomLeft(width, height, score1, score2); break; case FreeRectangleChoiceHeuristic.ContactPointRule: newNode = findPositionForNewNodeContactPoint(width, height, score1); break; case FreeRectangleChoiceHeuristic.BestLongSideFit: newNode = findPositionForNewNodeBestLongSideFit(width, height, score2, score1); break; case FreeRectangleChoiceHeuristic.BestAreaFit: newNode = findPositionForNewNodeBestAreaFit(width, height, score1, score2); break; } if (newNode.height == 0) return newNode; placeRectangle(newNode); trace(newNode); return newNode; } private function insert2( Rectangles:Vector.<Rectangle>, dst:Vector.<Rectangle>, method:int):void { dst.length = 0; while(Rectangles.length > 0) { var bestScore1:int = int.MAX_VALUE; var bestScore2:int = int.MAX_VALUE; var bestRectangleIndex:int = -1; var bestNode:Rectangle = new Rectangle(); for(var i:int = 0; i < Rectangles.length; ++i) { var score1:int = 0; var score2:int = 0; var newNode:Rectangle = scoreRectangle(Rectangles[i].width, Rectangles[i].height, method, score1, score2); if (score1 < bestScore1 || (score1 == bestScore1 && score2 < bestScore2)) { bestScore1 = score1; bestScore2 = score2; bestNode = newNode; bestRectangleIndex = i; } } if (bestRectangleIndex == -1) return; placeRectangle(bestNode); Rectangles.splice(bestRectangleIndex,1); } } private function placeRectangle(node:Rectangle):void { var numRectanglesToProcess:int = freeRectangles.length; for(var i:int = 0; i < numRectanglesToProcess; i++) { if (splitFreeNode(freeRectangles[i], node)) { freeRectangles.splice(i,1); --i; --numRectanglesToProcess; } } pruneFreeList(); usedRectangles.push(node); } private function scoreRectangle( width:int, height:int, method:int, score1:int, score2:int):Rectangle { var newNode:Rectangle = new Rectangle(); score1 = int.MAX_VALUE; score2 = int.MAX_VALUE; switch(method) { case FreeRectangleChoiceHeuristic.BestShortSideFit: newNode = findPositionForNewNodeBestShortSideFit(width, height); break; case FreeRectangleChoiceHeuristic.BottomLeftRule: newNode = findPositionForNewNodeBottomLeft(width, height, score1,score2); break; case FreeRectangleChoiceHeuristic.ContactPointRule: newNode = findPositionForNewNodeContactPoint(width, height, score1); // todo: reverse score1 = -score1; // Reverse since we are minimizing, but for contact point score bigger is better. break; case FreeRectangleChoiceHeuristic.BestLongSideFit: newNode = findPositionForNewNodeBestLongSideFit(width, height, score2, score1); break; case FreeRectangleChoiceHeuristic.BestAreaFit: newNode = findPositionForNewNodeBestAreaFit(width, height, score1, score2); break; } // Cannot fit the current Rectangle. if (newNode.height == 0) { score1 = int.MAX_VALUE; score2 = int.MAX_VALUE; } return newNode; } /// Computes the ratio of used surface area. private function occupancy():Number { var usedSurfaceArea:Number = 0; for(var i:int = 0; i < usedRectangles.length; i++) usedSurfaceArea += usedRectangles[i].width * usedRectangles[i].height; return usedSurfaceArea / (binWidth * binHeight); } private function findPositionForNewNodeBottomLeft(width:int, height:int, bestY:int, bestX:int) { var bestNode:Rectangle = new Rectangle(); //memset(bestNode, 0, sizeof(Rectangle)); bestY = int.MAX_VALUE; var rect:Rectangle; var topSideY:int; for(var i:int = 0; i < freeRectangles.length; i++) { rect = freeRectangles[i]; // Try to place the Rectangle in upright (non-flipped) orientation. if (rect.width >= width && rect.height >= height) { topSideY = rect.y + height; if (topSideY < bestY || (topSideY == bestY && rect.x < bestX)) { bestNode.x = rect.x; bestNode.y = rect.y; bestNode.width = width; bestNode.height = height; bestY = topSideY; bestX = rect.x; } } if (allowRotations && rect.width >= height && rect.height >= width) { topSideY = rect.y + width; if (topSideY < bestY || (topSideY == bestY && rect.x < bestX)) { bestNode.x = rect.x; bestNode.y = rect.y; bestNode.width = height; bestNode.height = width; bestY = topSideY; bestX = rect.x; } } } return bestNode; } private function findPositionForNewNodeBestShortSideFit(width:int, height:int):Rectangle { var bestNode:Rectangle = new Rectangle(); //memset(&bestNode, 0, sizeof(Rectangle)); bestShortSideFit = int.MAX_VALUE; bestLongSideFit = score2; var rect:Rectangle; var leftoverHoriz:int; var leftoverVert:int; var shortSideFit:int; var longSideFit:int; for(var i:int = 0; i < freeRectangles.length; i++) { rect = freeRectangles[i]; // Try to place the Rectangle in upright (non-flipped) orientation. if (rect.width >= width && rect.height >= height) { leftoverHoriz = Math.abs(rect.width - width); leftoverVert = Math.abs(rect.height - height); shortSideFit = Math.min(leftoverHoriz, leftoverVert); longSideFit = Math.max(leftoverHoriz, leftoverVert); if (shortSideFit < bestShortSideFit || (shortSideFit == bestShortSideFit && longSideFit < bestLongSideFit)) { bestNode.x = rect.x; bestNode.y = rect.y; bestNode.width = width; bestNode.height = height; bestShortSideFit = shortSideFit; bestLongSideFit = longSideFit; } } var flippedLeftoverHoriz:int; var flippedLeftoverVert:int; var flippedShortSideFit:int; var flippedLongSideFit:int; if (allowRotations && rect.width >= height && rect.height >= width) { var flippedLeftoverHoriz = Math.abs(rect.width - height); var flippedLeftoverVert = Math.abs(rect.height - width); var flippedShortSideFit = Math.min(flippedLeftoverHoriz, flippedLeftoverVert); var flippedLongSideFit = Math.max(flippedLeftoverHoriz, flippedLeftoverVert); if (flippedShortSideFit < bestShortSideFit || (flippedShortSideFit == bestShortSideFit && flippedLongSideFit < bestLongSideFit)) { bestNode.x = rect.x; bestNode.y = rect.y; bestNode.width = height; bestNode.height = width; bestShortSideFit = flippedShortSideFit; bestLongSideFit = flippedLongSideFit; } } } return bestNode; } private function findPositionForNewNodeBestLongSideFit(width:int, height:int, bestShortSideFit:int, bestLongSideFit:int):Rectangle { var bestNode:Rectangle = new Rectangle(); //memset(&bestNode, 0, sizeof(Rectangle)); bestLongSideFit = int.MAX_VALUE; var rect:Rectangle; var leftoverHoriz:int; var leftoverVert:int; var shortSideFit:int; var longSideFit:int; for(var i:int = 0; i < freeRectangles.length; i++) { rect = freeRectangles[i]; // Try to place the Rectangle in upright (non-flipped) orientation. if (rect.width >= width && rect.height >= height) { leftoverHoriz = Math.abs(rect.width - width); leftoverVert = Math.abs(rect.height - height); shortSideFit = Math.min(leftoverHoriz, leftoverVert); longSideFit = Math.max(leftoverHoriz, leftoverVert); if (longSideFit < bestLongSideFit || (longSideFit == bestLongSideFit && shortSideFit < bestShortSideFit)) { bestNode.x = rect.x; bestNode.y = rect.y; bestNode.width = width; bestNode.height = height; bestShortSideFit = shortSideFit; bestLongSideFit = longSideFit; } } if (allowRotations && rect.width >= height && rect.height >= width) { leftoverHoriz = Math.abs(rect.width - height); leftoverVert = Math.abs(rect.height - width); shortSideFit = Math.min(leftoverHoriz, leftoverVert); longSideFit = Math.max(leftoverHoriz, leftoverVert); if (longSideFit < bestLongSideFit || (longSideFit == bestLongSideFit && shortSideFit < bestShortSideFit)) { bestNode.x = rect.x; bestNode.y = rect.y; bestNode.width = height; bestNode.height = width; bestShortSideFit = shortSideFit; bestLongSideFit = longSideFit; } } } trace(bestNode); return bestNode; } private function findPositionForNewNodeBestAreaFit(width:int, height:int, bestAreaFit:int, bestShortSideFit:int):Rectangle { var bestNode:Rectangle = new Rectangle(); //memset(&bestNode, 0, sizeof(Rectangle)); bestAreaFit = int.MAX_VALUE; var rect:Rectangle; var leftoverHoriz:int; var leftoverVert:int; var shortSideFit:int; var areaFit:int; for(var i:int = 0; i < freeRectangles.length; i++) { rect = freeRectangles[i]; areaFit = rect.width * rect.height - width * height; // Try to place the Rectangle in upright (non-flipped) orientation. if (rect.width >= width && rect.height >= height) { leftoverHoriz = Math.abs(rect.width - width); leftoverVert = Math.abs(rect.height - height); shortSideFit = Math.min(leftoverHoriz, leftoverVert); if (areaFit < bestAreaFit || (areaFit == bestAreaFit && shortSideFit < bestShortSideFit)) { bestNode.x = rect.x; bestNode.y = rect.y; bestNode.width = width; bestNode.height = height; bestShortSideFit = shortSideFit; bestAreaFit = areaFit; } } if (allowRotations && rect.width >= height && rect.height >= width) { leftoverHoriz = Math.abs(rect.width - height); leftoverVert = Math.abs(rect.height - width); shortSideFit = Math.min(leftoverHoriz, leftoverVert); if (areaFit < bestAreaFit || (areaFit == bestAreaFit && shortSideFit < bestShortSideFit)) { bestNode.x = rect.x; bestNode.y = rect.y; bestNode.width = height; bestNode.height = width; bestShortSideFit = shortSideFit; bestAreaFit = areaFit; } } } return bestNode; } /// Returns 0 if the two intervals i1 and i2 are disjoint, or the length of their overlap otherwise. private function commonIntervalLength(i1start:int, i1end:int, i2start:int, i2end:int):int { if (i1end < i2start || i2end < i1start) return 0; return Math.min(i1end, i2end) - Math.max(i1start, i2start); } private function contactPointScoreNode(x:int, y:int, width:int, height:int):int { var score:int = 0; if (x == 0 || x + width == binWidth) score += height; if (y == 0 || y + height == binHeight) score += width; var rect:Rectangle; for(var i:int = 0; i < usedRectangles.length; i++) { rect = usedRectangles[i]; if (rect.x == x + width || rect.x + rect.width == x) score += commonIntervalLength(rect.y, rect.y + rect.height, y, y + height); if (rect.y == y + height || rect.y + rect.height == y) score += commonIntervalLength(rect.x, rect.x + rect.width, x, x + width); } return score; } private function findPositionForNewNodeContactPoint(width:int, height:int, bestContactScore:int):Rectangle { var bestNode:Rectangle = new Rectangle(); //memset(&bestNode, 0, sizeof(Rectangle)); bestContactScore = -1; var rect:Rectangle; var score:int; for(var i:int = 0; i < freeRectangles.length; i++) { rect = freeRectangles[i]; // Try to place the Rectangle in upright (non-flipped) orientation. if (rect.width >= width && rect.height >= height) { score = contactPointScoreNode(rect.x, rect.y, width, height); if (score > bestContactScore) { bestNode.x = rect.x; bestNode.y = rect.y; bestNode.width = width; bestNode.height = height; bestContactScore = score; } } if (allowRotations && rect.width >= height && rect.height >= width) { score = contactPointScoreNode(rect.x, rect.y, height, width); if (score > bestContactScore) { bestNode.x = rect.x; bestNode.y = rect.y; bestNode.width = height; bestNode.height = width; bestContactScore = score; } } } return bestNode; } private function splitFreeNode(freeNode:Rectangle, usedNode:Rectangle):Boolean { // Test with SAT if the Rectangles even intersect. if (usedNode.x >= freeNode.x + freeNode.width || usedNode.x + usedNode.width <= freeNode.x || usedNode.y >= freeNode.y + freeNode.height || usedNode.y + usedNode.height <= freeNode.y) return false; var newNode:Rectangle; if (usedNode.x < freeNode.x + freeNode.width && usedNode.x + usedNode.width > freeNode.x) { // New node at the top side of the used node. if (usedNode.y > freeNode.y && usedNode.y < freeNode.y + freeNode.height) { newNode = freeNode.clone(); newNode.height = usedNode.y - newNode.y; freeRectangles.push(newNode); } // New node at the bottom side of the used node. if (usedNode.y + usedNode.height < freeNode.y + freeNode.height) { newNode = freeNode.clone(); newNode.y = usedNode.y + usedNode.height; newNode.height = freeNode.y + freeNode.height - (usedNode.y + usedNode.height); freeRectangles.push(newNode); } } if (usedNode.y < freeNode.y + freeNode.height && usedNode.y + usedNode.height > freeNode.y) { // New node at the left side of the used node. if (usedNode.x > freeNode.x && usedNode.x < freeNode.x + freeNode.width) { newNode = freeNode.clone(); newNode.width = usedNode.x - newNode.x; freeRectangles.push(newNode); } // New node at the right side of the used node. if (usedNode.x + usedNode.width < freeNode.x + freeNode.width) { newNode = freeNode.clone(); newNode.x = usedNode.x + usedNode.width; newNode.width = freeNode.x + freeNode.width - (usedNode.x + usedNode.width); freeRectangles.push(newNode); } } return true; } private function pruneFreeList():void { for(var i:int = 0; i < freeRectangles.length; i++) for(var j:int = i+1; j < freeRectangles.length; j++) { if (isContainedIn(freeRectangles[i], freeRectangles[j])) { freeRectangles.splice(i,1); break; } if (isContainedIn(freeRectangles[j], freeRectangles[i])) { freeRectangles.splice(j,1); } } } private function isContainedIn(a:Rectangle, b:Rectangle):Boolean { return a.x >= b.x && a.y >= b.y && a.x+a.width <= b.x+b.width && a.y+a.height <= b.y+b.height; } } } class FreeRectangleChoiceHeuristic { public static const BestShortSideFit:int = 0; ///< -BSSF: Positions the Rectangle against the short side of a free Rectangle into which it fits the best. public static const BestLongSideFit:int = 1; ///< -BLSF: Positions the Rectangle against the long side of a free Rectangle into which it fits the best. public static const BestAreaFit:int = 2; ///< -BAF: Positions the Rectangle into the smallest free Rectangle into which it fits. public static const BottomLeftRule:int = 3; ///< -BL: Does the Tetris placement. public static const ContactPointRule:int = 4; ///< -CP: Choosest the placement where the Rectangle touches other Rectangles as much as possible. }
Download
How to use
//Create new MaxRectsBinPack instance
var maxRect:MaxRectsBinPack = new MaxRectsBinPack(1024,1024,false);
// insert new rectangle
maxRect.insert(300,200,0);
//There are 5 insert method in FreeRectangleChoiceHeuristic class.
// class FreeRectangleChoiceHeuristic {
// public static const BestShortSideFit:int = 0; ///< -BSSF: Positions the Rectangle against the short side of a free Rectangle into which it fits the best.
// public static const BestLongSideFit:int = 1; ///< -BLSF: Positions the Rectangle against the long side of a free Rectangle into which it fits the best.
// public static const BestAreaFit:int = 2; ///< -BAF: Positions the Rectangle into the smallest free Rectangle into which it fits.
// public static const BottomLeftRule:int = 3; ///< -BL: Does the Tetris placement.
// public static const ContactPointRule:int = 4; ///< -CP: Choosest the placement where the Rectangle touches other Rectangles as much as possible.
//}
usedRectangles: storage of all used rectangles
freeRectangles: storage of all free rectangles
The insert method will return a rectangle. when its width an height are both 0. That means it can not be inserted anymore.
For more information, see a series of blog posts at
http://clb.demon.fi/projects/rectangle-bin-packing
http://clb.demon.fi/projects/more-rectangle-bin-packing
http://clb.demon.fi/projects/even-more-rectangle-bin-packing
使用方法:http://www.cnblogs.com/yourihua/archive/2012/06/19/2554687.html
相关推荐
在本文中,我们将探讨一种特殊的算法...这些算法对于优化存储、包装、纹理图集创建等实际问题具有重要意义。同时,文章还强调了针对特定目标的改进方法,如选择目标箱,这表明在实际应用中,算法的选择和调整是关键。
# 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
内容概要:本文详细探讨了基于模型预测控制(MPC)的微网共享储能优化调度技术,分为日前优化和日内滚动MPC跟踪两大部分。日前优化部分通过分析居民用电需求,制定储能充放电策略,确保整体能源利用效率最大化。日内滚动MPC跟踪部分则通过预测模型、滚动优化和反馈校正,动态调整储能状态,保持系统稳定。文中提供了多个Python和MATLAB代码片段,展示了具体的技术实现细节,如K-means聚类、CVXPY建模、LSTM+ARIMA混合预测等。 适合人群:从事微网系统设计、储能优化调度的研究人员和技术开发者,以及对模型预测控制感兴趣的工程技术人员。 使用场景及目标:适用于微网系统的储能管理,旨在提高能源利用效率、降低运营成本,并确保系统在各种工况下的稳定性。主要目标是通过合理的储能调度,实现削峰填谷和平抑负荷波动。 其他说明:文章不仅介绍了理论背景,还分享了实际应用中的经验和教训,如处理光伏出力预测误差、优化求解器性能等问题。同时,文中提到的一些关键技术点,如充放电互斥约束、终端约束等,有助于深入理解MPC的应用挑战和解决方案。
本书由Bernard Marr撰写,探讨了互联网的第三次演变——未来互联网,即Web 3.0和元宇宙的概念。作者详细分析了元宇宙技术、Web3和区块链如何共同作用,推动互联网向更沉浸式和去中心化的方向发展。书中指出,这一变革不仅将改变我们的日常生活和娱乐方式,还将深刻影响教育、金融、医疗保健以及制造业等多个行业。同时,作者也探讨了政府和公共服务如何利用未来互联网提高效率,以及企业如何在这一变革中重新思考产品、服务和业务运营。书中还强调了未来互联网对技能需求的影响,以及如何在企业中建立适应未来互联网的成功文化,并制定相应的战略。
# 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
内容概要:本文详细介绍了如何使用VHDL语言在FPGA上实现16阶FIR低通滤波器的设计与实现。首先,文中给出了滤波器的基本参数设定,如采样率为50MHz,截止频率为3MHz,并采用汉明窗进行设计。接着,展示了顶层实体声明及其内部逻辑结构,包括移位寄存器作为延迟线以及乘累加操作的具体实现方法。同时提供了完整的VHDL代码片段,涵盖了从顶层实体定义到具体的功能模块,如系数生成、数据移位寄存器和乘累加模块。此外,还讨论了ModelSim仿真的配置与测试激励生成方式,确保仿真结果能够正确反映滤波器性能。最后,针对硬件实现过程中可能出现的问题进行了提示,如时钟约束、资源优化等。 适合人群:具有一定FPGA开发经验的技术人员,尤其是对VHDL编程有一定了解并希望深入研究FIR滤波器实现的人群。 使用场景及目标:适用于需要在FPGA平台上快速搭建并验证FIR低通滤波器的应用场合。主要目标是帮助开发者掌握FIR滤波器的工作原理及其在FPGA上的高效实现方法。 其他说明:文中不仅提供了详细的代码示例,还包括了许多实用的经验分享和技术要点提醒,有助于提高开发效率并减少常见错误的发生。
内容概要:本文详细介绍了车辆紧急防避撞AEB控制系统的构建与实现。首先,文章阐述了驾驶员制动模型,通过模拟人类驾驶者的制动行为,使车辆能够根据实际情况做出适当的制动反应。其次,引入了模糊控制方法用于计算期望减速度,使得车辆能够在面对不确定性环境时作出智能化决策。再次,建立了纵向发动机逆动力学模型,以确定合适的节气门开度,确保车辆的动力输出满足制动需求。此外,还探讨了制动压力与减速度的关系以及风阻和滚动阻力的影响,并展示了具体的代码实现。最后,文章描述了仿真的步骤,强调了验证模型有效性的重要性。 适合人群:从事自动驾驶技术研发的专业人士、对车辆控制感兴趣的工程师和技术爱好者。 使用场景及目标:适用于研究和开发先进的车辆安全辅助系统,旨在提高车辆在紧急情况下的避撞能力,减少交通事故的发生。通过理解和应用文中提供的模型和代码,可以为实际工程项目提供理论支持和技术指导。 其他说明:文章不仅提供了详细的理论解释,还包括了大量的代码示例,便于读者理解和实践。同时,作者还分享了一些实际开发中的经验和技巧,有助于解决可能出现的问题并优化系统性能。
Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码,个人经导师指导并认可通过的高分设计项目,评审分99分,代码完整确保可以运行,小白也可以亲自搞定,主要针对计算机相关专业的正在做大作业的学生和需要项目实战练习的学习者,可作为毕业设计、课程设计、期末大作业,代码资料完整,下载可用。 Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源
脚本功能: 自动打开浏览器。 进入指定的登录页面。 输入预设的用户名和密码。 点击登录按钮。 登录成功后获取用户信息并打印。 点击退出按钮并退出登录。 关闭浏览器。 注意事项: 确保已安装适用于您浏览器的驱动程序,例如 ChromeDriver,并正确设置其路径。 在实际应用中,您需要根据目标网站的结构和元素修改选择器(如 By.NAME、By.ID 等)和相应的值。 此脚本仅为示例,实际使用时需要考虑更复杂的场景,例如异常处理、验证码处理、动态元素加载等。 遵守目标网站的使用条款和法律法规,不要用于非法或未经授权的操作。
# 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
【信息安全领域实战项目】
# 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
内容概要:本文探讨了基于滑膜控制的五辆车编队实现自适应协同巡航控制(ACC)的研究。通过carsim/Simulink平台进行仿真,采用分层控制结构,上层滑膜控制器根据前车的距离和速度误差计算期望加速度,下层则通过控制节气门开度和制动压力来实现车速控制。文中展示了详细的算法架构、关键代码片段以及丰富的仿真结果图,验证了滑膜控制在车辆编队中的优越性能,特别是在紧急情况下能够迅速反应并保持稳定的跟车距离。 适合人群:对自动驾驶技术和车辆控制系统感兴趣的科研人员、工程师及高校相关专业学生。 使用场景及目标:适用于研究和开发多车编队的自适应巡航控制系统,旨在提高车队行驶的安全性和效率。具体目标包括减少车速跟踪误差、优化节气门和制动控制、提升紧急情况下的响应速度。 其他说明:提供了详细的滑膜控制理论讲解和技术实现细节,附带完整的仿真数据和工程落地指导,有助于读者深入理解和应用该技术。
# 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
内容概要:本文详细介绍了三相桥式整流电路采用双闭环控制(电流内环和电压外环)的方法及其在MATLAB中的仿真实现。首先阐述了为何需要引入电流内环来提高系统的动态响应速度和稳定性,特别是在负载突变情况下。接着描述了硬件配置,包括六个晶闸管的工作方式以及触发脉冲的生成机制。文中给出了具体的双PI控制器参数设置方法,并展示了如何通过调整电流环和电压环的比例和积分系数来优化系统性能。此外,还讨论了常见的调试问题及解决方案,如同步触发信号的相位补偿、PI参数的选择、采样时间的影响等。最后通过仿真实验数据对比,证明了双闭环控制相比单环控制在稳定性和抗干扰方面有着显著优势。 适合人群:从事电力电子研究的技术人员、高校相关专业师生、对电力电子控制系统感兴趣的工程技术人员。 使用场景及目标:适用于需要深入了解三相桥式整流电路双闭环控制原理并进行仿真实践的学习者;旨在帮助读者掌握双闭环控制系统的参数选择、调试技巧及应用实例。 其他说明:文中提供了大量MATLAB代码片段用于辅助理解和实施具体控制策略,同时分享了许多来自实际项目的经验教训,有助于读者更好地将理论应用于实践中。
内容概要:本文详细介绍了飞蛾扑火优化算法(Moth Flame Optimization, MFO)的原理和实现方法。首先解释了MFO的基本概念,即通过模仿飞蛾绕光飞行的行为来构建优化算法。接着展示了MFO的关键公式和Matlab代码实现,特别是飞蛾位置更新公式的具体形式。文中提供了23个经典的测试函数用于评估MFO性能,并给出了具体的调用方式。此外,还讨论了算法运行效果以及一些重要的调参经验和技巧,如种群数量、迭代次数、边界设定等。最后分享了一个实际应用案例,展示了MFO在光伏电池板排布优化中的成功应用。 适合人群:对优化算法感兴趣的科研工作者、学生以及从事相关领域研究的专业人士。 使用场景及目标:适用于需要高效求解复杂优化问题的研究项目,尤其是涉及多峰函数优化的情况。目标是帮助读者掌握MFO的工作原理并能够独立应用于实际问题中。 其他说明:本文不仅提供了详细的理论讲解和技术细节,还包括完整的代码实现和丰富的实验数据,有助于深入理解和实践MFO算法。
DBeaver 是一个通用的数据库管理工具和 SQL 客户端,具有许多功能,包括元数据编辑器、SQL 编辑器、富数据编辑器、ERD、数据导出/导入/迁移、SQL 执行计划等。支持 MySQL, PostgreSQL, Oracle, DB2, MSSQL, Sybase, Mimer, HSQLDB、Derby、Teradata、Vertica、Netezza、Informix 等。
内容概要:本文详细探讨了永磁同步电机(PMSM)中采用降阶负载转矩观测器进行转矩估计的方法,并介绍了将估计得到的负载转矩用于前馈补偿的技术。首先,文章指出传统全阶观测器存在模型复杂、参数调整困难的问题,提出利用降阶观测器简化模型并提高参数调整效率。接着,通过具体的数学推导和MATLAB/Simulink代码展示了降阶观测器的设计过程,强调了关键参数如观测器增益的选择对系统性能的影响。然后,讨论了前馈补偿的具体实现方式,即在速度环输出中加入负载转矩估计值,从而有效减小突加负载引起的转速波动。最后,通过实验数据对比证明了该方法的有效性和优越性,尤其是在应对突加负载时的表现更为突出。 适合人群:从事电机控制领域的研究人员和技术人员,尤其是关注永磁同步电机控制策略优化的专业人士。 使用场景及目标:适用于需要精确控制永磁同步电机转矩的应用场合,如电梯、电动汽车等。目标是提高系统的抗干扰能力和稳定性,减少突加负载导致的转速波动。 其他说明:文中提供了详细的MATLAB和C语言代码示例以及仿真模型构建指南,有助于读者理解和实践所介绍的技术。此外,还分享了一些实用的工程经验和调试技巧,如参数设置范围、注意事项等。
内容概要:本文详细介绍了西门子1200 PLC在水处理系统中的应用,重点讲解了SCL编程实现的关键功能块,包括模拟量换算、滤波、时间换算以及Modbus TCP通讯程序。每个功能块都有详细的代码示例和应用场景说明,展示了如何将模拟量信号转换为数字量、去除信号噪声、进行时间单位换算以及实现设备间的高效通信。此外,文中还提到了一些实用技巧,如仿真环境搭建、电气原理图解读、HMI界面设计等。 适合人群:具备一定PLC编程基础的技术人员,尤其是从事水处理行业自动化控制领域的工程师。 使用场景及目标:① 学习如何利用SCL语言编写高效的PLC功能块;② 掌握水处理系统中常见的信号处理方法;③ 实现PLC与其他设备之间的可靠通信;④ 提升对复杂工业控制系统的设计和调试能力。 其他说明:文中不仅提供了理论知识,还分享了许多实际项目中的经验和优化技巧,帮助读者更好地理解和应用所学内容。
内容概要:本文详细介绍了永磁同步电机和直流无刷电机无感FOC(磁场定向控制)的源码及其关键技术。首先探讨了速度与位置估算代码的设计,展示了如何使用实际值单位使代码更加直观。接着介绍了基于TI FOC框架的磁链观测器,强调了其开源性质和详细的注释,便于理解和扩展。此外,文章还提到了雅特力AT32平台的工程源码,以及电流环PI参数自动计算功能,显著提升了开发效率。最后,讨论了优秀的启动性能,如静止闭环启动、快速角度收敛、PLL锁相环的速度角度跟踪和鲁棒性强的特点。 适合人群:电机控制领域的工程师和技术爱好者,尤其是那些希望深入了解无感FOC控制机制并应用于实际项目的人群。 使用场景及目标:适用于需要高效、稳定的电机控制系统的设计和开发。目标是帮助读者掌握无感FOC控制的核心技术和实现方法,提高系统的响应速度和稳定性。 其他说明:文中提供的代码示例和解释有助于读者更好地理解无感FOC的工作原理,并提供了一种高效的开发方式,减少了调试时间和成本。