npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@kimap/indoor-positioning-sdk

v1.0.0

Published

基于Three.js的室内定位地图SDK - Indoor Positioning Map SDK based on Three.js

Readme

Kimap Indoor Positioning SDK

🗺️ 专业的室内定位地图SDK - 模块化、功能完整、易于扩展

基于Three.js的企业级室内定位地图SDK,提供完整的室内定位、导航、分析功能。


🎉 最新更新

🎨 图形生成器(ShapeGenerator)⭐ v1.0.0

程序化图形生成,无需用户交互!

// 一行代码生成圆形
kimap.createCircle('id', { x: 10, y: 0, z: 10 }, 5, { color: 0xff0000 });

// 批量生成100个图形
for (let i = 0; i < 100; i++) {
  kimap.createRectangle(`area-${i}`, { x: i*2, y: 0, z: 0 }, 1, 1);
}

📖 详细文档: SHAPE_GENERATOR_GUIDE.md


✨ 核心特性

🎯 基础功能

  • 3D地图渲染 - 加载并渲染OBJ格式的室内地图模型
  • 坐标系管理 - 自定义零点坐标和坐标范围
  • 实时定位 - 显示和更新当前位置,支持脉冲动画效果
  • 位置标记 - 添加、移除和管理多个位置标记点
  • 点击交互 - 点击地图显示弹窗信息
  • 相机控制 - 支持旋转、缩放、平移等交互操作

🎨 高级功能

  • 交互式绘制 - 用户在地图上逐点绘制(测距、圆形、矩形、多边形)
  • 图形生成器 - 通过API直接生成图形,无需用户交互
  • 轨迹追踪 - 历史轨迹显示和实时路径跟踪
  • 区域选择 - 框选/圆选/多边形选择,返回区域内元素
  • 路径规划 - A*、Dijkstra算法自动路径规划
  • POI管理 - 兴趣点管理和搜索
  • 面积计算 - 多边形、圆形面积周长计算
  • 坐标转换 - 世界坐标、地图坐标、屏幕坐标互转
  • 自定义元素 - 支持图片精灵和HTML元素叠加

📦 模块化架构

sdk/
├── index.ts                    # 主入口(KimapSDK)
├── core/                       # 核心模块
│   └── MapCore.ts             # 地图初始化核心
├── modules/                    # 功能模块
│   ├── DrawingModule.ts       # ✏️ 交互式绘制(用户点击绘制)
│   ├── ShapeGenerator.ts      # 🎨 图形生成器(程序化生成)
│   ├── TrackingModule.ts      # 🚶 轨迹追踪
│   └── SelectionModule.ts     # 🎯 区域选择
├── utils/                      # 工具类
│   ├── CoordinateUtils.ts     # 📐 坐标转换
│   ├── GeometryCalculator.ts  # 📊 几何计算
│   ├── PathPlanner.ts         # 🗺️ 路径规划
│   └── VectorHelper.ts        # 🔄 向量转换工具
└── types/                      # 类型定义
    ├── enums.ts               # 枚举
    └── interfaces.ts          # 接口

安装

npm install three

快速开始

新功能: 图形生成器(ShapeGenerator)已上线!

除了让用户手动绘制,现在可以通过API直接生成图形:

// 直接生成圆形,无需用户点击
kimap.createCircle('fence-1', { x: 10, y: 0, z: 10 }, 5, { color: 0xff0000 });

详见: 第9节 - 图形生成器

1. 基础用法

import KimapSDK from './sdk/KimapSDK';
import * as THREE from 'three';

// 创建SDK实例
const kimap = new KimapSDK({
  container: document.getElementById('map-container')!,
  objUrl: '/path/to/your/model.obj',
  origin: { x: 0, y: 0, z: 0 },      // 零点坐标
  maxX: 50,                           // X轴最大坐标(米)
  maxY: 10,                           // Y轴最大坐标(高度,米)
  onPositionClick: (position, object) => {
    console.log('点击位置:', position);
    console.log('点击对象:', object);
  }
});

2. 添加位置标记

// 添加静态标记点
kimap.addLocationMarker({
  id: 'entrance',
  position: new THREE.Vector3(5, 0, 5),
  label: '入口',
  color: 0x4CAF50
});

