当前位置: 首页>>代码示例>>Golang>>正文


Golang dvid.Point3d类代码示例

本文整理汇总了Golang中github.com/janelia-flyem/dvid/dvid.Point3d的典型用法代码示例。如果您正苦于以下问题:Golang Point3d类的具体用法?Golang Point3d怎么用?Golang Point3d使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。


在下文中一共展示了Point3d类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。

示例1: move

// Moves element position as well as relationships.
func (elems *Elements) move(from, to dvid.Point3d, deleteElement bool) (moved *Element, changed bool) {
	for i, elem := range *elems {
		if from.Equals(elem.Pos) {
			changed = true
			(*elems)[i].Pos = to
			moved = (*elems)[i].Copy()
			if deleteElement {
				(*elems)[i] = (*elems)[len(*elems)-1] // Delete without preserving order.
				*elems = (*elems)[:len(*elems)-1]
				break
			}
		}
	}

	// Check relationships for any moved points.
	for i, elem := range *elems {
		// Move any relationship with given pt.
		for j, r := range elem.Rels {
			if from.Equals(r.To) {
				r.To = to
				(*elems)[i].Rels[j] = r
				changed = true
			}
		}
	}
	return
}
开发者ID:tartavull,项目名称:dvid,代码行数:28,代码来源:annotation.go

示例2: GetGoogleSpec

// GetGoogleSpec returns a google-specific tile spec, which includes how the tile is positioned relative to
// scaled volume boundaries.  Not that the size parameter is the desired size and not what is required to fit
// within a scaled volume.
func (d *Data) GetGoogleSpec(scaling Scaling, plane dvid.DataShape, offset dvid.Point3d, size dvid.Point2d) (*GoogleTileSpec, error) {
	tile := new(GoogleTileSpec)
	tile.offset = offset

	// Convert combination of plane and size into 3d size.
	sizeWant, err := dvid.GetPoint3dFrom2d(plane, size, 1)
	if err != nil {
		return nil, err
	}
	tile.sizeWant = sizeWant

	// Determine which geometry is appropriate given the scaling and the shape/orientation
	tileSpec, err := GetTileSpec(scaling, plane)
	if err != nil {
		return nil, err
	}
	geomIndex, found := d.TileMap[*tileSpec]
	if !found {
		return nil, fmt.Errorf("Could not find scaled volume in %q for %s with scaling %d", d.DataName(), plane, scaling)
	}
	geom := d.Scales[geomIndex]
	tile.gi = geomIndex
	tile.channelCount = geom.ChannelCount
	tile.channelType = geom.ChannelType

	// Get the # bytes for each pixel
	switch geom.ChannelType {
	case "uint8":
		tile.bytesPerVoxel = 1
	case "float":
		tile.bytesPerVoxel = 4
	case "uint64":
		tile.bytesPerVoxel = 8
	default:
		return nil, fmt.Errorf("Unknown volume channel type in %s: %s", d.DataName(), geom.ChannelType)
	}

	// Check if the tile is completely outside the volume.
	volumeSize := geom.VolumeSize
	if offset[0] >= volumeSize[0] || offset[1] >= volumeSize[1] || offset[2] >= volumeSize[2] {
		tile.outside = true
		return tile, nil
	}

	// Check if the tile is on the edge and adjust size.
	var adjSize dvid.Point3d = sizeWant
	maxpt, err := offset.Expand2d(plane, size)
	for i := 0; i < 3; i++ {
		if maxpt[i] > volumeSize[i] {
			tile.edge = true
			adjSize[i] = volumeSize[i] - offset[i]
		}
	}
	tile.size = adjSize

	return tile, nil
}
开发者ID:hanslovsky,项目名称:dvid,代码行数:60,代码来源:googlevoxels.go

示例3: DeleteElement

