Unity 家居摆放系统设计 (一)

2024-08-27 03:48

本文主要是介绍Unity 家居摆放系统设计 (一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

之前看到明日方舟的宿舍挺有趣的,可以摆放大小不一的家具在一个矩形体的六面墙上。之前写了没时间弄博客现在做下记录。

本次设计点:

1、层级结构为,根节点下面有六面墙壁,每面墙在代码里会进行大小的缩放,所以这里为保持每面墙内的物体能够按照实际大小摆放,多加了一个反向缩放的原始节点层,在里面就是格子层和家具层

顶部墙面

 

 

 底部墙面

 

 

 

 

 前部墙面

 

 

 

 垂直的面加了四条线以显示边界

 

 

 

 后部墙面

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2、房间大小、格子大小、家具大小全部动态设置,效果如下面图所示:

格子正方形,房间正方形,家具长方形

 格子长方形,房间正方形,家具正方形

房间长方形,格子正方形,家具正方形

 

 3、目前一个面一个碰撞体共6个碰撞体,为了每一面都可以求出局部坐标进而求出每个格子的坐标再换算出行列;重合检测有房间内的所有家具的边界检测,和所有家具之间的重合检测。目前没时间弄,边界检查只需判断家具靠墙的一面的长宽共4个点是否越出墙的长宽即可;至于家具之前的重合检测,初步考虑用算法,将房间分割成X*Y*Z个小六面体,每个小六面体都存储有投影到六面墙上时每一面墙上对应所有已被其他家具占用的格子,这样每次家具的移动都对n个被波及到的小六面体进行数据增删以及检测重合。或者考虑用八叉树处理优化下。具体有空再试试

4、未精简优化代码:

控制器:

module("room.RoomController", Class.impl(Controller))--构造函数
function ctor(self, cusMgr)super.ctor(self, cusMgr)
end--析构函数
function dtor(self)
end-- Override 重新登录
function reLogin(self)super.reLogin(self)
end--游戏开始的回调
function gameStartCallBack(self)
end--模块间事件监听
function listNotification(self)GameDispatcher:addEventListener(room.RoomManager.OPEN_ROOM_PANEL, self.__onOpenRoomPanelHandler, self)
end--注册server发来的数据
function registerMsgHandler(self)return {}
endfunction __onOpenRoomPanelHandler(self, args)self:__addFrameHandler()self:__openRoomScene()room.RoomManager:setMainUICameraVisible(false)if(not self.mRoomPanel)thenself.mRoomPanel = room.RoomPanel.new()self.mRoomPanel:addEventListener(View.EVENT_VIEW_DESTROY, self.onDestroyRoomPanelHandler,self)endself.mRoomPanel:open()
endfunction onDestroyRoomPanelHandler(self)self:__removeFrameHandler()self:__closeRoomScene()room.RoomManager:setMainUICameraVisible(true)self.mRoomPanel:removeEventListener(View.EVENT_VIEW_DESTROY,self.onDestroyRoomPanelHandler,self)self.mRoomPanel = nil
end---------------------------------------------------------------场景--------------------------------------------------------------------------
function __addFrameHandler(self)LoopManager:addFrame(1, 0, self, self.__frameUpdate)
endfunction __removeFrameHandler(self)LoopManager:removeFrame(self, self.__frameUpdate)
endfunction __frameUpdate(self)if(gs.Input:GetMouseButton(0))thenlocal sceneCamera = room.RoomManager:getSceneCamera():GetComponent(ty.Camera)local hitInfo = gs.UnityEngineUtil.RaycastByUICamera(sceneCamera, "", 100)if(hitInfo) thenlocal transform = hitInfo.transformif(transform)thenif(string.find(transform.name, "WALL_") ~= nil)thenlocal needUpdate = falselocal dirType = room.getDirType(transform.name)if(self.mCurDirType ~= dirType)thenneedUpdate = truelocal oldIndex = self.mCurIndexlocal oldDirType, newDirType = self.mCurDirType, dirTypeself.mCurDirType = dirTypeself:changeTileMaterial(oldDirType, nil)local thing = self.mThingDic[oldDirType][oldIndex]self.mThingDic[oldDirType][oldIndex] = nilthing.transform:SetParent(self.mThingNodeDic[newDirType].transform, false)local localPos = self.mThingNodeDic[newDirType].transform:InverseTransformPoint(hitInfo.point)local row, col = self:getRowColByPos(newDirType, localPos.x, localPos.y)local index = self:getTileIndexByRowCol(newDirType, row, col)self.mCurIndex = indexif(not self.mThingDic[newDirType])thenself.mThingDic[newDirType] = {}endself.mThingDic[newDirType][self.mCurIndex] = thingelselocal localPos = self.mThingNodeDic[self.mCurDirType].transform:InverseTransformPoint(hitInfo.point)local row, col = self:getRowColByPos(self.mCurDirType, localPos.x, localPos.y)local index = self:getTileIndexByRowCol(self.mCurDirType, row, col)if(self.mCurIndex ~= index)thenneedUpdate = truelocal oldIndex = self.mCurIndexself.mCurIndex = indexlocal thing = self.mThingDic[self.mCurDirType][oldIndex]self.mThingDic[self.mCurDirType][oldIndex] = nilself.mThingDic[self.mCurDirType][self.mCurIndex] = thingendend-- 直接跟随鼠标坐标if(needUpdate)thenlocal localPos = self.mThingNodeDic[self.mCurDirType].transform:InverseTransformPoint(hitInfo.point)local thingId = room.RoomManager:getThingIdByIndex(self.mCurIndex)local thingConfigVo = room.RoomManager:getThingConfigVo(thingId)localPos.z = localPos.z + thingConfigVo:getSizeY() / 2self.mThingDic[self.mCurDirType][self.mCurIndex].transform.localPosition = localPosself:changeTileMaterial(self.mCurDirType, self.mCurIndex)end-- 直接跟随鼠标坐标对应的格子if(needUpdate)thenlocal thingId = room.RoomManager:getThingIdByIndex(self.mCurIndex)local thingConfigVo = room.RoomManager:getThingConfigVo(thingId)local tileX, tileY = self:getTilePos(self.mCurDirType, self.mCurIndex)gs.TransQuick:LPos(self.mThingDic[self.mCurDirType][self.mCurIndex].transform, tileX, tileY, thingConfigVo:getSizeY() / 2)self:changeTileMaterial(self.mCurDirType, self.mCurIndex)endendendendend
endfunction __initSceneData(self)-- 房间场景的各个物体字典self.mWallDic = {}self.mOriginalNodeDic = {}self.mThingNodeDic = {}self.mTileNodeDic = {}-- 房间场景的所有格子字典self.mTileIndexDic = {}-- 房间场景的所有物件字典self.mThingDic = {}
endfunction __openRoomScene(self)self:__initSceneData()-- 初始化self.mRoomScene = AssetLoader.GetGO(UrlManager:getPrefabPath('ui/room/Scene_RoomRoot.prefab'))local childGods, childTrans = GoUtil.GetChildHash(self.mRoomScene)    local dirTypeList = {}table.insert(dirTypeList, room.DIR_TOP)table.insert(dirTypeList, room.DIR_BOTTOM)table.insert(dirTypeList, room.DIR_FRONT)table.insert(dirTypeList, room.DIR_BEHIND)table.insert(dirTypeList, room.DIR_LEFT)table.insert(dirTypeList, room.DIR_RIGHT)-- 初始化各个节点for i = 1, #dirTypeList dolocal dirType = dirTypeList[i]self.mWallDic[dirType] = self:getWallNodeName(childGods, dirType)self.mOriginalNodeDic[dirType] = self:getOriginalNodeName(childGods, dirType)self.mThingNodeDic[dirType] = self:getThingNodeName(childGods, dirType)self.mTileNodeDic[dirType] = self:getTileNodeName(childGods, dirType)end-- 场景大小设置local roomSizeX, roomSizeY, roomSizeZ = room.RoomManager:getRoomSize()gs.TransQuick:Pos(self.mRoomScene.transform, 0, 500, roomSizeZ / 2)-- 6面墙的位置gs.TransQuick:LPos(self.mWallDic[room.DIR_TOP].transform, 0, roomSizeY / 2, 0)gs.TransQuick:LPos(self.mWallDic[room.DIR_BOTTOM].transform, 0, -roomSizeY / 2, 0)gs.TransQuick:LPos(self.mWallDic[room.DIR_FRONT].transform, 0, 0, roomSizeZ / 2)gs.TransQuick:LPos(self.mWallDic[room.DIR_BEHIND].transform, 0, 0, -roomSizeZ / 2)gs.TransQuick:LPos(self.mWallDic[room.DIR_RIGHT].transform, roomSizeX / 2, 0, 0)gs.TransQuick:LPos(self.mWallDic[room.DIR_LEFT].transform, -roomSizeX / 2, 0, 0)-- 6面墙的大小local sideDepth = room.RoomManager:getSideDepth()gs.TransQuick:Scale(self.mWallDic[room.DIR_TOP].transform, roomSizeX, roomSizeZ, sideDepth)gs.TransQuick:Scale(self.mWallDic[room.DIR_BOTTOM].transform, roomSizeX, roomSizeZ, sideDepth)gs.TransQuick:Scale(self.mWallDic[room.DIR_FRONT].transform, roomSizeX, roomSizeY, sideDepth)gs.TransQuick:Scale(self.mWallDic[room.DIR_BEHIND].transform, roomSizeX, roomSizeY, sideDepth)gs.TransQuick:Scale(self.mWallDic[room.DIR_RIGHT].transform, roomSizeZ, roomSizeY, sideDepth)gs.TransQuick:Scale(self.mWallDic[room.DIR_LEFT].transform, roomSizeZ, roomSizeY, sideDepth)-- 6面墙缩放后,墙内总结点反向缩放,以使总结点内的所有物体都能按照通用标准大小gs.TransQuick:Scale(self.mOriginalNodeDic[room.DIR_TOP].transform, 1 / roomSizeX, 1 / roomSizeZ, 1 / sideDepth)gs.TransQuick:Scale(self.mOriginalNodeDic[room.DIR_BOTTOM].transform, 1 / roomSizeX, 1 / roomSizeZ, 1 / sideDepth)gs.TransQuick:Scale(self.mOriginalNodeDic[room.DIR_FRONT].transform, 1 / roomSizeX, 1 / roomSizeY, 1 / sideDepth)gs.TransQuick:Scale(self.mOriginalNodeDic[room.DIR_BEHIND].transform, 1 / roomSizeX, 1 / roomSizeY, 1 / sideDepth)gs.TransQuick:Scale(self.mOriginalNodeDic[room.DIR_RIGHT].transform, 1 / roomSizeZ, 1 / roomSizeY, 1 / sideDepth)gs.TransQuick:Scale(self.mOriginalNodeDic[room.DIR_LEFT].transform, 1 / roomSizeZ, 1 / roomSizeY, 1 / sideDepth)-- 场景添加格子for i = 1, #dirTypeList dolocal dirType = dirTypeList[i]self:addTileToWall(dirType)end-- local id = 0-- for i = 1, #dirTypeList do--     id = id + 1--     local dirType = dirTypeList[i]--     self:addThingToWall(dirType, id)-- end-- 初始加一个在底部self.mCurDirType = room.DIR_BOTTOMself.mCurIndex = 1self:addThingToWall(self.mCurDirType, self.mCurIndex)
endfunction changeTileMaterial(self, dirType, index)if(index)thenlocal tileX, tileY = self:getTilePos(dirType, index)local thingX, thingY = tileX, tileYlocal thingId = room.RoomManager:getThingIdByIndex(index)local thingConfigVo = room.RoomManager:getThingConfigVo(thingId)local thingSizeX, thingSizeY, thingSizeZ = thingConfigVo:getSize()-- index所在点占据的格子范围包含的最小坐标和最大坐标(加减0.001是取巧做法,基本可以减少坐标点避免刚好落在tile边界上的概率)local thingMinX = thingX - thingSizeX / 2 + 0.001local thingMaxX = thingX + thingSizeX / 2 - 0.001local thingMinY = thingY - thingSizeY / 2 + 0.001local thingMaxY = thingY + thingSizeY / 2 - 0.001-- index所在点占据的格子范围包含的最小行列和最大行列local minCol = self:getColByPosX(dirType, thingMinX)local maxCol = self:getColByPosX(dirType, thingMaxX)local minRow = self:getRowByPosY(dirType, thingMinY)local maxRow = self:getRowByPosY(dirType, thingMaxY)-- 刷格子对应颜色local indexDic = self.mTileIndexDic[dirType]for _index, tile in pairs(indexDic) dolocal _row, _col = self:getRowColByIndex(dirType, _index)if((_row >= minRow and _row <= maxRow) or (_col >= minCol and _col <= maxCol))thenlocal renderer = tile:GetComponent(ty.MeshRenderer)gs.GoUtil.ChangeShader(renderer, 1, true)elselocal renderer = tile:GetComponent(ty.MeshRenderer)gs.GoUtil.ChangeShader(renderer, 1, false)endendelse-- 刷全部格子颜色至默认local indexDic = self.mTileIndexDic[dirType]for _index, tile in pairs(indexDic) dolocal _row, _col = self:getRowColByIndex(dirType, _index)local renderer = tile:GetComponent(ty.MeshRenderer)gs.GoUtil.ChangeShader(renderer, 1, false)endend
endfunction addTileToWall(self, dirType)if(not self.mTileIndexDic[dirType])thenself.mTileIndexDic[dirType] = {}endlocal tileSizeX, tileSizeY = room.RoomManager:getTileSize()local tileRowCount, tileColCount = self:getRowColNum(dirType)local sideDepth = room.RoomManager:getSideDepth()local index = 0for row = 1, tileRowCount dofor col = 1, tileColCount doindex = index + 1local tileX, tileY = self:getTilePos(dirType, index)local tile = AssetLoader.GetGO(UrlManager:getPrefabPath('ui/room/Scene_RoomTile.prefab'))tile.transform:SetParent(self.mTileNodeDic[dirType].transform, false)gs.TransQuick:Scale(tile.transform, tileSizeX, tileSizeY, sideDepth)gs.TransQuick:LPos(tile.transform, tileX, tileY, 0)self.mTileIndexDic[dirType][index] = tileendend
endfunction addThingToWall(self, dirType, thingId)if(not self.mThingDic[dirType])thenself.mThingDic[dirType] = {}endlocal thingConfigVo = room.RoomManager:getThingConfigVo(thingId)local thingSizeX, thingSizeY, thingSizeZ = thingConfigVo:getSize()local thing = AssetLoader.GetGO(UrlManager:getPrefabPath('ui/room/Scene_RoomThing.prefab'))gs.TransQuick:Scale(thing.transform, thingSizeX, thingSizeY, thingSizeZ)gs.TransQuick:LPos(thing.transform, 0, 0, thingSizeY / 2)thing.transform:SetParent(self.mThingNodeDic[dirType].transform, false)self.mThingDic[dirType][thingId] = thing
endfunction getRowColNum(self, dirType)local roomSizeX, roomSizeY, roomSizeZ = room.RoomManager:getRoomSize()local tileSizeX, tileSizeY = room.RoomManager:getTileSize()local col = 0local row = 0if(dirType == room.DIR_LEFT or dirType == room.DIR_RIGHT)thencol = math.floor(roomSizeZ / tileSizeX)row = math.floor(roomSizeY / tileSizeY)elseif(dirType == room.DIR_TOP or dirType == room.DIR_BOTTOM)thencol = math.floor(roomSizeX / tileSizeX)row = math.floor(roomSizeZ / tileSizeY)elseif(dirType == room.DIR_FRONT or dirType == room.DIR_BEHIND)thencol = math.floor(roomSizeX / tileSizeX)row = math.floor(roomSizeY / tileSizeY)endreturn row, col
endfunction getRowColByIndex(self, dirType, index)local tileRowCount, tileColCount = self:getRowColNum(dirType)local temp = index % tileColCountlocal col = temp == 0 and tileColCount or templocal temp = math.ceil(index / tileColCount)local row = temp == 0 and tileColCount or tempreturn row, col
endfunction getTileIndexByRowCol(self, dirType, row, col)local tileRowCount, tileColCount = self:getRowColNum(dirType)return (row - 1) * tileColCount + col
end-- 如果坐标处在tile边界,获取会不准,需自己提前判断
function getRowColByPos(self, dirType, localPosX, localPosY)local col = self:getColByPosX(dirType, localPosX)local row = self:getRowByPosY(dirType, localPosY)return row, col
end-- 如果坐标处在tile边界,获取会不准,需自己提前判断
function getColByPosX(self, dirType, localPosX)local roomSizeX, roomSizeY, roomSizeZ = room.RoomManager:getRoomSize()local tileSizeX, tileSizeY = room.RoomManager:getTileSize()local col = 0if(dirType == room.DIR_LEFT or dirType == room.DIR_RIGHT)thencol = math.ceil((localPosX  + roomSizeZ / 2) / tileSizeX)elseif(dirType == room.DIR_TOP or dirType == room.DIR_BOTTOM)thencol = math.ceil((localPosX  + roomSizeX / 2) / tileSizeX)elseif(dirType == room.DIR_FRONT or dirType == room.DIR_BEHIND)thencol = math.ceil((localPosX  + roomSizeX / 2) / tileSizeX)endreturn col
end-- 如果坐标处在tile边界,获取会不准,需自己提前判断
function getRowByPosY(self, dirType, localPosY)local roomSizeX, roomSizeY, roomSizeZ = room.RoomManager:getRoomSize()local tileSizeX, tileSizeY = room.RoomManager:getTileSize()local row = 0if(dirType == room.DIR_LEFT or dirType == room.DIR_RIGHT)thenrow = math.ceil((localPosY  + roomSizeY / 2) / tileSizeY)elseif(dirType == room.DIR_TOP or dirType == room.DIR_BOTTOM)thenrow = math.ceil((localPosY  + roomSizeZ / 2) / tileSizeY)elseif(dirType == room.DIR_FRONT or dirType == room.DIR_BEHIND)thenrow = math.ceil((localPosY  + roomSizeY / 2) / tileSizeY)endreturn row
endfunction getTilePos(self, dirType, index)local roomSizeX, roomSizeY, roomSizeZ = room.RoomManager:getRoomSize()local tileSizeX, tileSizeY = room.RoomManager:getTileSize()local halfTileSizeX = tileSizeX / 2local halfTileSizeY = tileSizeY / 2local startX = 0local startY = 0if(dirType == room.DIR_LEFT or dirType == room.DIR_RIGHT)thenstartX = (- roomSizeZ / 2) + halfTileSizeXstartY = (- roomSizeY / 2) + halfTileSizeYelseif(dirType == room.DIR_TOP or dirType == room.DIR_BOTTOM)thenstartX = (- roomSizeX / 2) + halfTileSizeXstartY = (- roomSizeZ / 2) + halfTileSizeYelseif(dirType == room.DIR_FRONT or dirType == room.DIR_BEHIND)thenstartX = (- roomSizeX / 2) + halfTileSizeXstartY = (- roomSizeY / 2) + halfTileSizeYendlocal row, col = self:getRowColByIndex(dirType, index)local tileX = startX + (col - 1) * tileSizeXlocal tileY = startY + (row - 1) * tileSizeYreturn tileX, tileY
endfunction getWallNodeName(self, gos, type)return gos["WALL_".. type]
endfunction getOriginalNodeName(self, gos, type)return gos["ORIGINAL_NODE_".. type]
endfunction getTileNodeName(self, gos, type)return gos["TILE_NODE_".. type]
endfunction getThingNodeName(self, gos, type)return gos["THING_NODE_".. type]
endfunction __closeRoomScene(self)self.mWallDic = nilself.mOriginalNodeDic = nilself.mThingNodeDic = nilself.mTileNodeDic = nilif(self.mTileIndexDic)thenfor dirType, indexDic in pairs(self.mTileIndexDic) dofor index, tile in pairs(indexDic) dogs.GameObject.Destroy(tile)endendself.mTileIndexDic = nilendif(self.mThingDic)thenfor dirType, indexDic in pairs(self.mThingDic) dofor index, tile in pairs(indexDic) dogs.GameObject.Destroy(tile)endendself.mThingDic = nilendgs.GameObject.Destroy(self.mRoomScene)self.mRoomScene = nil
endreturn _M

数据管理器

module("room.RoomManager", Class.impl(Manager))OPEN_ROOM_PANEL = "OPEN_ROOM_PANEL"--构造函数
function ctor(self)super.ctor(self)self:__init()
end-- Override 重置数据
function resetData(self)super.resetData(self)self:__init()
endfunction __init(self)
end-- 面的厚度(用于墙面厚度和格子厚度)
function getSideDepth(self)return 0.0001
end-- 获取格子大小
function getTileSize(self)local x, y = 1, 1return x, y
end-- 房间宽高厚均为格子宽高的公倍数
function getRoomSize(self)local x, y, z = 15, 5, 10return x, y, z
endfunction getThingConfigVo(self, id)local configVo = room.RoomThingConfigVo.new()configVo:setConfigId(id)configVo:setSize(1, 1, 1)configVo:setRotation(0, 0, 0)return configVo
endfunction getThingIdByIndex(self, index)local thingId = 1return thingId
endfunction setMainUICameraVisible(self, visible)if(not self.mMainUICamera)thenself.mMainUICamera = gs.GameObject.Find("[SCamera]")endself.mMainUICamera:SetActive(visible)if(not self.mSceneCamera)thenlocal childGods, childTrans = GoUtil.GetChildHash(gs.GameObject.Find("[CAMERAs]"))self.mSceneCamera = childGods["[SCENE_CAMERA]"]endif(visible)thenself.mSceneCamera:SetActive(false)gs.TransQuick:Pos(self.mSceneCamera.transform, -8, 4, -2)elseself.mSceneCamera:SetActive(true)gs.TransQuick:Pos(self.mSceneCamera.transform, 0, 500, 0)end
endfunction getSceneCamera(self)return self.mSceneCamera
endreturn _M

常量定义

room.DIR_TOP = "TOP"
room.DIR_BOTTOM = "BOTTOM"
room.DIR_FRONT = "FRONT"
room.DIR_BEHIND = "BEHIND"
room.DIR_LEFT = "LEFT"
room.DIR_RIGHT = "RIGHT"room.getDirType = function(str)if(string.find(str, room.DIR_TOP))thenreturn room.DIR_TOPelseif(string.find(str, room.DIR_BOTTOM))thenreturn room.DIR_BOTTOMelseif(string.find(str, room.DIR_FRONT))thenreturn room.DIR_FRONTelseif(string.find(str, room.DIR_BEHIND))thenreturn room.DIR_BEHINDelseif(string.find(str, room.DIR_LEFT))thenreturn room.DIR_LEFTelseif(string.find(str, room.DIR_RIGHT))thenreturn room.DIR_RIGHTendreturn ""
end

模拟的格子数据结构

module("room.RoomThingConfigVo", Class.impl())function setConfigId(self, cusConfigId)self.mConfigId = cusConfigId
endfunction getConfigId(self)return self.mConfigId or 0
endfunction setRotation(self, rotationX, rotationY, rotationZ)self.mRotationX = rotationXself.mRotationY = rotationYself.mRotationZ = rotationZ
endfunction getRotation(self)return self:getRotationX(), self:getRotationY(), self:getRotationZ()
endfunction getRotationX(self)local rotation = self.mRotationX or 0return rotation
endfunction getRotationY(self)local rotation = self.mRotationY or 0return rotation
endfunction getRotationZ(self)local rotation = self.mSizeZ or 0return rotation
endfunction setSize(self, sizeX, sizeY, sizeZ)self.mSizeX = sizeXself.mSizeY = sizeYself.mSizeZ = sizeZ
endfunction getSize(self)return self:getSizeX(), self:getSizeY(), self:getSizeZ()
endfunction getSizeX(self)local size = self.mSizeX or 0return size
endfunction getSizeY(self)local size = self.mSizeY or 0return size
endfunction getSizeZ(self)local size = self.mSizeZ or 0return size
endfunction getDirType(self)return room.DIR_BOTTOM
endfunction getIndex(self)return 0
endreturn _M

module("room.RoomThingVo", Class.impl(room.RoomThingConfigVo))function setId(self, cusId)self.mId = cusId
endfunction getId(self)return self.mId or 0
endreturn _M

 

这篇关于Unity 家居摆放系统设计 (一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1110547

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

软考系统规划与管理师考试证书含金量高吗?

2024年软考系统规划与管理师考试报名时间节点: 报名时间:2024年上半年软考将于3月中旬陆续开始报名 考试时间:上半年5月25日到28日,下半年11月9日到12日 分数线:所有科目成绩均须达到45分以上(包括45分)方可通过考试 成绩查询:可在“中国计算机技术职业资格网”上查询软考成绩 出成绩时间:预计在11月左右 证书领取时间:一般在考试成绩公布后3~4个月,各地领取时间有所不同

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

怎么让1台电脑共享给7人同时流畅设计

在当今的创意设计与数字内容生产领域,图形工作站以其强大的计算能力、专业的图形处理能力和稳定的系统性能,成为了众多设计师、动画师、视频编辑师等创意工作者的必备工具。 设计团队面临资源有限,比如只有一台高性能电脑时,如何高效地让七人同时流畅地进行设计工作,便成为了一个亟待解决的问题。 一、硬件升级与配置 1.高性能处理器(CPU):选择多核、高线程的处理器,例如Intel的至强系列或AMD的Ry

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能