kimap.addLocationMarker({
  id: 'exit',
  position: new THREE.Vector3(45, 0, 45),
  label: '出口',
  color: 0xF44336
});

3. 更新实时位置

// 模拟实时位置更新
let currentX = 0;
let currentZ = 0;

setInterval(() => {
  currentX += 0.1;
  currentZ += 0.05;
  
  const position = new THREE.Vector3(currentX, 0, currentZ);
  kimap.updateCurrentPosition(position);
}, 100);

4. 显示弹窗

// 基础用法:显示弹窗
kimap.showPopup({
  title: '当前位置',
  content: '您在一楼大厅',
  position: new THREE.Vector3(25, 0, 25)
});

// 人员移动时弹窗自动跟随(默认启用)
kimap.showPopup({
  title: '张三',
  content: '工号: 001',
  position: new THREE.Vector3(25, 0, 25)
}, true); // true表示跟随目标(默认值)

// 人员移动时更新弹窗位置
setInterval(() => {
  const newPosition = getUserPosition(); // 获取人员新位置
  kimap.updatePopupTarget(newPosition); // 更新弹窗跟随目标
}, 1000);

// 禁用跟随功能(固定位置弹窗)
kimap.showPopup({
  title: '提示',
  content: '请保持安静',
  position: new THREE.Vector3(25, 0, 25)
}, false); // false表示不跟随

// 手动关闭弹窗
setTimeout(() => {
  kimap.hidePopup();
}, 3000);

5. 坐标转换

// 地图坐标转世界坐标
const worldPos = kimap.mapToWorld(10, 0, 15);
console.log('世界坐标:', worldPos);

// 世界坐标转地图坐标
const mapPos = kimap.worldToMap(new THREE.Vector3(10, 0, 15));
console.log('地图坐标:', mapPos);

6. 绘制功能

import { DrawMode } from './sdk/types/enums';

// 开始测距
kimap.startDraw(DrawMode.MEASURE, {
  onDrawClick: (pos) => console.log('点击:', pos),
  onDrawComplete: (points) => {
    const distance = points[0].distanceTo(points[1]);
    console.log(`距离: ${distance.toFixed(2)}米`);
  }
});

// 绘制圆形
kimap.startDraw(DrawMode.CIRCLE);

// 绘制多边形(双击完成)
kimap.startDraw(DrawMode.POLYGON, {
  onDrawComplete: (points) => {
    console.log('多边形顶点:', points);
  }
});

// 清除所有绘制
kimap.clearDrawings();

7. 区域选择(返回内部元素)

// 框选矩形区域
const selection = kimap.selectByPolygon([
  new THREE.Vector3(10, 0, 10),
  new THREE.Vector3(30, 0, 10),
  new THREE.Vector3(30, 0, 30),
  new THREE.Vector3(10, 0, 30)
]);

console.log('选中元素:', selection.elements);
console.log('选中标记:', selection.markers);
console.log('选中POI:', selection.pois);

// 计算选择区域面积
const area = kimap.calculateSelectionArea(selection.area);
console.log(`面积: ${area.toFixed(2)} 平方米`);

// 高亮显示选中的元素
kimap.highlightSelection(selection, 0xffff00);

// 圆形选择
const circleSelection = kimap.selectByCircle(
  new THREE.Vector3(20, 0, 20),  // 圆心
  15                              // 半径
);

8. 路径规划

import { PathAlgorithm } from './sdk/types/enums';

// A*算法路径规划
const pathResult = kimap.planPath({
  start: new THREE.Vector3(0, 0, 0),
  end: new THREE.Vector3(50, 0, 50),
  algorithm: PathAlgorithm.ASTAR,
  obstacles: [
    // 障碍物(如墙体)
    [
      new THREE.Vector3(20, 0, 10),
      new THREE.Vector3(30, 0, 10),
      new THREE.Vector3(30, 0, 30),
      new THREE.Vector3(20, 0, 30)
    ]
  ]
});

console.log('路径长度:', pathResult.distance, '米');
console.log('预计时长:', pathResult.duration, '秒');

// 显示路径
kimap.addTrack({
  id: 'nav-path',
  points: pathResult.path.map(pos => ({
    position: pos,
    timestamp: Date.now()
  })),
  color: 0x00ff00,
  showMarkers: true
});