func (d *Data) DeleteElement(ctx *datastore.VersionedCtx, pt dvid.Point3d) error {
	// Get from block key
	blockSize := d.blockSize()
	blockCoord := pt.Chunk(blockSize).(dvid.ChunkPoint3d)
	tk := NewBlockTKey(blockCoord)

	d.Lock()
	defer d.Unlock()

	elems, err := getElements(ctx, tk)
	if err != nil {
		return err
	}

	// Delete the given element
	deleted, _ := elems.delete(pt)
	if deleted == nil {
		return fmt.Errorf("Did not find element %s in datastore", pt)
	}

	// Put block key version without given element
	if err := putElements(ctx, tk, elems); err != nil {
		return err
	}

	// Alter all stored versions of this annotation using a batch.
	store, err := d.BackendStore()
	if err != nil {
		return err
	}
	batcher, ok := store.(storage.KeyValueBatcher)
	if !ok {
		return fmt.Errorf("Data type annotation requires batch-enabled store, which %q is not\n", store)
	}
	batch := batcher.NewBatch(ctx)

	// Delete in label key
	if err := d.deleteElementInLabel(ctx, batch, deleted.Pos); err != nil {
		return err
	}

	// Delete element in any tags
	if err := d.deleteElementInTags(ctx, batch, deleted.Pos, deleted.Tags); err != nil {
		return err
	}

	// Modify any reference in relationships
	if err := d.deleteElementInRelationships(ctx, batch, deleted.Pos, deleted.Rels); err != nil {
		return err
	}

	return batch.Commit()
}
开发者ID:tartavull,项目名称:dvid,代码行数:53,代码来源:annotation.go

示例4: newFloatVolume

func newFloatVolume(t *testing.T, offset, size dvid.Point3d) *testVolume {
	var buf bytes.Buffer
	for i := int64(0); i < size.Prod(); i++ {
		if err := binary.Write(&buf, binary.LittleEndian, float32(i)); err != nil {
			t.Fatalf("couldn't write to float volume: %v\n", err)
		}
	}
	return &testVolume{
		data:   buf.Bytes(),
		offset: offset,
		size:   size,
	}
}
开发者ID:janelia-flyem,项目名称:dvid,代码行数:13,代码来源:float32_test.go

示例5: deleteElementInLabel

func (d *Data) deleteElementInLabel(ctx *datastore.VersionedCtx, batch storage.Batch, pt dvid.Point3d) error {
	labelData := d.GetSyncedLabelblk()
	if labelData == nil {
		return nil // no synced labels
	}
	label, err := labelData.GetLabelAtPoint(ctx.VersionID(), pt)
	if err != nil {
		return err
	}
	tk := NewLabelTKey(label)
	elems, err := getElementsNR(ctx, tk)
	if err != nil {
		return fmt.Errorf("err getting elements for label %d: %v\n", label, err)
	}

	// Note all elements to be deleted.
	var delta DeltaModifyElements
	var toDel []int
	for i, elem := range elems {
		if pt.Equals(elem.Pos) {
			delta.Del = append(delta.Del, ElementPos{Label: label, Kind: elem.Kind, Pos: elem.Pos})
			toDel = append(toDel, i)
		}
	}
	if len(toDel) == 0 {
		return nil
	}

	// Delete them from high index to low index due while reusing slice.
	for i := len(toDel) - 1; i >= 0; i-- {
		d := toDel[i]
		elems[d] = elems[len(elems)-1]
		elems[len(elems)-1] = ElementNR{}
		elems = elems[:len(elems)-1]
	}

	// Put the modified list of elements
	if err := putBatchElements(batch, tk, elems); err != nil {
		return err
	}

	// Notify any subscribers of label annotation changes.
	evt := datastore.SyncEvent{Data: d.DataUUID(), Event: ModifyElementsEvent}
	msg := datastore.SyncMessage{Event: ModifyElementsEvent, Version: ctx.VersionID(), Delta: delta}
	if err := datastore.NotifySubscribers(evt, msg); err != nil {
		return err
	}
	return nil
}
开发者ID:tartavull,项目名称:dvid,代码行数:49,代码来源:annotation.go

示例6: deleteRel

func (elems *Elements) deleteRel(pt dvid.Point3d) (changed bool) {
	for i, elem := range *elems {
		// Remove any relationship with given pt.
		var todel []int
		for j, r := range elem.Rels {
			if pt.Equals(r.To) {
				todel = append(todel, j)
			}
		}
		if len(todel) > 0 {
			(*elems)[i].Rels = elem.Rels.delete(todel)
			changed = true
		}
	}
	return
}
开发者ID:tartavull,项目名称:dvid,代码行数:16,代码来源:annotation.go

示例7: delete

// Deletes element position as well as relationships that reference that element.
func (elems *ElementsNR) delete(pt dvid.Point3d) (deleted *ElementNR, changed bool) {
	// Delete any elements at point.
	var cut = -1
	for i, elem := range *elems {
		if pt.Equals(elem.Pos) {
			cut = i
			break
		}
	}
	if cut >= 0 {
		deleted = (*elems)[cut].Copy()
		changed = true
		(*elems)[cut] = (*elems)[len(*elems)-1] // Delete without preserving order.
		*elems = (*elems)[:len(*elems)-1]
	}
	return
}
开发者ID:tartavull,项目名称:dvid,代码行数:18,代码来源:annotation.go

示例8: moveElementInRelationships

// move all reference to given element point in the related points in different blocks.
// This is private method and assumes outer locking as well as current "from" block already being modified,
// including relationships.
func (d *Data) moveElementInRelationships(ctx *datastore.VersionedCtx, batch storage.Batch, from, to dvid.Point3d, rels []Relationship) error {
	blockSize := d.blockSize()
	fromBlockCoord := from.Chunk(blockSize).(dvid.ChunkPoint3d)

	// Get list of blocks with related points.
	relBlocks := make(map[dvid.IZYXString]struct{})
	for _, rel := range rels {
		blockCoord := rel.To.Chunk(blockSize).(dvid.ChunkPoint3d)
		if blockCoord.Equals(fromBlockCoord) {
			continue // relationships are almoved in from block
		}
		relBlocks[blockCoord.ToIZYXString()] = struct{}{}
	}

	// Alter the moved points in those related blocks.
	for izyxstr := range relBlocks {
		blockCoord, err := izyxstr.ToChunkPoint3d()
		if err != nil {
			return err
		}
		tk := NewBlockTKey(blockCoord)
		elems, err := getElements(ctx, tk)
		if err != nil {
			return err
		}

		// Move element in related element.
		if _, changed := elems.move(from, to, false); !changed {
			dvid.Errorf("Unable to find moved element %s in related element @ block %s:\n%v\n", from, blockCoord, elems)
			continue
		}

		// Save the block elements.
		if err := putBatchElements(batch, tk, elems); err != nil {
			return err
		}
	}
	return nil
}
开发者ID:tartavull,项目名称:dvid,代码行数:42,代码来源:annotation.go

示例9: deleteElementInTags

// delete all reference to given element point in the slice of tags.
// This is private method and assumes outer locking.
func (d *Data) deleteElementInTags(ctx *datastore.VersionedCtx, batch storage.Batch, pt dvid.Point3d, tags []Tag) error {
	for _, tag := range tags {
		// Get the elements in tag.
		tk, err := NewTagTKey(tag)
		if err != nil {
			return err
		}
		elems, err := getElementsNR(ctx, tk)
		if err != nil {
			return err
		}

		// Note all elements to be deleted.
		var toDel []int
		for i, elem := range elems {
			if pt.Equals(elem.Pos) {
				toDel = append(toDel, i)
			}
		}
		if len(toDel) == 0 {
			continue
		}

		// Delete them from high index to low index due while reusing slice.
		for i := len(toDel) - 1; i >= 0; i-- {
			d := toDel[i]
			elems[d] = elems[len(elems)-1]
			elems[len(elems)-1] = ElementNR{}
			elems = elems[:len(elems)-1]
		}

		// Save the tag.
		if err := putBatchElements(batch, tk, elems); err != nil {
			return err
		}
	}
	return nil
}
开发者ID:tartavull,项目名称:dvid,代码行数:40,代码来源:annotation.go

示例10: blockSize

// blockSize is either defined by any synced labelblk or by the default block size.
// Also checks to make sure that synced data is consistent.
func (d *Data) blockSize() dvid.Point3d {
	if d.cachedBlockSize != nil {
		return *d.cachedBlockSize
	}
	var bsize dvid.Point3d
	d.cachedBlockSize = &bsize
	if lb := d.GetSyncedLabelblk(); lb != nil {
		bsize = lb.BlockSize().(dvid.Point3d)
		return bsize
	}
	if lv := d.GetSyncedLabelvol(); lv != nil {
		if len(bsize) != 0 && !bsize.Equals(lv.BlockSize) {
			dvid.Errorf("annotations %q is synced to labelblk and labelvol with different block sizes!\n", d.DataName())
		} else {
			bsize = lv.BlockSize
			return bsize
		}
	}
	if len(bsize) != 0 {
		bsize = dvid.Point3d{DefaultBlockSize, DefaultBlockSize, DefaultBlockSize}
	}
	return bsize
}
开发者ID:tartavull,项目名称:dvid,代码行数:25,代码来源:annotation.go