9. 图形生成器(程序化绘制)

// ⭐ 直接生成圆形(无需用户交互)
kimap.createCircle('fence-1', 
  { x: 10, y: 0, z: 10 },  // 圆心
  5,                        // 半径(米)
  { color: 0xff0000, opacity: 0.5 }
);

// 创建矩形区域
kimap.createRectangle('office-1',
  { x: 0, y: 0, z: 0 },    // 左下角
  10,                       // 宽度(米)
  8,                        // 深度(米)
  { color: 0x00ff00, opacity: 0.3 }
);

// 创建多边形
const points = [
  { x: 0, y: 0, z: 0 },
  { x: 10, y: 0, z: 0 },
  { x: 10, y: 0, z: 10 },
  { x: 0, y: 0, z: 10 }
];
kimap.createPolygon('area-1', points, { color: 0x0000ff });

// 创建线条
kimap.createLine('path-1', points, { 
  color: 0xff0000, 
  linewidth: 2,
  dashed: true 
});

// 创建3D盒子
kimap.createBox('box-1',
  { x: 15, y: 1, z: 15 },  // 中心位置
  2, 2, 2,                  // 宽、高、深
  { color: 0xffff00 }
);

// 管理图形
kimap.updateShape('fence-1', { color: 0x00ffff, opacity: 0.8 });
kimap.setShapeVisible('fence-1', false);  // 隐藏
kimap.removeShape('fence-1');             // 移除
kimap.clearAllShapes();                   // 清除所有

// 📘 详见: SHAPE_GENERATOR_GUIDE.md

10. POI管理

// 添加POI
kimap.addPOI({
  id: 'cafe-1',
  name: '星巴克',
  category: '餐饮',
  position: { x: 15, y: 0, z: 20 },
  tags: ['咖啡', '休闲'],
  data: { phone: '123-4567', hours: '8:00-22:00' }
});

// 搜索POI
const results = kimap.searchPOI('咖啡');
console.log('搜索结果:', results);

// 导航到POI
if (results.length > 0) {
  const path = kimap.planPath({
    start: currentPosition,
    end: results[0].position,
    algorithm: PathAlgorithm.ASTAR
  });
}

11. 清理资源

// 销毁SDK实例
kimap.destroy();

📚 详细文档

核心文档

绘制系统

坐标与转换

其他功能

API 文档

配置选项 (KimapConfig)

| 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | container | HTMLElement | ✅ | 地图容器DOM元素 | | objUrl | string | ✅ | OBJ模型文件URL | | origin | {x, y, z} | ✅ | 坐标系零点坐标 | | maxX | number | ✅ | X轴最大坐标(米) | | maxY | number | ✅ | Y轴最大坐标/高度(米) | | onPositionClick | function | ❌ | 点击位置回调函数 |

主要方法

addLocationMarker(marker: LocationMarker)

添加位置标记点。

参数:

  • marker.id (string) - 标记唯一ID
  • marker.position (Vector3) - 标记位置
  • marker.label (string, 可选) - 标记文字标签
  • marker.color (number, 可选) - 标记颜色(十六进制)

示例:

kimap.addLocationMarker({
  id: 'poi-001',
  position: { x: 25, y: 0, z: 25 },
  label: 'POI点',
  color: 0xFF5722
});

removeLocationMarker(id: string)

移除指定ID的位置标记。

示例:

kimap.removeLocationMarker('poi-001');

updateCurrentPosition(position: Vector3)

更新当前实时位置(带脉冲动画效果)。

示例:

kimap.updateCurrentPosition(new THREE.Vector3(15, 0, 25));

showPopup(info: PopupInfo, follow?: boolean)

显示信息弹窗。

参数:

  • info.title (string) - 弹窗标题
  • info.content (string) - 弹窗内容
  • info.position (Vector3) - 弹窗显示位置
  • follow (boolean, 可选) - 是否跟随目标位置,默认为 true

示例:

// 跟随模式(默认)
kimap.showPopup({
  title: '张三',
  content: '工号: 001<br>部门: 研发部',
  position: new THREE.Vector3(30, 0, 40)
}, true);

// 固定位置模式
kimap.showPopup({
  title: '会议室A',
  content: '3层东侧,可容纳20人',
  position: new THREE.Vector3(30, 0, 40)
}, false);