示例11: TestSetMetadata

func TestSetMetadata(t *testing.T) {
	datastore.OpenTest()
	defer datastore.CloseTest()

	uuid, _ := initTestRepo()
	server.CreateTestInstance(t, uuid, "imagetile", "tiles", dvid.Config{})

	// Store Metadata
	url := fmt.Sprintf("%snode/%s/tiles/metadata", server.WebAPIPath, uuid)
	server.TestHTTP(t, "POST", url, bytes.NewBufferString(testMetadata))

	// Check instance really has it set.
	var metadata metadataJSON
	respStr := server.TestHTTP(t, "GET", url, nil)
	if err := json.Unmarshal(respStr, &metadata); err != nil {
		t.Fatalf("Couldn't parse JSON response to metadata request (%v):\n%s\n", err, respStr)
	}
	expectMin := dvid.Point3d{0, 0, 0}
	expectMax := dvid.Point3d{5, 5, 4}
	if !expectMin.Equals(metadata.MinTileCoord) {
		t.Errorf("Expected min tile coord %s, got %s\n", expectMin, metadata.MinTileCoord)
	}
	if !expectMax.Equals(metadata.MaxTileCoord) {
		t.Errorf("Expected max tile coord %s, got %s\n", expectMax, metadata.MaxTileCoord)
	}
	tileSpec, err := parseTileSpec(metadata.Levels)
	if err != nil {
		t.Errorf("Error parsing returned tile level spec:\n%v\n", metadata.Levels)
	}
	if len(tileSpec) != 4 {
		t.Errorf("Bad tile spec load: only %d elements != 4\n", len(tileSpec))
	}
	if tileSpec[2].Resolution.GetMax() != 40.0 {
		t.Errorf("Bad tile spec at level 2: %v\n", tileSpec[2])
	}
	if tileSpec[3].TileSize.Value(2) != 512 {
		t.Errorf("Bad tile spec at level 3: %v\n", tileSpec[3])
	}
}
开发者ID:tartavull,项目名称:dvid,代码行数:39,代码来源:imagetile_test.go

示例12: GetGoogleSubvolGeom

// GetGoogleSubvolGeom returns a google-specific voxel spec, which includes how the data is positioned relative to
// scaled volume boundaries.  Not that the size parameter is the desired size and not what is required to fit
// within a scaled volume.
func (d *Data) GetGoogleSubvolGeom(scaling Scaling, shape dvid.DataShape, offset dvid.Point3d, size dvid.Point) (*GoogleSubvolGeom, error) {
	gsg := new(GoogleSubvolGeom)
	if err := gsg.shape.FromShape(shape); err != nil {
		return nil, err
	}
	gsg.offset = offset

	// If 2d plane, convert combination of plane and size into 3d size.
	if size.NumDims() == 2 {
		size2d := size.(dvid.Point2d)
		sizeWant, err := dvid.GetPoint3dFrom2d(shape, size2d, 1)
		if err != nil {
			return nil, err
		}
		gsg.sizeWant = sizeWant
	} else {
		var ok bool
		gsg.sizeWant, ok = size.(dvid.Point3d)
		if !ok {
			return nil, fmt.Errorf("Can't convert %v to dvid.Point3d", size)
		}
	}

	// Determine which geometry is appropriate given the scaling and the shape/orientation
	tileSpec, err := GetGSpec(scaling, shape)
	if err != nil {
		return nil, err
	}
	geomIndex, found := d.GeomMap[*tileSpec]
	if !found {
		return nil, fmt.Errorf("Could not find scaled volume in %q for %s with scaling %d", d.DataName(), shape, scaling)
	}
	geom := d.Scales[geomIndex]
	gsg.gi = geomIndex
	gsg.channelCount = geom.ChannelCount
	gsg.channelType = geom.ChannelType

	// Get the # bytes for each pixel
	switch geom.ChannelType {
	case "UINT8":
		gsg.bytesPerVoxel = 1
	case "FLOAT":
		gsg.bytesPerVoxel = 4
	case "UINT64":
		gsg.bytesPerVoxel = 8
	default:
		return nil, fmt.Errorf("Unknown volume channel type in %s: %s", d.DataName(), geom.ChannelType)
	}

	// Check if the requested area is completely outside the volume.
	volumeSize := geom.VolumeSize
	if offset[0] >= volumeSize[0] || offset[1] >= volumeSize[1] || offset[2] >= volumeSize[2] {
		gsg.outside = true
		return gsg, nil
	}

	// Check if the requested shape is on the edge and adjust size.
	adjSize := gsg.sizeWant
	maxpt := offset.Add(adjSize)
	for i := uint8(0); i < 3; i++ {
		if maxpt.Value(i) > volumeSize[i] {
			gsg.edge = true
			adjSize[i] = volumeSize[i] - offset[i]
		}
	}
	gsg.size = adjSize

	return gsg, nil
}
开发者ID:tartavull,项目名称:dvid,代码行数:72,代码来源:googlevoxels.go