updatePopupTarget(position: Vector3D)

更新弹窗跟随的目标位置。用于人员移动时实时更新弹窗位置。

参数:

  • position (Vector3D) - 新的目标位置

示例:

// 显示人员弹窗
kimap.showPopup({
  title: '张三',
  content: '工号: 001',
  position: personPosition
});

// 人员移动时更新弹窗位置
setInterval(() => {
  const newPos = getPersonPosition();
  kimap.updatePopupTarget(newPos);
}, 100);

hidePopup()

隐藏当前弹窗并停止跟随。

mapToWorld(x, y, z)

将地图坐标转换为世界坐标。

返回: THREE.Vector3

worldToMap(position)

将世界坐标转换为地图坐标。

返回: {x: number, y: number, z: number}

getCoordinateSystem()

获取当前坐标系信息。

返回: {origin: Vector3, maxX: number, maxY: number}

destroy()

销毁SDK实例,释放资源。

完整示例

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Kimap SDK Demo</title>
  <style>
    #map-container {
      width: 100vw;
      height: 100vh;
      position: relative;
    }
    .control-panel {
      position: absolute;
      top: 20px;
      left: 20px;
      background: white;
      padding: 20px;
      border-radius: 8px;
      box-shadow: 0 4px 12px rgba(0,0,0,0.15);
      z-index: 100;
    }
  </style>
</head>
<body>
  <div id="map-container">
    <div class="control-panel">
      <h3>室内定位演示</h3>
      <button onclick="startTracking()">开始定位</button>
      <button onclick="stopTracking()">停止定位</button>
      <button onclick="addMarker()">添加标记</button>
    </div>
  </div>

  <script type="module">
    import KimapSDK from './sdk/KimapSDK.js';
    import * as THREE from 'three';

    // 初始化SDK
    const kimap = new KimapSDK({
      container: document.getElementById('map-container'),
      objUrl: './models/building.obj',
      origin: { x: 0, y: 0, z: 0 },
      maxX: 100,
      maxY: 15,
      onPositionClick: (position, object) => {
        if (object && object.userData.type === 'locationMarker') {
          kimap.showPopup({
            title: object.userData.label,
            content: `坐标: (${position.x.toFixed(2)}, ${position.z.toFixed(2)})`,
            position: position
          });
        }
      }
    });

    // 添加初始标记
    kimap.addLocationMarker({
      id: 'start',
      position: new THREE.Vector3(10, 0, 10),
      label: '起点',
      color: 0x4CAF50
    });

    kimap.addLocationMarker({
      id: 'end',
      position: new THREE.Vector3(90, 0, 90),
      label: '终点',
      color: 0xF44336
    });

    // 定位追踪
    let trackingInterval = null;
    let currentPos = { x: 10, z: 10 };

    window.startTracking = function() {
      if (trackingInterval) return;
      
      trackingInterval = setInterval(() => {
        // 模拟移动
        currentPos.x += Math.random() * 2 - 1;
        currentPos.z += Math.random() * 2 - 1;
        
        // 限制在范围内
        currentPos.x = Math.max(0, Math.min(100, currentPos.x));
        currentPos.z = Math.max(0, Math.min(100, currentPos.z));
        
        kimap.updateCurrentPosition(
          new THREE.Vector3(currentPos.x, 0, currentPos.z)
        );
      }, 100);
    };

    window.stopTracking = function() {
      if (trackingInterval) {
        clearInterval(trackingInterval);
        trackingInterval = null;
      }
    };

    window.addMarker = function() {
      const id = 'marker-' + Date.now();
      const x = Math.random() * 100;
      const z = Math.random() * 100;
      
      kimap.addLocationMarker({
        id: id,
        position: new THREE.Vector3(x, 0, z),
        label: `标记-${id.substr(-4)}`,
        color: 0x2196F3
      });
    };

    // 清理
    window.addEventListener('beforeunload', () => {
      kimap.destroy();
    });
  </script>
</body>
</html>

浏览器兼容性

  • Chrome 90+
  • Firefox 88+
  • Safari 14+
  • Edge 90+

需要支持WebGL 2.0。

许可证

MIT License

技术支持

如有问题请联系技术支持或查看源码注释。