示例13: ConstructTiles

func (d *Data) ConstructTiles(uuidStr string, tileSpec TileSpec, request datastore.Request) error {
	config := request.Settings()
	uuid, versionID, err := datastore.MatchingUUID(uuidStr)
	if err != nil {
		return err
	}
	if err = datastore.AddToNodeLog(uuid, []string{request.Command.String()}); err != nil {
		return err
	}

	source, err := datastore.GetDataByUUID(uuid, d.Source)
	if err != nil {
		return err
	}
	src, ok := source.(*imageblk.Data)
	if !ok {
		return fmt.Errorf("Cannot construct imagetile for non-voxels data: %s", d.Source)
	}

	// Save the current tile specification
	d.Levels = tileSpec
	if err := datastore.SaveDataByUUID(uuid, d); err != nil {
		return err
	}

	// Get size of tile at lowest resolution.
	lastLevel := Scaling(len(tileSpec) - 1)
	loresSpec, found := tileSpec[lastLevel]
	if !found {
		return fmt.Errorf("Illegal tile spec.  Should have levels 0 to absent %d.", lastLevel)
	}
	var loresSize [3]float64
	for i := 0; i < 3; i++ {
		loresSize[i] = float64(loresSpec.Resolution[i]) * float64(DefaultTileSize[i])
	}
	loresMag := dvid.Point3d{1, 1, 1}
	for i := Scaling(0); i < lastLevel; i++ {
		levelMag := tileSpec[i].levelMag
		loresMag[0] *= levelMag[0]
		loresMag[1] *= levelMag[1]
		loresMag[2] *= levelMag[2]
	}

	// Get min and max points in terms of distance.
	var minPtDist, maxPtDist [3]float64
	for i := uint8(0); i < 3; i++ {
		minPtDist[i] = float64(src.MinPoint.Value(i)) * float64(src.VoxelSize[i])
		maxPtDist[i] = float64(src.MaxPoint.Value(i)) * float64(src.VoxelSize[i])
	}

	// Adjust min and max points for the tileable surface at lowest resolution.
	var minTiledPt, maxTiledPt dvid.Point3d
	for i := 0; i < 3; i++ {
		minInt, _ := math.Modf(minPtDist[i] / loresSize[i])
		maxInt, _ := math.Modf(maxPtDist[i] / loresSize[i])
		minTileCoord := int32(minInt)
		maxTileCoord := int32(maxInt)
		minTiledPt[i] = minTileCoord * DefaultTileSize[i] * loresMag[i]
		maxTiledPt[i] = (maxTileCoord+1)*DefaultTileSize[i]*loresMag[i] - 1
	}
	sizeVolume := maxTiledPt.Sub(minTiledPt).AddScalar(1)

	// Setup swappable ExtData buffers (the stitched slices) so we can be generating tiles
	// at same time we are reading and stitching them.
	var bufferLock [2]sync.Mutex
	var sliceBuffers [2]*imageblk.Voxels
	var bufferNum int

	// Get the planes we should tile.
	planes, err := config.GetShapes("planes", ";")
	if planes == nil {
		// If no planes are specified, construct imagetile for 3 orthogonal planes.
		planes = []dvid.DataShape{dvid.XY, dvid.XZ, dvid.YZ}
	}

	outF, err := d.putTileFunc(versionID)

	// sort the tile spec keys to iterate from highest to lowest resolution
	var sortedKeys []int
	for scaling, _ := range tileSpec {
		sortedKeys = append(sortedKeys, int(scaling))
	}
	sort.Ints(sortedKeys)

	for _, plane := range planes {
		timedLog := dvid.NewTimeLog()
		offset := minTiledPt.Duplicate()

		switch {

		case plane.Equals(dvid.XY):
			width, height, err := plane.GetSize2D(sizeVolume)
			if err != nil {
				return err
			}
			dvid.Debugf("Tiling XY image %d x %d pixels\n", width, height)
			for z := src.MinPoint.Value(2); z <= src.MaxPoint.Value(2); z++ {
				server.BlockOnInteractiveRequests("imagetile.ConstructTiles [xy]")

				sliceLog := dvid.NewTimeLog()
//.........这里部分代码省略.........
开发者ID:jwohlwend,项目名称:dvid,代码行数:101,代码来源:imagetile.go

示例14: MoveElement

func (d *Data) MoveElement(ctx *datastore.VersionedCtx, from, to dvid.Point3d) error {
	// Calc block keys
	blockSize := d.blockSize()
	fromCoord := from.Chunk(blockSize).(dvid.ChunkPoint3d)
	fromTk := NewBlockTKey(fromCoord)

	toCoord := to.Chunk(blockSize).(dvid.ChunkPoint3d)
	toTk := NewBlockTKey(toCoord)

	d.Lock()
	defer d.Unlock()

	// Alter all stored versions of this annotation using a batch.
	store, err := d.BackendStore()
	if err != nil {
		return err
	}
	batcher, ok := store.(storage.KeyValueBatcher)
	if !ok {
		return fmt.Errorf("Data type annotation requires batch-enabled store, which %q is not\n", store)
	}
	batch := batcher.NewBatch(ctx)

	// Handle from block
	fromElems, err := getElements(ctx, fromTk)
	if err != nil {
		return err
	}

	deleteElement := (bytes.Compare(fromTk, toTk) != 0)
	moved, _ := fromElems.move(from, to, deleteElement)
	if moved == nil {
		return fmt.Errorf("Did not find moved element %s in datastore", from)
	}
	dvid.Infof("moved element %v from %s -> %s\n", *moved, fromCoord, toCoord)

	if err := putBatchElements(batch, fromTk, fromElems); err != nil {
		return err
	}

	// If we've moved blocks, add the element in new place.
	if deleteElement {
		toElems, err := getElements(ctx, toTk)
		if err != nil {
			return err
		}
		toElems.add(Elements{*moved})
		dvid.Infof("new %s value: %v\n", toCoord, toElems)

		if err := putBatchElements(batch, toTk, toElems); err != nil {
			return err
		}
	}

	if err := batch.Commit(); err != nil {
		return err
	}
	batch = batcher.NewBatch(ctx)

	// Move in label key
	if err := d.moveElementInLabels(ctx, batch, from, to, moved.ElementNR); err != nil {
		return err
	}

	// Move element in any tags
	if err := d.moveElementInTags(ctx, batch, from, to, moved.Tags); err != nil {
		return err
	}

	// Move any reference in relationships
	if err := d.moveElementInRelationships(ctx, batch, from, to, moved.Rels); err != nil {
		return err
	}

	return batch.Commit()
}
开发者ID:tartavull,项目名称:dvid,代码行数:76,代码来源:annotation.go

示例15: VoxelWithin

func (i Immutable) VoxelWithin(p dvid.Point3d) bool {
	izyx := p.ToBlockIZYXString(i.blockSize)
	_, found := i.blocks[izyx]
	return found
}
开发者ID:tartavull,项目名称:dvid,代码行数:5,代码来源:roi.go


注:本文中的github.com/janelia-flyem/dvid/dvid.Point3d类示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。